package org.openlca.app.rcp.plugins;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.openlca.app.App;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
class PluginService {
public final static String BASE_URL = "http://www.openlca.org/files/openlca";
private final static Logger log = LoggerFactory
.getLogger(PluginService.class);
private final static JsonLoader jsonLoader = new JsonLoader();
private final static BundleService bundleService = new BundleService();
private final static Gson mapper = new Gson();
private final static String PLUGINS_DIRECTORY = "plugins";
public List<Plugin> getAvailablePlugins() {
String json = jsonLoader.getPluginsJson();
try {
List<Plugin> plugins = mapper.fromJson(json, new TypeToken<List<Plugin>>() {
}.getType());
for (Plugin plugin : plugins)
setStatus(plugin);
return plugins;
} catch (Exception e) {
log.error("Error parsing plugins json", e);
return Collections.emptyList();
}
}
private void setStatus(Plugin plugin) {
Bundle installed = Platform.getBundle(plugin.getSymbolicName());
if (installed == null)
return;
plugin.setInstalled(true);
plugin.setCurrentVersion(installed.getVersion().toString());
if (compare(plugin.getVersion(), installed.getVersion().toString()) > 0)
plugin.setUpdateable(true);
}
public void install(Plugin plugin) {
download(plugin);
uninstall(plugin, plugin.getVersion());
plugin.setRestartNecessary(true);
plugin.setInstalled(true);
plugin.setCurrentVersion(plugin.getVersion());
plugin.setUpdateable(false);
}
private boolean download(Plugin plugin) {
try {
URL url = getDownloadUrl(plugin);
Path temp = Files.createTempFile("olca-plugin", ".jar");
IOUtils.copy(url.openStream(), Files.newOutputStream(temp));
copyToDropins(temp, plugin.getFileName());
return true;
} catch (IOException e) {
log.error("Could not download plugin " + plugin.getDisplayName(), e);
return false;
}
}
private URL getDownloadUrl(Plugin plugin) {
try {
return new URL(BASE_URL + "/" + App.getVersion() + "/"
+ PLUGINS_DIRECTORY + "/" + plugin.getFileName());
} catch (MalformedURLException e) {
log.error("Error constructing download url", e);
return null;
}
}
public boolean copyLocalFile(Path from, Plugin plugin) {
if (plugin.isInstalled() && !plugin.isUpdateable())
return false;
boolean success = copyToDropins(from, plugin.getFileName());
if (!success)
return false;
plugin.setRestartNecessary(true);
if (plugin.isInstalled())
plugin.setUpdated(true);
else
plugin.setInstalled(true);
return true;
}
private boolean copyToDropins(Path from, String fileName) {
try {
File dropins = getDropinsDirectory();
Path to = new File(dropins, fileName).toPath();
IOUtils.copy(Files.newInputStream(from), Files.newOutputStream(to));
return true;
} catch (IOException e) {
log.error("Could not copy file", e);
return false;
}
}
private File getDropinsDirectory() {
Location installationLocation = Platform.getInstallLocation();
if (installationLocation == null)
return null;
File installation = new File(installationLocation.getURL().getFile());
if (!installation.exists())
return null;
File dropinsDirectory = new File(installation, "dropins");
if (!dropinsDirectory.exists())
dropinsDirectory.mkdirs();
return dropinsDirectory;
}
public void uninstall(Plugin plugin) {
uninstall(plugin, null);
plugin.setRestartNecessary(true);
plugin.setInstalled(false);
plugin.setCurrentVersion(null);
plugin.setUpdateable(false);
}
private void uninstall(Plugin plugin, String versionToKeep) {
Bundle[] bundles = bundleService.getBundles(plugin.getSymbolicName());
for (Bundle bundle : bundles)
if (bundle.getVersion() == null)
bundleService.delete(bundle);
else if (!bundle.getVersion().toString().equals(versionToKeep))
bundleService.delete(bundle);
}
private int compare(String v1, String v2) {
int[] version1 = parseVersion(v1);
int[] version2 = parseVersion(v2);
for (int i = 0; i < version1.length; i++) {
int result = Integer.compare(version1[i], version2[i]);
if (result != 0)
return result;
}
return 0;
}
private int[] parseVersion(String v) {
int[] versions = new int[3];
if (v == null)
return versions;
String[] splitted = v.split("\\.");
for (int i = 0; i < splitted.length && i < 3; i++)
versions[i] = Integer.parseInt(splitted[i]);
return versions;
}
public void update(Plugin plugin) {
install(plugin);
plugin.setUpdated(true);
}
}