/*
*
* * Copyright (C) 2015 CS SI
* *
* * This program is free software; you can redistribute it and/or modify it
* * under the terms of the GNU General Public License as published by the Free
* * Software Foundation; either version 3 of the License, or (at your option)
* * any later version.
* * This program is distributed in the hope that it will be useful, but WITHOUT
* * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* * more details.
* *
* * You should have received a copy of the GNU General Public License along
* * with this program; if not, see http://www.gnu.org/licenses/
*
*/
package org.esa.snap.utils;
import org.esa.snap.core.gpf.descriptor.ToolAdapterOperatorDescriptor;
import org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterIO;
import org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterOpSpi;
import org.esa.snap.core.gpf.operators.tooladapter.ToolAdapterRegistry;
import org.esa.snap.modules.ModulePackager;
import org.esa.snap.ui.tooladapter.actions.ToolAdapterActionRegistrar;
import org.openide.modules.ModuleInstall;
import org.openide.modules.Places;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.logging.Logger;
/**
* Tool Adapter module installer class for NetBeans.
* and menu entries.
*
* @author Cosmin Cara
*/
public class ModuleInstaller extends ModuleInstall {
private final static String descriptionKeyName = "OpenIDE-Module-Short-Description";
private final static Attributes.Name typeKey = new Attributes.Name("OpenIDE-Module-Type");
private final static FilenameFilter jarFilter = (dir, name) -> name.endsWith("jar");
private final Logger logger = Logger.getGlobal();
private final Path nbUserModulesPath = Paths.get(Places.getUserDirectory().getAbsolutePath(), "modules");
private final File userModulePath = ToolAdapterIO.getUserAdapterPath();
@Override
public void restored() {
String jarFile = getCurrentJarPath();
if (jarFile != null) {
File unpackLocation = processJarFile(new File(jarFile));
if (unpackLocation != null) {
registerAdapterAction(ToolAdapterIO.registerAdapter(unpackLocation));
} else {
logger.warning(String.format("Jar %s could not be unpacked. See previous exception.", jarFile));
}
} else {
Map<String, File> jarAdapters = getJarAdapters(nbUserModulesPath.toFile());
jarAdapters.keySet().stream().forEach(key -> {
File destination = new File(userModulePath, key);
processJarFile(destination);
});
synchronized (ToolAdapterIO.class) {
Collection<ToolAdapterOpSpi> toolAdapterOpSpis = ToolAdapterIO.searchAndRegisterAdapters();
toolAdapterOpSpis.forEach(this::registerAdapterAction);
}
}
}
@Override
public void uninstalled() {
logger.info("Uninstalling module");
String jarFile = getCurrentJarPath();
if (jarFile != null) {
try {
logger.info("Jar file: " + jarFile);
String alias = ModulePackager.getAdapterAlias(new File(jarFile));
logger.info("Alias: " + alias);
ToolAdapterOpSpi spi = ToolAdapterRegistry.INSTANCE.getOperatorMap().values()
.stream()
.filter(d -> alias.equals(d.getOperatorAlias()))
.findFirst().get();
if (spi != null) {
final ToolAdapterOperatorDescriptor descriptor = (ToolAdapterOperatorDescriptor) spi.getOperatorDescriptor();
//ToolAdapterActionRegistrar.removeOperatorMenu(descriptor);
ToolAdapterIO.removeOperator(descriptor);
}
} catch (IOException e) {
logger.warning(e.getMessage());
}
} else {
logger.info("No jar found");
}
}
private Map<String, File> getJarAdapters(File fromPath) {
Map<String, File> output = new HashMap<>();
File[] files = fromPath.listFiles(jarFilter);
if (files != null) {
logger.info(String.format("Found %s packed user module" + (files.length > 1 ? "s" : ""), String.valueOf(files.length)));
try {
for (File file : files) {
JarFile jarFile = new JarFile(file);
Manifest manifest = jarFile.getManifest();
Attributes manifestEntries = manifest.getMainAttributes();
if (manifestEntries.containsKey(typeKey) &&
"STA".equals(manifestEntries.getValue(typeKey.toString()))) {
logger.info(String.format("Module %s was detected as a STA module", file.getName()));
output.put(manifestEntries.getValue(descriptionKeyName), file);
}
}
} catch (Exception e) {
logger.severe(e.getMessage());
}
}
return output;
}
private String getCurrentJarPath() {
String path = null;
try {
URL url = this.getClass().getProtectionDomain().getCodeSource().getLocation();
JarURLConnection connection = (JarURLConnection) url.openConnection();
JarFile jarFile = connection.getJarFile();
path = jarFile.getName();
} catch (IOException e) {
logger.severe(e.getMessage());
}
return path;
}
private File processJarFile(File jarFile) {
String unpackPath = jarFile.getName().replace(".jar", "");
try {
unpackPath = ModulePackager.getAdapterAlias(jarFile);
} catch (IOException e) {
logger.warning(e.getMessage());
}
File destination = new File(userModulePath, unpackPath);
try{
if (!destination.exists()) {
ModulePackager.unpackAdapterJar(jarFile, destination);
} else {
File versionFile = new File(destination, "version.txt");
if (versionFile.exists()) {
String versionText = new String(Files.readAllBytes(Paths.get(versionFile.toURI()))); //FileUtils.readText(versionFile);
String jarVersion = ModulePackager.getAdapterVersion(jarFile);
if (jarVersion != null && !versionText.equals(jarVersion)) {
ModulePackager.unpackAdapterJar(jarFile, destination);
logger.info(String.format("The adapter with the name %s and version %s was replaced by version %s", unpackPath, versionText, jarVersion));
} else {
logger.info(String.format("An adapter with the name %s and version %s already exists", unpackPath, versionText));
}
} else {
ModulePackager.unpackAdapterJar(jarFile, destination);
}
}
} catch (Exception e) {
logger.severe(e.getMessage());
}
return destination;
}
private void registerAdapterAction(ToolAdapterOpSpi opSpi) {
ToolAdapterOperatorDescriptor operatorDescriptor = (ToolAdapterOperatorDescriptor) opSpi.getOperatorDescriptor();
if (operatorDescriptor != null) {
ToolAdapterActionRegistrar.registerOperatorMenu(operatorDescriptor);
}
}
}