From 04f525f7374b192c5b47efc974045789a1913421 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 13 Apr 2021 14:21:05 +0200 Subject: [PATCH 001/173] [javadoc] Fixed chmod method javadoc --- .../main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java index 5b96ad328..9f9d4af96 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java @@ -147,9 +147,10 @@ public static void deleteUser(String username, boolean removeHome) throws IOExce * Changes the access permissions of file system objects (files and * directories). * - * @param path The path of the file or directory. - * @param mode The mode to be set. + * @param sudo Sets if the command needs sudo. * @param recursive Sets if the command is recursive. + * @param mode The mode to be set. + * @param path The path of the file or directory. * @throws IOException if the permissions could not be changed. */ public static void chmod(boolean sudo, boolean recursive, String mode, String path) throws IOException { From deaab4ce545d2ff3af4fbf9ddb823e2af77f4a42 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 13 Apr 2021 14:28:46 +0200 Subject: [PATCH 002/173] Allows the Apps to be started from a non-root user account --- .../sm/impl/provider/AppsLauncherManager.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index 74cab5995..8959a781e 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -248,8 +248,39 @@ private void updateAppInArchive(final Long objId, final AppDetails definition, f interaction); } - protected boolean delete(Long objId) { - return this.deleteDef(objId); + return this.get(appId).getRunning(); + } + + protected String[] assembleCommand(final String workDir, final String appName, final String runAs, final String prefix, final String[] env) + { + ArrayList ret = new ArrayList<>(); + String trimmedAppName = appName.replaceAll("space-app-", ""); + if (osValidator.isWindows()) { + ret.add("cmd"); + ret.add("/c"); + StringBuilder str = new StringBuilder(); + str.append(prefix); + str.append(trimmedAppName); + str.append(".bat"); + ret.add(str.toString()); + } else { + if (runAs != null) { + ret.add("sudo"); + ret.add("su"); + ret.add("-"); + ret.add(runAs); + ret.add("-c"); + } else { + ret.add("/bin/sh"); + ret.add("-c"); + } + StringBuilder envString = new StringBuilder(); + for (String envVar : env) { + envString.append(envVar); + envString.append(" "); + } + + ret.add("cd " + workDir + ";" + envString.toString() + "./" + prefix + trimmedAppName + ".sh"); } protected boolean refreshAvailableAppsList(final URI providerURI) { From 8c6c45785dfd19a0205f62e012f988958c73402d Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 14 Apr 2021 10:39:55 +0200 Subject: [PATCH 003/173] Added a start banner for all NMF Apps with System information --- .../NanoSatMOConnectorImpl.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 030407055..25be6cf85 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -34,6 +34,7 @@ import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.misc.AppShutdownGuard; import esa.mo.helpertools.misc.Const; +import esa.mo.nmf.AppStorage; import esa.mo.nmf.MCRegistration; import esa.mo.nmf.MPRegistration; import esa.mo.nmf.MissionPlanningNMFAdapter; @@ -47,6 +48,7 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.com.COMService; @@ -73,6 +75,9 @@ * @author Cesar Coelho */ public class NanoSatMOConnectorImpl extends NMFProvider { + + private static final String SEPARATOR = "------------"; + private static final Logger LOGGER = Logger.getLogger(NanoSatMOConnectorImpl.class.getName()); private Long appDirectoryServiceId; @@ -91,6 +96,26 @@ public class NanoSatMOConnectorImpl extends NMFProvider { @Override public void init(final MonitorAndControlNMFAdapter mcAdapter) { super.startTime = System.currentTimeMillis(); + + Properties p = System.getProperties(); + StringBuilder java = new StringBuilder(); + java.append(p.getProperty("java.runtime.name", "?")); + java.append(" (version: "); + java.append(p.getProperty("java.runtime.version", "?")); + java.append(")"); + + StringBuilder os = new StringBuilder(); + os.append(p.getProperty("os.name", "?")); + os.append(" (version: "); + os.append(p.getProperty("os.version", "?")); + os.append(")"); + + System.out.println(SEPARATOR); + System.out.println("NanoSat MO Framework"); + System.out.println("OS: " + os.toString()); + System.out.println("Java: " + java.toString()); + System.out.println(SEPARATOR); + HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties ConnectionProvider.resetURILinks(); From 8ea92e960299a0bf7baa75fc051378a52e9f191c Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 14 Apr 2021 10:48:25 +0200 Subject: [PATCH 004/173] [nmf-app] Changed the location of the comArchive to the home directory --- .../mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 25be6cf85..fcd13699f 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -117,7 +117,7 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { System.out.println(SEPARATOR); HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties - ConnectionProvider.resetURILinks(); + ConnectionProvider.resetURILinksFile(); // Resets the providerURIs.properties file // Create provider name to be registerd on the Directory service... String appName = "Unknown"; @@ -130,6 +130,10 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; + String location = AppStorage.getAppNMFInternalDir() + File.separator + "comArchive.db"; + String url = "jdbc:sqlite:" + location; + System.setProperty("esa.nmf.archive.persistence.jdbc.url", url); + try { comServices.init(); comServices.initArchiveSync(); From 18e367fc0581114ae3b5ea826a6d27cbae9f2504 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 14 Apr 2021 14:57:33 +0200 Subject: [PATCH 005/173] Moved to the home directory, the comArchive.db and the provider.properties --- .../connections/ConnectionProvider.java | 36 ++++-- .../mo/helpertools/helpers/HelperMisc.java | 115 +++++++++++------- .../NanoSatMOConnectorImpl.java | 19 ++- .../mo/nmf/nmfpackage/HelperNMFPackage.java | 3 + 4 files changed, 112 insertions(+), 61 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java index 74d48b713..203c257ce 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java @@ -23,6 +23,7 @@ import esa.mo.helpertools.helpers.HelperConnections; import esa.mo.helpertools.helpers.HelperMisc; import java.io.BufferedWriter; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; @@ -120,8 +121,8 @@ public MALProvider startService(String serviceName, MALService malService, MALIn * @return MALProvider * @throws MALException On error. */ - public MALProvider startService(String serviceName, MALService malService, boolean isPublisher, - MALInteractionHandler handler) throws MALException { + public MALProvider startService(String serviceName, MALService malService, + boolean isPublisher, MALInteractionHandler handler) throws MALException { return startService(serviceName, malService, isPublisher, handler, null); } @@ -188,7 +189,12 @@ public MALProvider startService(String serviceName, MALService malService, boole serviceKey}); if (shouldInitUriFiles()) { - this.writeURIsOnFile(primaryConnectionDetails, serviceName, HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME); + String path = System.getProperty(HelperMisc.PROP_PROVIDERURIS_PATH, + HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME); + + this.writeURIsOnFile(primaryConnectionDetails, + serviceName, + path); } globalProvidersDetailsPrimary.add(serviceName, primaryConnectionDetails); @@ -221,12 +227,16 @@ public MALProvider startService(String serviceName, MALService malService, boole .getDomain(), serviceKey}); + if (shouldInitUriFiles()) { - this.writeURIsOnFile(secondaryConnectionDetails, serviceName, - HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME); + String pathSec = System.getProperty(HelperMisc.PROP_PROVIDERURIS_SEC_PATH, + HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME); + + this.writeURIsOnFile(secondaryConnectionDetails, + serviceName, + pathSec); } globalProvidersDetailsSecondary.add(serviceName, secondaryConnectionDetails); - secondaryMALServiceProvider = serviceProvider2; } @@ -298,21 +308,25 @@ public static boolean shouldInitUriFiles() { /** * Clears the URI links file if its generation is enabled */ - public static void resetURILinks() { + public static void resetURILinksFile() { globalProvidersDetailsPrimary.reset(); globalProvidersDetailsSecondary.reset(); if (shouldInitUriFiles()) { - try (BufferedWriter wrt = new BufferedWriter(new FileWriter(HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME, - false))) { + String path = System.getProperty(HelperMisc.PROP_PROVIDERURIS_PATH, + HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME); + + try (BufferedWriter wrt = new BufferedWriter(new FileWriter(path, false))) { } catch (IOException ex) { Logger.getLogger(ConnectionProvider.class.getName()).log(Level.WARNING, "Unable to reset URI information from properties file {0}", ex); } if (System.getProperty(HelperMisc.SECONDARY_PROTOCOL) != null) { - try (BufferedWriter wrt2 = new BufferedWriter(new FileWriter( - HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME, false))) { + String pathSec = System.getProperty(HelperMisc.PROP_PROVIDERURIS_SEC_PATH, + HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME); + + try (BufferedWriter wrt2 = new BufferedWriter(new FileWriter(pathSec, false))) { } catch (IOException ex) { Logger.getLogger(ConnectionProvider.class.getName()).log(Level.WARNING, "Unable to reset URI information from properties file {0}", ex); diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java index 592b0ec3b..91ff72a03 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java @@ -48,53 +48,74 @@ */ public class HelperMisc { - private static final Set LOADED_PROPERTIES = new TreeSet(); - - public static final String TRANSPORT_PROPERTIES_FILE = "transport.properties"; - public static final String PROVIDER_PROPERTIES_FILE = "provider.properties"; - public static final String CONSUMER_PROPERTIES_FILE = "consumer.properties"; - public static final String SHARED_BROKER_PROPERTIES = "sharedBroker.properties"; - public static final String SHARED_BROKER_URI = "sharedBrokerURI.properties"; - public static final String PROVIDER_URIS_PROPERTIES_FILENAME = "providerURIs.properties"; - public static final String PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME = "providerURIsSecondary.properties"; - public static final String PROPERTY_SHARED_BROKER_URI = "esa.mo.helpertools.connections.SharedBrokerURI"; - - // These are used by the Apps Launcher service - public final static String APP_VERSION = "helpertools.configurations.provider.app.version"; - public final static String APP_CATEGORY = "helpertools.configurations.provider.app.category"; - public final static String APP_COPYRIGHT = "helpertools.configurations.provider.app.copyright"; - public final static String APP_DESCRIPTION = "helpertools.configurations.provider.app.description"; - public final static String APP_USER = "helpertools.configurations.provider.app.user"; - - public static final String PROP_MO_APP_NAME = "helpertools.configurations.MOappName"; - public static final String PROP_DOMAIN = "helpertools.configurations.provider.Domain"; - public static final String PROP_NETWORK = "helpertools.configurations.Network"; - - // Fine-tunning Network properties (only works if the NETWORK is not set) - public static final String PROP_ORGANIZATION_NAME = "helpertools.configurations.OrganizationName"; - public static final String PROP_MISSION_NAME = "helpertools.configurations.MissionName"; - public static final String PROP_NETWORK_ZONE = "helpertools.configurations.NetworkZone"; - public static final String PROP_DEVICE_NAME = "helpertools.configurations.DeviceName"; - - public static final String PROP_GPS_POLL_RATE_MS = "helpertools.configurations.gpspollrate"; - public static final String PROP_GPS_POLLING_ACTIVE = "helpertools.configurations.pollgps"; - - private static final String PROP_TRANSPORT_ID = "helpertools.configurations.provider.transportfilepath"; - private static final String SETTINGS_PROPERTY = "esa.mo.nanosatmoframework.provider.settings"; - public static final String SECONDARY_PROTOCOL = "org.ccsds.moims.mo.mal.transport.secondary.protocol"; - - public static final String PROPERTY_APID_QUALIFIER = "org.ccsds.moims.mo.malspp.apidQualifier"; - public static final String PROPERTY_APID = "org.ccsds.moims.mo.malspp.apid"; - - public static final String PROP_INIT_URI_FILES = "helpertools.initurifiles"; - - public static final Identifier SESSION_NAME = new Identifier("LIVE"); - - /** - * Clears the list of loaded property files. - */ - public static void clearLoadedPropertiesList() { - LOADED_PROPERTIES.clear(); + private static final Set LOADED_PROPERTIES = new TreeSet(); + + public static final String TRANSPORT_PROPERTIES_FILE = "transport.properties"; + public static final String PROVIDER_PROPERTIES_FILE = "provider.properties"; + public static final String CONSUMER_PROPERTIES_FILE = "consumer.properties"; + public static final String SHARED_BROKER_PROPERTIES = "sharedBroker.properties"; + public static final String SHARED_BROKER_URI = "sharedBrokerURI.properties"; + public static final String PROVIDER_URIS_PROPERTIES_FILENAME = "providerURIs.properties"; + public static final String PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME = "providerURIsSecondary.properties"; + public static final String PROPERTY_SHARED_BROKER_URI = "esa.mo.helpertools.connections.SharedBrokerURI"; + + // These are used by the Apps Launcher service + public final static String APP_VERSION = "helpertools.configurations.provider.app.version"; + public final static String APP_CATEGORY = "helpertools.configurations.provider.app.category"; + public final static String APP_COPYRIGHT = "helpertools.configurations.provider.app.copyright"; + public final static String APP_DESCRIPTION = "helpertools.configurations.provider.app.description"; + public final static String APP_USER = "helpertools.configurations.provider.app.user"; + + public static final String PROP_MO_APP_NAME = "helpertools.configurations.MOappName"; + public static final String PROP_DOMAIN = "helpertools.configurations.provider.Domain"; + public static final String PROP_NETWORK = "helpertools.configurations.Network"; + public static final String PROP_WORK_DIR_STORAGE_MODE = "helpertools.configurations.workdirstorage"; + + // Fine-tunning Network properties (only works if the NETWORK is not set) + public static final String PROP_ORGANIZATION_NAME = "helpertools.configurations.OrganizationName"; + public static final String PROP_MISSION_NAME = "helpertools.configurations.MissionName"; + public static final String PROP_NETWORK_ZONE = "helpertools.configurations.NetworkZone"; + public static final String PROP_DEVICE_NAME = "helpertools.configurations.DeviceName"; + + public static final String PROP_GPS_POLL_RATE_MS = "helpertools.configurations.gpspollrate"; + public static final String PROP_GPS_POLLING_ACTIVE = "helpertools.configurations.pollgps"; + + private static final String PROP_TRANSPORT_ID = "helpertools.configurations.provider.transportfilepath"; + private static final String SETTINGS_PROPERTY = "esa.mo.nanosatmoframework.provider.settings"; + public static final String SECONDARY_PROTOCOL = "org.ccsds.moims.mo.mal.transport.secondary.protocol"; + public static final String PROP_PROVIDERURIS_PATH = "helpertools.configurations.provider.providerurispath"; + public static final String PROP_PROVIDERURIS_SEC_PATH = "helpertools.configurations.provider.providerurispathsecondary"; + + public static final String PROPERTY_APID_QUALIFIER = "org.ccsds.moims.mo.malspp.apidQualifier"; + public static final String PROPERTY_APID = "org.ccsds.moims.mo.malspp.apid"; + + public static final String PROP_INIT_URI_FILES = "helpertools.initurifiles"; + + public static final Identifier SESSION_NAME = new Identifier("LIVE"); + + /** + * Clears the list of loaded property files. + */ + public static void clearLoadedPropertiesList() { + LOADED_PROPERTIES.clear(); + } + + /** + * Loads in a property file and optionally searches for a contained property + * that contains the next file to load. + * + * @param configFile The name of the property file to load. May be null, in + * which case nothing is loaded. + * @param chainProperty The property name that contains the name of the next + * file to load. + * @return The loaded properties or an empty list if no file loaded. + */ + private static Properties loadProperties(final String configFile, final String chainProperty) { + Properties topProps = new Properties(); + + if (null != configFile) { + topProps = loadProperties(ClassLoader.getSystemClassLoader().getResource(configFile), + chainProperty); } /** diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index fcd13699f..fe3e31ea9 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -130,9 +130,22 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; - String location = AppStorage.getAppNMFInternalDir() + File.separator + "comArchive.db"; - String url = "jdbc:sqlite:" + location; - System.setProperty("esa.nmf.archive.persistence.jdbc.url", url); + // Check if the new Home dir mode property is enabled: + int mode = Integer.parseInt(System.getProperty(HelperMisc.PROP_WORK_DIR_STORAGE_MODE, "0")); + + if(mode >= 2){ + File nmfInternal = AppStorage.getAppNMFInternalDir(); + String location = nmfInternal + File.separator + "comArchive.db"; + String url = "jdbc:sqlite:" + location; + System.setProperty("esa.nmf.archive.persistence.jdbc.url", url); + + String urisPath = nmfInternal + File.separator + HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME; + System.setProperty(HelperMisc.PROP_PROVIDERURIS_PATH, urisPath); + String urisPath_sec = nmfInternal + File.separator + HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME; + System.setProperty(HelperMisc.PROP_PROVIDERURIS_SEC_PATH, urisPath_sec); + } + + ConnectionProvider.resetURILinksFile(); // Resets the providerURIs.properties file try { comServices.init(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index a9fadb73c..d737c3c3a 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -111,6 +111,9 @@ public static String generateProviderProperties(String runAs) throws IOException } str.append("\n"); + str.append("# Enables the new Home directory mode: \n"); + str.append(HelperMisc.PROP_WORK_DIR_STORAGE_MODE + "=" + "2\n"); + str.append("\n"); str.append("# NanoSat MO Framework transport configuration\n"); str.append("helpertools.configurations.provider.transportfilepath=transport.properties\n"); str.append("\n"); From cfac88702787dc349fb185ed4e034d43c00efe60 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 14 Apr 2021 15:28:39 +0200 Subject: [PATCH 006/173] Check if sudo is available before using it --- .../sm/impl/provider/AppsLauncherManager.java | 90 +++++++++++++------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index 8959a781e..fbaee9b52 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -32,6 +32,7 @@ import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.misc.Const; import esa.mo.sm.impl.util.OSValidator; +import esa.mo.sm.impl.util.ShellCommander; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -73,35 +74,29 @@ * * @author Cesar Coelho */ -public class AppsLauncherManager extends DefinitionsManager { +public class AppsLauncherManager extends DefinitionsManager +{ - private static final int APP_STOP_TIMEOUT = 15000; - private static final Logger LOGGER = Logger.getLogger(AppsLauncherManager.class.getName()); + private static final int APP_STOP_TIMEOUT = 15000; - private final OSValidator osValidator = new OSValidator(); + private static final Logger LOGGER = Logger.getLogger(AppsLauncherManager.class.getName()); - private static final String FOLDER_LOCATION_PROPERTY = "esa.mo.sm.impl.provider.appslauncher.FolderLocation"; - private static final String DEFAULT_APPS_FOLDER_PATH = ".." + File.separator + ".." + File.separator + "apps"; - /** - * Location of the apps folder, relative to the MO Supervisor - */ - private File appsFolderPath; - private final HashMap handlers = new HashMap<>(); - - private AtomicLong uniqueObjIdDef; // Counter + private final OSValidator osValidator = new OSValidator(); - public AppsLauncherManager(COMServicesProvider comServices) { - super(comServices); + private boolean sudoAvailable = false; + + private static final String FOLDER_LOCATION_PROPERTY + = "esa.mo.sm.impl.provider.appslauncher.FolderLocation"; - // If there is a property for that, then use it!! - if (System.getProperty(FOLDER_LOCATION_PROPERTY) != null) { - appsFolderPath = new File(System.getProperty(FOLDER_LOCATION_PROPERTY)); - } else { - LOGGER.log(Level.INFO, "Property not set: {0} \nUsing default apps directory: {1}", new Object[]{ - FOLDER_LOCATION_PROPERTY, - DEFAULT_APPS_FOLDER_PATH}); - appsFolderPath = new File(DEFAULT_APPS_FOLDER_PATH); - } + private static final String DEFAULT_APPS_FOLDER_PATH + = ".." + File.separator + ".." + File.separator + "apps"; + + /** + * Location of the apps folder, relative to the MO Supervisor + */ + private File appsFolderPath; + private final HashMap handlers + = new HashMap<>(); if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) != null && MALContextFactory.lookupArea( @@ -132,9 +127,46 @@ public Boolean compareName(Long objId, Identifier name) { return this.get(objId).getName().equals(name); } - @Override - public ElementList newDefinitionList() { - return new AppDetailsList(); + if(osValidator.isUnix()){ + ShellCommander shell = new ShellCommander(); + String out = shell.runCommandAndGetOutputMessageAndError("sudo --help"); + sudoAvailable = !out.contains("command not found"); + } + } + + protected AppDetailsList getAll() + { + return (AppDetailsList) this.getAllDefs(); + } + + @Override + public Boolean compareName(Long objId, Identifier name) + { + return this.get(objId).getName().equals(name); + } + + @Override + public ElementList newDefinitionList() + { + return new AppDetailsList(); + } + + public AppDetails get(Long input) + { + return (AppDetails) this.getDef(input); + } + + protected Long addApp(final AppDetails definition, final ObjectId source, final URI uri) + { + Long objId = null; + Long related = null; + + if (definition.getExtraInfo() != null) { + try { // Read the provider.properties of the app + objId = readAppObjectId(definition); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } } public AppDetails get(Long input) { @@ -265,7 +297,9 @@ protected String[] assembleCommand(final String workDir, final String appName, f ret.add(str.toString()); } else { if (runAs != null) { - ret.add("sudo"); + if(sudoAvailable){ + ret.add("sudo"); + } ret.add("su"); ret.add("-"); ret.add(runAs); From 6d07cbad94fc3ebd9f5f019e5b96dd289bcf5116 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 14 Apr 2021 15:39:38 +0200 Subject: [PATCH 007/173] Code cleanup. Some logs were returning nothing because of: {} --- .../mo/helpertools/helpers/HelperMisc.java | 199 +++++++++--------- 1 file changed, 98 insertions(+), 101 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java index 91ff72a03..3b0ac7a00 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java @@ -135,7 +135,27 @@ private static Properties loadProperties(final String configFile, final String c topProps = loadProperties(ClassLoader.getSystemClassLoader().getResource(configFile), chainProperty); } - return topProps; + System.setProperties(sysProps); + } + + /** + * Loads in a property file and optionally searches for a contained property + * that contains the next file to load. + * + * @param url The URL of the property file to load. May be null, in + * which case nothing is loaded. + * @param chainProperty The property name that contains the name of the next + * file to load. + * @return The loaded properties or an empty list if no file loaded. + * @throws java.lang.IllegalArgumentException If chainProperty == null. + */ + public static Properties loadProperties(final java.net.URL url, final String chainProperty) + throws IllegalArgumentException { + final Properties topProps = new Properties(); + if (chainProperty == null) { + throw new IllegalArgumentException( + "ChainProperty must not be null. " + + "Provide an empty String if you do not want to provide a chainProperty."); } /** @@ -149,11 +169,51 @@ public static void loadConsumerProperties() throws MalformedURLException, IOExce final Properties sysProps = System.getProperties(); final File file = new File(System.getProperty("consumer.properties", CONSUMER_PROPERTIES_FILE)); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "consumer.properties")); - } else { - throw new IOException("The file " + file.getName() + " does not exist."); - } + return topProps; + } + + /** + * Loads in a property file. + * + * @param path The path of the property file to load. + * @return The loaded properties or an empty list if no file loaded. + * @throws IOException The file could not be loaded. + * @throws IllegalArgumentException If path == null + */ + public static Properties loadProperties(final String path) + throws IOException, IllegalArgumentException { + if (path == null) { + throw new IllegalArgumentException("Filepath must not be null."); + } + final File file = new File(path); + final FileInputStream inputStream = new FileInputStream(file); + final Properties ret = new Properties(); + ret.load(inputStream); + inputStream.close(); + return ret; + } + + /** + * Loads the provider properties file + */ + public static void loadPropertiesFile() { + HelperMisc.loadPropertiesFile(false); + } + + /** + * Loads the provider properties file and the properties for the shared broker + * + * @param useSharedBroker Flag that determines if the properties in the + * SHARED_BROKER_PROPERTIES file will be read + */ + public static void loadPropertiesFile(Boolean useSharedBroker) { + // Were they loaded already? + String propAreLoaded = System.getProperty("PropertiesLoadedFlag"); + if (propAreLoaded != null) { + if (System.getProperty("PropertiesLoadedFlag").equals("true")) { + return; + } + } System.setProperties(sysProps); } @@ -177,41 +237,27 @@ public static Properties loadProperties(final java.net.URL url, final String cha "ChainProperty must not be null. Provide an empty String if you do not want to provide a chainProperty."); } - if (null != url) { - try { - final Properties myProps = new Properties(); - InputStream stream = url.openStream(); - myProps.load(stream); - stream.close(); - - final Properties subProps = loadProperties(myProps.getProperty(chainProperty), chainProperty); - - String loadingString = (LOADED_PROPERTIES.contains(url.toString())) ? "Reloading properties " + url - .toString() : "Loading properties " + url.toString(); - - Logger.getLogger(HelperMisc.class.getName()).log(Level.INFO, loadingString); - topProps.putAll(subProps); - topProps.putAll(myProps); - LOADED_PROPERTIES.add(url.toString()); - } catch (IOException ex) { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, "Failed to load properties " + url, ex); - } + if (providerFile != null) { + file = new File(providerFile); + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "provider.properties")); + } else { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "The file provider.properties does not exist on the path: {0}\n" + + "Is the application working directory configured properly?", providerFile); } return topProps; } - /** - * Loads in a property file. - * - * @param path The path of the property file to load. - * @return The loaded properties or an empty list if no file loaded. - * @throws IOException The file could not be loaded. - * @throws IllegalArgumentException If path == null - */ - public static Properties loadProperties(final String path) throws IOException, IllegalArgumentException { - if (path == null) { - throw new IllegalArgumentException("Filepath must not be null."); + if (settingsFile != null) { + file = new File(settingsFile); + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "settings.properties")); + } else { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "The file settings.properties does not exist on the path: {0}\n" + + "Is the application working directory configured properly?", settingsFile); } final File file = new File(path); final FileInputStream inputStream = new FileInputStream(file); @@ -244,70 +290,14 @@ public static void loadPropertiesFile(Boolean useSharedBroker) { } } - try { - final java.util.Properties sysProps = System.getProperties(); - - File file; - final String providerFile = System.getProperty("provider.properties", PROVIDER_PROPERTIES_FILE); - - if (providerFile != null) { - file = new File(providerFile); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "provider.properties")); - } else { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, - "The file provider.properties does not exist on the path: {}. Is the application working directory configured properly?", - providerFile); - } - } - - final String settingsFile = System.getProperty(SETTINGS_PROPERTY, "settings.properties"); - - if (settingsFile != null) { - file = new File(settingsFile); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "settings.properties")); - } else { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, - "The file settings.properties does not exist on the path: {}. Is the application working directory configured properly?", - settingsFile); - } - } - - String transport_file_path = TRANSPORT_PROPERTIES_FILE; - String trans_path_prop = System.getProperty(PROP_TRANSPORT_ID); - - if (trans_path_prop != null) { - transport_file_path = trans_path_prop; - } - - file = new File(System.getProperty("transport.properties", transport_file_path)); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "transport.properties")); - } else { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, - "The file transport.properties does not exist on the path: {}. Is the application working directory configured properly?", - transport_file_path); - } - - if (useSharedBroker) { - file = new File(System.getProperty("sharedBroker.properties", SHARED_BROKER_PROPERTIES)); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "sharedBroker.properties")); - } - - file = new File(System.getProperty("sharedBrokerURI.properties", SHARED_BROKER_URI)); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "sharedBrokerURI.properties")); - } - } - - System.setProperties(sysProps); - System.setProperty("PropertiesLoadedFlag", "true"); - - } catch (MalformedURLException ex) { - Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); - } + file = new File(System.getProperty("transport.properties", transport_file_path)); + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "transport.properties")); + } else { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "The file transport.properties does not exist on the path: {0}\n" + + "Is the application working directory configured properly?", transport_file_path); + } } @@ -416,7 +406,14 @@ public static Element elementList2element(ElementList obj) throws Exception { obj.getClass().getSimpleName()); } - return (Element) eleFact.createElement(); + if (eleFact == null) { + Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, + "The element could not be found in the MAL ElementFactory! " + + "The object type is: ''{0}''. " + + "Maybe the service Helper for this object was not initialized. " + + "Try initializing the Service Helper of this object.", + obj.getClass().getSimpleName()); + } } From bdddc81b35c063930d249873ce1a86b65449a335 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 15 Apr 2021 13:36:17 +0200 Subject: [PATCH 008/173] [nmfpack] During installation/uninstallation, replaced the use of useradd/userdel to adduser/deluser. --- .../mo/nmf/nmfpackage/LinuxUsersGroups.java | 179 +++++++++++++++--- .../mo/nmf/nmfpackage/NMFPackageManager.java | 14 +- 2 files changed, 159 insertions(+), 34 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java index 9f9d4af96..1be04c921 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java @@ -40,8 +40,8 @@ public class LinuxUsersGroups { private static final String MSG_NOT_FOUND = "The command was not found.\n"; /** - * Creates a new Linux user account and sets its respective password. The - * account can be created without a password by passing null into the + * Adds a new Linux user account and sets its respective password. The + * account can be created without a password by passing a null into the * password field argument. * * @param username The username of the user account. @@ -54,12 +54,11 @@ public class LinuxUsersGroups { * with no intervening whitespace. * @throws IOException if the user could not be created. */ - public static void createUser(String username, String password, boolean withGroup, String extraGroups) - throws IOException { + public static void useradd(String username, String password, + boolean withGroup, String extraGroups) throws IOException { ShellCommander shell = new ShellCommander(); final String defaultShell = "/bin/bash"; - //-------------------------------------------------------------------- // First, we need to check if the "useradd" exist String cmd1 = "useradd -h"; String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); @@ -69,7 +68,6 @@ public static void createUser(String username, String password, boolean withGrou throw new IOException(msg); } - //-------------------------------------------------------------------- // Second, we need to check if we have permissions to run the commands StringBuilder useradd = new StringBuilder(); useradd.append("sudo "); @@ -88,29 +86,118 @@ public static void createUser(String username, String password, boolean withGrou // Does the user account have a respective password? if (password != null) { - String cmd2 = "chpasswd -h"; - String out2 = shell.runCommandAndGetOutputMessageAndError(cmd2); + LinuxUsersGroups.chpasswd(username, password); + } + + // Change permissions on the home directories + LinuxUsersGroups.printCommandAndOutput(cmd3, out3); + } + + /** + * Adds a new Linux user account and sets its respective password. The + * account can be created without a password by passing a null into the + * password field argument. + * + * @param username The username of the user account. + * @param password The Password of the user account. Can be null if no + * password is to be defined. + * @param withGroup Defines if a group with the same name must also be + * created during the user account creation. + * @throws IOException if the user could not be created. + */ + public static void adduser(String username, String password, + boolean withGroup) throws IOException { + ShellCommander shell = new ShellCommander(); + final String defaultShell = "/bin/bash"; + + // First, we need to check if the "useradd" exist + String cmd1 = "adduser -h"; + String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); + + if (out1.contains(NOT_FOUND)) { + String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; + throw new IOException(msg); + } - if (out2.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd2 + "\n" + out2; - throw new IOException(msg); - } + // Second, we need to check if we have permissions to run the commands + StringBuilder useradd = new StringBuilder(); + useradd.append("sudo "); + useradd.append("adduser --system ") + .append("--shell ").append(defaultShell) + .append(withGroup ? " --group " : " ") + .append(username); + //String cmd = "useradd $user_nmf_admin -m -s /bin/bash --user-group"; + //String cmd = "useradd $user_nmf_admin --create-home --shell /bin/bash --user-group"; - StringBuilder chpasswd = new StringBuilder(); - chpasswd.append("echo ").append(username).append(":").append(password).append(" | ").append("chpasswd"); - // echo $user_nmf_admin:$user_nmf_admin_password | chpasswd + String cmd3 = useradd.toString(); + String out3 = shell.runCommandAndGetOutputMessageAndError(cmd3); - String cmd4 = chpasswd.toString(); - String out4 = shell.runCommandAndGetOutputMessageAndError(cmd4); + if (out3.contains(PERMISSION_DENIED)) { + String msg = "Permission denied! For command:\n >> " + cmd3 + "\n" + out3; + throw new IOException(msg); + } - if (out4.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd4 + "\n" + out4; - throw new IOException(msg); - } + // Does the user account have a respective password? + if (password != null) { + LinuxUsersGroups.chpasswd(username, password); } // Change permissions on the home directories - Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, " Running command: " + cmd3 + "\n" + out3); + LinuxUsersGroups.printCommandAndOutput(cmd3, out3); + } + + public static void addUserToGroup(String username, String extraGroup) throws IOException { + ShellCommander shell = new ShellCommander(); + + // First, we need to check if the "useradd" exist + String cmd1 = "adduser -h"; + String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); + + if (out1.contains(NOT_FOUND)) { + String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; + throw new IOException(msg); + } + + StringBuilder useradd = new StringBuilder(); + useradd.append("sudo "); + useradd.append("adduser ") + .append(username) + .append(" ") + .append(extraGroup); + + String cmd3 = useradd.toString(); + String out3 = shell.runCommandAndGetOutputMessageAndError(cmd3); + + if (out3.contains(PERMISSION_DENIED)) { + String msg = "Permission denied! For command:\n >> " + cmd3 + "\n" + out3; + throw new IOException(msg); + } + } + + public static void chpasswd(String username, String password) throws IOException { + ShellCommander shell = new ShellCommander(); + String cmd2 = "chpasswd -h"; + String out2 = shell.runCommandAndGetOutputMessageAndError(cmd2); + + if (out2.contains(NOT_FOUND)) { + String msg = MSG_NOT_FOUND + "\n >> " + cmd2 + "\n" + out2; + throw new IOException(msg); + } + + StringBuilder chpasswd = new StringBuilder(); + chpasswd.append("echo ") + .append(username).append(":").append(password) + .append(" | ") + .append("chpasswd"); + // echo $user_nmf_admin:$user_nmf_admin_password | chpasswd + + String cmd4 = chpasswd.toString(); + String out4 = shell.runCommandAndGetOutputMessageAndError(cmd4); + + if (out4.contains(PERMISSION_DENIED)) { + String msg = "Permission denied! For command:\n >> " + cmd4 + "\n" + out4; + throw new IOException(msg); + } } /** @@ -120,7 +207,7 @@ public static void createUser(String username, String password, boolean withGrou * @param removeHome Sets if the user's home directory will be removed. * @throws IOException if the user could not be deleted. */ - public static void deleteUser(String username, boolean removeHome) throws IOException { + public static void userdel(String username, boolean removeHome) throws IOException { StringBuilder cmd = new StringBuilder(); cmd.append("sudo "); cmd.append("userdel --force "); @@ -140,7 +227,37 @@ public static void deleteUser(String username, boolean removeHome) throws IOExce throw new IOException(msg); } - Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, " Running command: " + cmd + "\n" + out); + LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); + } + + /** + * Deletes an existing Linux user account. + * + * @param username The username of the user account. + * @param removeHome Sets if the user's home directory will be removed. + * @throws IOException if the user could not be deleted. + */ + public static void deluser(String username, boolean removeHome) throws IOException { + StringBuilder cmd = new StringBuilder(); + cmd.append("sudo "); + cmd.append("deluser "); + cmd.append(removeHome ? "--remove-home " : ""); + cmd.append(username); + + ShellCommander shell = new ShellCommander(); + String out = shell.runCommandAndGetOutputMessageAndError(cmd.toString()); + + if (out.contains(NOT_FOUND)) { + String msg = MSG_NOT_FOUND + "\n >> " + cmd + "\n" + out; + throw new IOException(msg); + } + + if (out.contains(PERMISSION_DENIED)) { + String msg = "Permission denied! For command:\n >> " + cmd + "\n" + out; + throw new IOException(msg); + } + + LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); } /** @@ -175,7 +292,7 @@ public static void chmod(boolean sudo, boolean recursive, String mode, String pa throw new IOException(msg); } - Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, " Running command: " + cmd + "\n" + out); + LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); } public static void chgrp(boolean recursive, String newGroup, String path) throws IOException { @@ -200,10 +317,10 @@ public static void chgrp(boolean recursive, String newGroup, String path) throws throw new IOException(msg); } - Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, " Running command: " + cmd + "\n" + out); + LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); } - static String findHomeDir(String username) throws IOException { + public static String findHomeDir(String username) throws IOException { StringBuilder cmd = new StringBuilder(); cmd.append("cat /etc/passwd | grep '"); cmd.append(username); @@ -222,9 +339,13 @@ static String findHomeDir(String username) throws IOException { throw new IOException(msg); } - Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, " Running command: " + cmd + "\n" + out); - + LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); return out; } + public static void printCommandAndOutput(String cmd, String out) { + Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, + "Executed command: " + cmd + "\n" + out); + } + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index fc45dfd6a..369f67f7f 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -129,8 +129,10 @@ public static void install(final String packageLocation, final File nmfDir) thro // Create the User for this App username = generateUsername(appName); boolean withGroup = true; - LinuxUsersGroups.createUser(username, password, withGroup, GROUP_NMF_APPS); - + LinuxUsersGroups.adduser(username, password, withGroup); + LinuxUsersGroups.addUserToGroup(username, GROUP_NMF_APPS); + //LinuxUsersGroups.useradd(username, password, withGroup, GROUP_NMF_APPS); + // Set the right Group and Permissions to the Home Directory // The owner remains with the app, the group is nmf-admin String homeDir = LinuxUsersGroups.findHomeDir(username); @@ -203,8 +205,9 @@ public static void install(final String packageLocation, final File nmfDir) thro System.console().printf(SEPARATOR); } - - public static void uninstall(final String packageLocation, final boolean keepUserData) throws IOException { + + public static void uninstall(final String packageLocation, + final boolean keepUserData) throws IOException { System.console().printf(SEPARATOR); // Get the Package to be uninstalled @@ -259,7 +262,8 @@ public static void uninstall(final String packageLocation, final boolean keepUse // --------------------------------------- // We need to delete the respective user here!! - LinuxUsersGroups.deleteUser(generateUsername(appName), true); + //LinuxUsersGroups.userdel(generateUsername(appName), true); + LinuxUsersGroups.deluser(generateUsername(appName), true); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully uninstalled from: " + packageLocation); From 5bf556a258d18ac8a8512ce6b83fe8fcbf993726 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 15 Apr 2021 14:45:32 +0200 Subject: [PATCH 009/173] [pictureprocessor] Code cleanup. Changed directory where the pictures are stored --- .../pictureprocessor/PictureProcessorApp.java | 30 +++++----- .../mo/PictureProcessorMCAdapter.java | 55 +++++++++++-------- .../mo/PictureReceivedAdapter.java | 31 ++++++----- .../process/LoggingExecuteResultHandler.java | 21 ++++--- .../process/PictureProcessingExecutor.java | 34 ++++++------ .../process/ProcessEventListener.java | 17 +++--- .../pictureprocessor/utils/FileUtils.java | 17 +++--- 7 files changed, 109 insertions(+), 96 deletions(-) diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java index 5fe4036e4..c5e688caa 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,13 +13,14 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor; +import esa.mo.nmf.AppStorage; import static esa.mo.nmf.apps.pictureprocessor.utils.FileUtils.createDirectoriesIfNotExist; import java.nio.file.Path; @@ -28,17 +28,19 @@ import esa.mo.nmf.apps.pictureprocessor.mo.PictureProcessorMCAdapter; import esa.mo.nmf.nanosatmoconnector.NanoSatMOConnectorImpl; +import java.io.File; /** - * An NMF App that that takes pictures and processes them through a python script + * An NMF App that that takes pictures and processes them through a python + * script */ public class PictureProcessorApp { public PictureProcessorApp() { - Path outputFolder = createDirectoriesIfNotExist(Paths.get("pictures")); - NanoSatMOConnectorImpl connector = new NanoSatMOConnectorImpl(); - + File userdata = AppStorage.getAppUserdataDir(); + String path = userdata + File.separator + "pictures"; + Path outputFolder = createDirectoriesIfNotExist(Paths.get(path)); connector.init(new PictureProcessorMCAdapter(connector, outputFolder)); } @@ -49,7 +51,7 @@ public PictureProcessorApp() { * @throws java.lang.Exception If there is an error */ public static void main(final String[] args) throws Exception { - new PictureProcessorApp(); + PictureProcessorApp pictureProcessorApp = new PictureProcessorApp(); } } diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java index af9207bf6..22387ab6d 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,9 +13,9 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor.mo; @@ -87,7 +86,6 @@ public void initialRegistrations(MCRegistration registration) { regiserActionTakeAndProcessPicture(actionDefs, actionNames); regiserActionDestroyProcess(actionDefs, actionNames); - // ---- registration.registerActions(actionNames, actionDefs); @@ -120,13 +118,17 @@ private void regiserActionTakeAndProcessPicture(ActionDefinitionDetailsList acti ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); { Byte rawType = Attribute._INTEGER_TYPE_SHORT_FORM; - arguments.add(new ArgumentDefinitionDetails(new Identifier("min process duration"), - "minimum picture processing duration", rawType, "seconds", null, null, null)); + arguments.add(new ArgumentDefinitionDetails( + new Identifier("min process duration"), + "minimum picture processing duration", + rawType, "seconds", null, null, null)); } { Byte rawType = Attribute._INTEGER_TYPE_SHORT_FORM; - arguments.add(new ArgumentDefinitionDetails(new Identifier("max process duration"), - "max picture processing duration", rawType, "seconds", null, null, null)); + arguments.add(new ArgumentDefinitionDetails( + new Identifier("max process duration"), + "max picture processing duration", + rawType, "seconds", null, null, null)); } actionDefs.add(new ActionDefinitionDetails( @@ -139,17 +141,21 @@ private void regiserActionDestroyProcess(ActionDefinitionDetailsList actionDefs, ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); { Byte rawType = Attribute._LONG_TYPE_SHORT_FORM; - arguments.add(new ArgumentDefinitionDetails(new Identifier("process id"), "process id", rawType, "", null, - null, null)); + arguments.add(new ArgumentDefinitionDetails( + new Identifier("process id"), + "process id", + rawType, "", null, null, null)); } - actionDefs.add(new ActionDefinitionDetails("Destryo a process", new UOctet((short) 0), new UShort(1), - arguments)); + actionDefs.add(new ActionDefinitionDetails( + "Destroy a process", + new UOctet((short) 0), + new UShort(1), + arguments)); actionNames.add(new Identifier(ACTION_DESTROY_PROCESS)); } private void takeAndProcessPicture(Long actionInstanceObjId, AttributeValueList attributeValues) { - int minProcessingDurationSeconds = getAs(attributeValues.get(0)); int maxProcessingDurationSeconds = getAs(attributeValues.get(1)); @@ -158,8 +164,12 @@ private void takeAndProcessPicture(Long actionInstanceObjId, AttributeValueList LOG.info("Process Max duration " + maxProcessingDurationSeconds); LOG.info("Process Request Id " + actionInstanceObjId); - PictureReceivedAdapter adapter = new PictureReceivedAdapter(this, actionInstanceObjId, outputFolder, - minProcessingDurationSeconds, maxProcessingDurationSeconds); + PictureReceivedAdapter adapter = new PictureReceivedAdapter( + this, + actionInstanceObjId, + outputFolder, + minProcessingDurationSeconds, + maxProcessingDurationSeconds); try { connector.getPlatformServices().getCameraService().takePicture(defaultCameraSettings(), adapter); processMap.put(actionInstanceObjId, adapter); @@ -184,7 +194,8 @@ private void destroyProcess(AttributeValueList attributeValues) { private void publishParameter(String id, int exitCode) { try { - connector.pushParameterValue("Process Request ID: " + id + " exitCode: " + exitCode, exitCode); + connector.pushParameterValue("Process Request ID: " + id + + " exitCode: " + exitCode, exitCode); } catch (NMFException e) { LOG.log(Level.SEVERE, "Failed to publish parameter", e); } diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureReceivedAdapter.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureReceivedAdapter.java index a86b258cb..4332cdf6f 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureReceivedAdapter.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureReceivedAdapter.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,9 +13,9 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor.mo; @@ -48,15 +47,19 @@ public class PictureReceivedAdapter extends CameraAdapter { private final Path outputFolder; private final PictureProcessingExecutor executor; - public PictureReceivedAdapter(ProcessEventListener processEventListener, Long processRequestId, Path outputFolder, - Integer minProcessDurationSeconds, Integer maxProcessDurationSeconds) { + public PictureReceivedAdapter(ProcessEventListener processEventListener, + Long processRequestId, Path outputFolder, + Integer minProcessDurationSeconds, Integer maxProcessDurationSeconds) { this.outputFolder = outputFolder; - this.executor = new PictureProcessingExecutor(processEventListener, processRequestId, minProcessDurationSeconds, - maxProcessDurationSeconds); + this.executor = new PictureProcessingExecutor( + processEventListener, processRequestId, + minProcessDurationSeconds, maxProcessDurationSeconds + ); } @Override - public void takePictureResponseReceived(MALMessageHeader msgHeader, Picture picture, java.util.Map qosProperties) { + public void takePictureResponseReceived(MALMessageHeader msgHeader, + Picture picture, java.util.Map qosProperties) { Path outputFile = outputFolder.resolve(pictureFileName()); if (!savePicture(outputFile, picture)) { diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/LoggingExecuteResultHandler.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/LoggingExecuteResultHandler.java index 9d25427de..da71cd170 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/LoggingExecuteResultHandler.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/LoggingExecuteResultHandler.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,9 +13,9 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor.process; @@ -37,8 +36,8 @@ public class LoggingExecuteResultHandler extends DefaultExecuteResultHandler { private final ProcessEventListener processEventListener; private final Long processRequestId; - public LoggingExecuteResultHandler(ProcessEventListener processEventListener, Long processRequestId, - OutputStream processOutputStream) { + public LoggingExecuteResultHandler(ProcessEventListener processEventListener, + Long processRequestId, OutputStream processOutputStream) { this.processOutputStream = processOutputStream; this.processEventListener = processEventListener; this.processRequestId = processRequestId; diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java index 4c7910309..91955a4f4 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,9 +13,9 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor.process; @@ -51,8 +50,8 @@ public class PictureProcessingExecutor { private final Long maxDurationMillis; private final Long processRequestId; - public PictureProcessingExecutor(ProcessEventListener processEventListener, Long processRequestId, - Integer minProcessDurationSeconds, Integer maxProcessDurationSeconds) { + public PictureProcessingExecutor(ProcessEventListener processEventListener, + Long processRequestId, Integer minProcessDurationSeconds, Integer maxProcessDurationSeconds) { this.maxDurationMillis = toWatchdogTimeout(maxProcessDurationSeconds); this.minDurationSeconds = toMinDuration(minProcessDurationSeconds); this.executor = new DefaultExecutor(); @@ -62,9 +61,8 @@ public PictureProcessingExecutor(ProcessEventListener processEventListener, Long } public boolean processPicture(Path picture) { - - LOG.info("Process " + processRequestId + " is starting. It will last at least " + minDurationSeconds + - "s and at most " + maxDurationMillis + "ms"); + LOG.info("Process " + processRequestId + " is starting. It will last at least " + + minDurationSeconds + "s and at most " + maxDurationMillis + "ms"); OutputStream outputStream = initLogStream(picture.getFileName()); if (outputStream == null) { @@ -80,8 +78,9 @@ public boolean processPicture(Path picture) { environment.put(ENV_PROCESS_DURATION, String.valueOf(minDurationSeconds)); try { - executor.execute(commandLine, environment, new LoggingExecuteResultHandler(processEventListener, - processRequestId, outputStream)); + executor.execute(commandLine, environment, + new LoggingExecuteResultHandler(processEventListener, processRequestId, outputStream) + ); } catch (IOException e) { LOG.log(Level.SEVERE, "Picture could not be processed", e); return false; @@ -115,7 +114,8 @@ private static OutputStream initLogStream(Path fileName) { } private static Path logFileName(Path processInputFile) { - return processInputFile.resolveSibling("picture-processor-" + processInputFile.toString() + ".log"); + String name = "picture-processor-" + processInputFile.toString() + ".log"; + return processInputFile.resolveSibling(name); } } diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/ProcessEventListener.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/ProcessEventListener.java index 77c92c340..6a8286c4e 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/ProcessEventListener.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/ProcessEventListener.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,9 +13,9 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor.process; diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/utils/FileUtils.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/utils/FileUtils.java index 9b7d13cc8..e55597a58 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/utils/FileUtils.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/utils/FileUtils.java @@ -1,11 +1,10 @@ -/* +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany * ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework + * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. @@ -14,9 +13,9 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.nmf.apps.pictureprocessor.utils; From 56b1b8a2d11f80d106b7b5377826e662dcc79c67 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 1 Jun 2021 14:20:05 +0200 Subject: [PATCH 010/173] [nmfpack] Support for additional libs or files. --- .../nmfpackage/GenerateNMFPackageMojo.java | 54 +++-- sdk/examples/space/picture-processor/pom.xml | 206 +++++++++--------- 2 files changed, 145 insertions(+), 115 deletions(-) diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 229fdd666..04aaa10ad 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -25,6 +25,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.maven.plugin.AbstractMojo; @@ -73,14 +74,16 @@ public class GenerateNMFPackageMojo extends AbstractMojo { /** * The set of libraries to be added to the .nmfpack */ - @Parameter(property = "generate-nmf-package.libs", required = true) - private String[] libs; + @Parameter(property = "generate-nmf-package.libs") + private List libs; /** * The set of privileges that an App can have */ public enum Privilege { - normal, admin, root + normal, + admin, + root } /** @@ -89,23 +92,33 @@ public enum Privilege { @Parameter(property = "generate-nmf-package.privilege", defaultValue = "normal") private Privilege privilege; + final ArrayList inputFiles = new ArrayList<>(); + final ArrayList locations = new ArrayList<>(); + String appPath = "no-path"; + @Override public void execute() throws MojoExecutionException { getLog().info("Generating NMF Package..."); - - ArrayList inputFiles = new ArrayList<>(); - ArrayList locations = new ArrayList<>(); + appPath = "apps" + SEPARATOR + name + SEPARATOR; try { File myAppFilename = this.findAppJarInTargetFolder(); inputFiles.add(myAppFilename.getAbsolutePath()); - locations.add("apps" + SEPARATOR + name + SEPARATOR + myAppFilename.getName()); + locations.add(appPath + myAppFilename.getName()); + + // Add the external libs or files + if (libs != null) { + for (String lib : libs) { + getLog().info(">> lib: " + lib); + addFileOrDirectory(lib, ""); + } + } } catch (IOException ex) { Logger.getLogger(GenerateNMFPackageMojo.class.getName()).log(Level.SEVERE, "The Jar file was not found!", ex); } - getLog().info("\n------------- NMF Package - Generator -------------\n"); + getLog().info("\n------------ NMF Package - Generator ------------\n"); getLog().info("Input values:"); getLog().info(">> name = " + name); getLog().info(">> version = " + version); @@ -115,13 +128,13 @@ public void execute() throws MojoExecutionException { getLog().info(">> maxHeap = " + maxHeap); if (mainClass == null) { - throw new MojoExecutionException("The mainClass property needs to be defined!\n" + - "Please use the tag inside the tag!\n"); + throw new MojoExecutionException("The mainClass property needs to be defined!\n" + + "Please use the tag inside the tag!\n"); } if ("${esa.nmf.version-qualifier}".equals(nmfVersion)) { - throw new MojoExecutionException("The nmfVersion property needs to be defined!\n" + - "Please use the tag inside the tag!\n"); + throw new MojoExecutionException("The nmfVersion property needs to be defined!\n" + + "Please use the tag inside the tag!\n"); } final Time time = new Time(System.currentTimeMillis()); @@ -130,11 +143,24 @@ public void execute() throws MojoExecutionException { // Package 1 NMFPackageDetails details = new NMFPackageDetails(name, version, timestamp, mainClass, maxHeap); NMFPackageCreator.nmfPackageCreator(details, inputFiles, locations, "target"); - // Additional libraries? } - private File findAppJarInTargetFolder() throws IOException { + private void addFileOrDirectory(String path, String nest) { + File f = new File(path); + + if (f.isDirectory()) { + nest += f.getName() + File.separator; + for (File n : f.listFiles()) { + addFileOrDirectory(n.getAbsolutePath(), nest); + } + } else { + inputFiles.add(f.getAbsolutePath()); + locations.add(appPath + nest + f.getName()); + } + } + + private File findAppJarInTargetFolder() throws IOException { File targetFolder = new File("target"); File[] fList = targetFolder.listFiles(); diff --git a/sdk/examples/space/picture-processor/pom.xml b/sdk/examples/space/picture-processor/pom.xml index f5285b3d6..58423035d 100644 --- a/sdk/examples/space/picture-processor/pom.xml +++ b/sdk/examples/space/picture-processor/pom.xml @@ -13,112 +13,116 @@ --> - 4.0.0 + 4.0.0 - - int.esa.nmf - parent - 2.1.0-SNAPSHOT - ../../../../parent/pom.xml - + + int.esa.nmf + parent + 2.1.0-SNAPSHOT + ../../../../parent/pom.xml + - int.esa.nmf.sdk.examples.space - picture-processor - jar + int.esa.nmf.sdk.examples.space + picture-processor + jar - ESA NMF SDK App Example - Picture Processor - A demo that takes pictures using Camera Platform Service and process them through a python script. - http://www.esa.int - - - ESA + ESA NMF SDK App Example - Picture Processor + A demo that takes pictures using Camera Platform Service and process them through a python script. http://www.esa.int - - - - - European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 - https://raw.github.com/esa/nanosat-mo-framework/master/LICENCE.md - repo - - - - - scm:git:git@github.com:esa/nanosat-mo-framework.git - scm:git:git@github.com:esa/nanosat-mo-framework.git - https://github.com/esa/nanosat-mo-framework - - - - GitHub - https://github.com/esa/nanosat-mo-framework/issues - - - - - Francesco Cantavenera - - - - esa.mo.nmf.apps.pictureprocessor.PictureProcessorApp - - - - - int.esa.nmf.core - nanosat-mo-connector - - - - - - - - org.apache.maven.plugins - maven-enforcer-plugin - - - org.apache.maven.plugins - maven-dependency-plugin - - - org.codehaus.mojo - build-helper-maven-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - org.apache.maven.plugins - maven-resources-plugin - - - + + ESA + http://www.esa.int + + + + + European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + https://raw.github.com/esa/nanosat-mo-framework/master/LICENCE.md + repo + + + + + scm:git:git@github.com:esa/nanosat-mo-framework.git + scm:git:git@github.com:esa/nanosat-mo-framework.git + https://github.com/esa/nanosat-mo-framework + + + + GitHub + https://github.com/esa/nanosat-mo-framework/issues + + + + + Francesco Cantavenera + + + + + esa.mo.nmf.apps.pictureprocessor.PictureProcessorApp + + + + + int.esa.nmf.core + nanosat-mo-connector + + - - - generate-nmf-package - + + + - - int.esa.nmf.core - nmf-package-maven-plugin - - - package - - generate-nmf-package - - - ${assembly.mainClass} - - - - + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.codehaus.mojo + build-helper-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-resources-plugin + - - - - \ No newline at end of file + + + + + generate-nmf-package + + + + int.esa.nmf.core + nmf-package-maven-plugin + + + package + + generate-nmf-package + + + ${assembly.mainClass} + + ${basedir}/src/main/resources/scripts/imageEditor + + + + + + + + + + From efb57d1f9962db89cb5575325a3448899c426030 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 31 Aug 2021 15:52:25 +0200 Subject: [PATCH 011/173] The App was using folders outside the restricted area. The code now follows the AppStorage class recommendations. --- .../apps/pictureprocessor/PictureProcessorApp.java | 5 +---- .../mo/PictureProcessorMCAdapter.java | 12 +++++++++--- .../process/PictureProcessingExecutor.java | 7 +++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java index c5e688caa..4cb66f65a 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java @@ -38,10 +38,7 @@ public class PictureProcessorApp { public PictureProcessorApp() { NanoSatMOConnectorImpl connector = new NanoSatMOConnectorImpl(); - File userdata = AppStorage.getAppUserdataDir(); - String path = userdata + File.separator + "pictures"; - Path outputFolder = createDirectoriesIfNotExist(Paths.get(path)); - connector.init(new PictureProcessorMCAdapter(connector, outputFolder)); + connector.init(new PictureProcessorMCAdapter(connector)); } /** diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java index 22387ab6d..58b814af7 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java @@ -21,6 +21,7 @@ package esa.mo.nmf.apps.pictureprocessor.mo; import static esa.mo.helpertools.helpers.HelperAttributes.attribute2JavaType; +import esa.mo.nmf.AppStorage; import java.io.IOException; import java.nio.file.Path; @@ -55,6 +56,9 @@ import esa.mo.nmf.NMFInterface; import esa.mo.nmf.NMFProvider; import esa.mo.nmf.apps.pictureprocessor.process.ProcessEventListener; +import static esa.mo.nmf.apps.pictureprocessor.utils.FileUtils.createDirectoriesIfNotExist; +import java.io.File; +import java.nio.file.Paths; /** * The adapter for the NMF App @@ -69,11 +73,9 @@ public class PictureProcessorMCAdapter extends MonitorAndControlNMFAdapter imple private final Map processMap = new ConcurrentHashMap<>(); private final NMFInterface connector; - private final Path outputFolder; - public PictureProcessorMCAdapter(NMFProvider connector, Path outputFolder) { + public PictureProcessorMCAdapter(NMFProvider connector) { this.connector = connector; - this.outputFolder = outputFolder; } @Override @@ -164,6 +166,10 @@ private void takeAndProcessPicture(Long actionInstanceObjId, AttributeValueList LOG.info("Process Max duration " + maxProcessingDurationSeconds); LOG.info("Process Request Id " + actionInstanceObjId); + File userdata = AppStorage.getAppUserdataDir(); + String path = userdata + File.separator + "pictures"; + Path outputFolder = createDirectoriesIfNotExist(Paths.get(path)); + PictureReceivedAdapter adapter = new PictureReceivedAdapter( this, actionInstanceObjId, diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java index 91955a4f4..07fc20f50 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/process/PictureProcessingExecutor.java @@ -20,9 +20,11 @@ */ package esa.mo.nmf.apps.pictureprocessor.process; +import esa.mo.nmf.AppStorage; import static esa.mo.nmf.apps.pictureprocessor.utils.FileUtils.createDirectoriesIfNotExist; import static esa.mo.nmf.apps.pictureprocessor.utils.FileUtils.newOutpuStreamSafe; import static esa.mo.nmf.apps.pictureprocessor.utils.FileUtils.stripFileNameExtension; +import java.io.File; import java.io.IOException; import java.io.OutputStream; @@ -108,8 +110,9 @@ private static int toMinDuration(Integer minDurationMillis) { } private static OutputStream initLogStream(Path fileName) { - Path logFileName = createDirectoriesIfNotExist(Paths.get(LOG_PATH)).resolve(logFileName(stripFileNameExtension( - fileName))); + String path = AppStorage.getAppUserdataDir() + File.separator + LOG_PATH; + Path logFileName = createDirectoriesIfNotExist(Paths.get(path)) + .resolve(logFileName(stripFileNameExtension(fileName))); return newOutpuStreamSafe(logFileName); } From eb098d2ce67f6be3d08f79a76bd1516e3e1c5888 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 13 Sep 2021 14:44:57 +0200 Subject: [PATCH 012/173] Improved the startup banner --- .../src/main/java/esa/mo/nmf/NMFProvider.java | 51 +++++++++++++++++-- .../NanoSatMOConnectorImpl.java | 22 +------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java index 950beecb2..2596cd1ae 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java @@ -52,6 +52,7 @@ import esa.mo.reconfigurable.service.ReconfigurableService; import esa.mo.reconfigurable.service.ConfigurationChangeListener; import esa.mo.reconfigurable.provider.ReconfigurableProvider; +import java.util.Properties; /** * The generic NMF Provider. Includes a Heartbeat service and a Directory @@ -267,12 +268,15 @@ public final URI readCentralDirectoryServiceURI() { if (System.getProperty(Const.CENTRAL_DIRECTORY_URI_PROPERTY) != null) { return new URI(System.getProperty(Const.CENTRAL_DIRECTORY_URI_PROPERTY)); } else { - String path = ".." + File.separator + ".." + File.separator + Const.NANOSAT_MO_SUPERVISOR_NAME + - File.separator + Const.FILENAME_CENTRAL_DIRECTORY_SERVICE; + String path = ".." + + File.separator + ".." + + File.separator + + Const.NANOSAT_MO_SUPERVISOR_NAME + + File.separator + + Const.FILENAME_CENTRAL_DIRECTORY_SERVICE; Logger.getLogger(NMFProvider.class.getName()).log(Level.INFO, - "Property {0} not set. Falling back to reading from {1}.", new Object[]{ - Const.CENTRAL_DIRECTORY_URI_PROPERTY, - path}); + "Property {0} not set. Falling back to reading from {1}.", new Object[]{ + Const.CENTRAL_DIRECTORY_URI_PROPERTY, path}); File file = new File(path); // Select the file that we want to read from @@ -311,4 +315,41 @@ public final void writeCentralDirectoryServiceURI(final String centralDirectoryU } } + /** + * Generates a starting Banner that can be used for NMF Providers. + * + * @return The banner. + */ + protected String generateStartBanner() { + Properties p = System.getProperties(); + final String SEPARATOR = "------------\n"; + + StringBuilder banner = new StringBuilder(); + banner.append("\n"); + banner.append(SEPARATOR); + banner.append("NanoSat MO Framework\n"); + + // OS version + banner.append("OS: "); + banner.append(p.getProperty("os.name", "?")); + banner.append(" (version: "); + banner.append(p.getProperty("os.version", "?")); + banner.append(")\n"); + + // User + banner.append("Running as User: "); + banner.append(p.getProperty("user.name", "?")); + banner.append("\n"); + + // Java version + banner.append("Java: "); + banner.append(p.getProperty("java.runtime.name", "?")); + banner.append(" (version: "); + banner.append(p.getProperty("java.runtime.version", "?")); + banner.append(")\n"); + + banner.append(SEPARATOR); + return banner.toString(); + } + } diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index fe3e31ea9..efa65384a 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -76,8 +76,6 @@ */ public class NanoSatMOConnectorImpl extends NMFProvider { - private static final String SEPARATOR = "------------"; - private static final Logger LOGGER = Logger.getLogger(NanoSatMOConnectorImpl.class.getName()); private Long appDirectoryServiceId; @@ -96,25 +94,7 @@ public class NanoSatMOConnectorImpl extends NMFProvider { @Override public void init(final MonitorAndControlNMFAdapter mcAdapter) { super.startTime = System.currentTimeMillis(); - - Properties p = System.getProperties(); - StringBuilder java = new StringBuilder(); - java.append(p.getProperty("java.runtime.name", "?")); - java.append(" (version: "); - java.append(p.getProperty("java.runtime.version", "?")); - java.append(")"); - - StringBuilder os = new StringBuilder(); - os.append(p.getProperty("os.name", "?")); - os.append(" (version: "); - os.append(p.getProperty("os.version", "?")); - os.append(")"); - - System.out.println(SEPARATOR); - System.out.println("NanoSat MO Framework"); - System.out.println("OS: " + os.toString()); - System.out.println("Java: " + java.toString()); - System.out.println(SEPARATOR); + System.out.println(this.generateStartBanner()); HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties ConnectionProvider.resetURILinksFile(); // Resets the providerURIs.properties file From 911e3d229bebbe28377f946eaf477d7d719468e7 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 13 Sep 2021 14:46:52 +0200 Subject: [PATCH 013/173] New constructor with ConnectionConsumer. Cleanup of imports --- .../apps/pictureprocessor/PictureProcessorApp.java | 7 ------- .../java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java | 11 +++++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java index 4cb66f65a..e75b37dee 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/PictureProcessorApp.java @@ -20,15 +20,8 @@ */ package esa.mo.nmf.apps.pictureprocessor; -import esa.mo.nmf.AppStorage; -import static esa.mo.nmf.apps.pictureprocessor.utils.FileUtils.createDirectoriesIfNotExist; - -import java.nio.file.Path; -import java.nio.file.Paths; - import esa.mo.nmf.apps.pictureprocessor.mo.PictureProcessorMCAdapter; import esa.mo.nmf.nanosatmoconnector.NanoSatMOConnectorImpl; -import java.io.File; /** * An NMF App that that takes pictures and processes them through a python diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java index 6e855208a..ade146c9a 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java @@ -22,6 +22,7 @@ import esa.mo.helpertools.clock.PlatformClockCallback; import esa.mo.helpertools.clock.SystemClock; +import esa.mo.helpertools.connections.ConnectionConsumer; import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.TaskScheduler; import esa.mo.nmf.ctt.services.com.ArchiveConsumerManagerPanel; @@ -82,6 +83,16 @@ public ProviderTabPanel(final ProviderSummary provider, Blob authenticationId, S initComponents(); } + /** + * Creates a new tab for a Provider and populates it. + * + * @param connection + */ + public ProviderTabPanel(final ConnectionConsumer connection) { + services = new GroundMOAdapterImpl(connection); + initComponents(); + } + public GroundMOAdapterImpl getServices() { return this.services; } From 8508b09e84bb63d3974f15132a5d4a969d0d5305 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 13 Sep 2021 14:50:09 +0200 Subject: [PATCH 014/173] The env variables were not being passed on Linux machines. This was affecting Phi-Sat-2 setup when starting Apps --- .../sm/impl/provider/AppsLauncherManager.java | 234 ++++++++++-------- 1 file changed, 134 insertions(+), 100 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index fbaee9b52..b12ca606e 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -316,33 +316,36 @@ protected String[] assembleCommand(final String workDir, final String appName, f ret.add("cd " + workDir + ";" + envString.toString() + "./" + prefix + trimmedAppName + ".sh"); } + return ret.toArray(new String[0]); + } + protected String[] assembleAppStopCommand(final String workDir, final String appName, final String runAs, final String[] env) + { + return assembleCommand(workDir, appName, runAs, "stop_", env); + } - protected boolean refreshAvailableAppsList(final URI providerURI) { - // Go to all the "apps folder" and check if there are new folders - // get all the files from a directory - File[] fList = appsFolderPath.listFiles(); - - if (fList == null) { - LOGGER.log(Level.SEVERE, "The directory could not be found: {0} (full path: {1})", new Object[]{ - appsFolderPath - .toString(), - appsFolderPath - .getAbsolutePath()}); - - return false; - } - - boolean anyChanges = false; - AppDetailsList apps = new AppDetailsList(); + protected String[] assembleAppStartCommand(final String workDir, final String appName, final String runAs, final String[] env) + { + return assembleCommand(workDir, appName, runAs, "start_", env); + } - for (File folder : fList) { // Roll all the apps inside the apps folder - if (folder.isDirectory()) { - File propsFile = new File(folder, HelperMisc.PROVIDER_PROPERTIES_FILE); - if (propsFile.exists() && !propsFile.isDirectory()) { - AppDetails app = this.readAppDescriptor(folder.getName(), propsFile); - apps.add(app); - } - } + protected HashMap assembleAppLauncherEnvironment(final String directoryServiceURI) + { + final HashMap targetEnv = new HashMap<>(); + try { + // Inherit NMF HOME and NMF LIB from the supervisor + Map parentEnv = EnvironmentUtils.getProcEnvironment(); + if (parentEnv.containsKey("NMF_LIB")) { + targetEnv.put("NMF_LIB", parentEnv.get("NMF_LIB")); + } + if (parentEnv.containsKey("NMF_HOME")) { + targetEnv.put("NMF_HOME", parentEnv.get("NMF_HOME")); + } + if (parentEnv.containsKey("PATH")) { + targetEnv.put("PATH", parentEnv.get("PATH")); + } + if (osValidator.isWindows()) { + if (parentEnv.containsKey("TEMP")) { + targetEnv.put("TEMP", parentEnv.get("TEMP")); } // Compare with the defs list! @@ -377,85 +380,102 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { anyChanges = true; } } + } + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "getProcEnvironment failed!", ex); + } + // Extend the current environment by JAVA_OPTS + targetEnv.put("JAVA_OPTS", + "-D" + Const.CENTRAL_DIRECTORY_URI_PROPERTY + "=" + directoryServiceURI + ""); + + return targetEnv; + } - // Also needs to check if we removed a folder! - final LongList ids = this.listAll(); - final AppDetailsList localApps = this.getAll(); - for (int i = 0; i < ids.size(); i++) { // Roll all the apps inside the apps folder - AppDetails localApp = localApps.get(i); - boolean appStillIntact = false; - for (File folder : fList) { // Roll all the apps inside the apps folder - if (folder.isDirectory()) { - if (folder.getName().equals(localApp.getName().getValue())) { - for (File file : folder.listFiles()) { // Roll all the files inside each app folder - // Check if the folder contains the provider properties - if (HelperMisc.PROVIDER_PROPERTIES_FILE.equals(file.getName())) { - // All Good! - appStillIntact = true; - break; - } - } - } - } - } + protected void startAppProcess(final ProcessExecutionHandler handler, + final MALInteraction interaction, final String directoryServiceURI) throws IOException + { + // get it from the list of available apps + AppDetails app = (AppDetails) this.getDef(handler.getObjId()); + String appName = app.getName().getValue(); + + // Go to the folder where the app are installed + final File appFolder = new File(appsFolderPath + File.separator + appName); + Map env = assembleAppLauncherEnvironment(directoryServiceURI); + String[] appLauncherCommand = assembleAppStartCommand( + appFolder.getAbsolutePath(), + appName, + app.getRunAs(), + EnvironmentUtils.toStrings(env)); + + final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); + pb.environment().clear(); + pb.environment().putAll(env); + + pb.directory(appFolder); + LOGGER.log(Level.INFO, + "Initializing ''{0}'' app in dir: {1}, using launcher command: {2}", + new Object[]{appName, appFolder.getAbsolutePath(), Arrays.toString(appLauncherCommand)}); + final Process proc = pb.start(); + handler.monitorProcess(proc); + handlers.put(handler.getObjId(), handler); + this.setRunning(handler.getObjId(), true, interaction); // Update the Archive + } - if (!appStillIntact) { - LOGGER.log(Level.INFO, "The app has been removed: {0}", localApp.getName().getValue()); + protected boolean killAppProcess(final Long appInstId, MALInteraction interaction) + { + AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps + String appName = app.getName().getValue(); - this.delete(ids.get(i)); - anyChanges = true; - } - } + LOGGER.log(Level.INFO, "Killing app: {0}", appName); + ProcessExecutionHandler handler = handlers.get(appInstId); - return anyChanges; + if (handler == null) { + LOGGER.log(Level.INFO, + "Handler of {0} app is null, setting running = false.", appName); + app.setRunning(false); + return false; } - protected boolean isAppRunning(final Long appId) { - // get it from the list of available apps - AppDetails app = (AppDetails) this.getDef(appId); - ProcessExecutionHandler handler = handlers.get(appId); - - if (handler == null) { - LOGGER.log(Level.FINE, "The Process handler could not be found!"); - - app.setRunning(false); - return false; - } - - return this.get(appId).getRunning(); + if (handler.getProcess() == null) { + LOGGER.log(Level.INFO, + "Process of {0} app is null, setting running = false.", appName); + app.setRunning(false); + return true; } - protected String[] assembleCommand(final String workDir, final String appName, final String runAs, - final String prefix, final String[] env) { - ArrayList ret = new ArrayList<>(); - String trimmedAppName = appName.replaceAll("space-app-", ""); - if (osValidator.isWindows()) { - ret.add("cmd"); - ret.add("/c"); - StringBuilder str = new StringBuilder(); - str.append(prefix); - str.append(trimmedAppName); - str.append(".bat"); - ret.add(str.toString()); - } else { - if (runAs != null) { - ret.add("su"); - ret.add("-"); - ret.add(runAs); - ret.add("-c"); - } else { - ret.add("/bin/sh"); - ret.add("-c"); - } - StringBuilder envString = new StringBuilder(); - for (String envVar : env) { - envString.append(envVar); - envString.append(" "); - } + handler.close(); + this.setRunning(handler.getObjId(), false, interaction); // Update the Archive + handlers.remove(appInstId); // Get rid of it! - ret.add("cd " + workDir + ";" + envString.toString() + "./" + prefix + trimmedAppName + ".sh"); - } - return ret.toArray(new String[0]); + return true; + } + + protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interaction, boolean onlyNativeComponent) throws + IOException, MALInteractionException, MALException + { + AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps + + // Go to the folder where the app is installed + final File appFolder + = new File(appsFolderPath + File.separator + app.getName().getValue()); + Map env = assembleAppLauncherEnvironment(""); + final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), + app.getName().getValue(), app.getRunAs(), EnvironmentUtils.toStrings(env)); + + final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); + pb.environment().clear(); + pb.directory(appFolder); + LOGGER.log(Level.INFO, + "Stopping ''{0}'' app in dir: {1}, using launcher command: {2}", + new Object[]{app.getName().getValue(), appFolder.getAbsolutePath(), Arrays.toString( + appLauncherCommand)}); + final Process proc = pb.start(); + interaction.sendUpdate(appInstId); + boolean exitCleanly = false; + try { + exitCleanly = proc.waitFor(APP_STOP_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (InterruptedException ex) { + LOGGER.log(Level.WARNING, null, ex); } protected String[] assembleAppStopCommand(final String workDir, final String appName, final String runAs, @@ -572,11 +592,25 @@ protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interac } catch (InterruptedException ex) { LOGGER.log(Level.WARNING, null, ex); } - if (!exitCleanly) { - LOGGER.log(Level.WARNING, - "App {0} stop script did not exit within the timeout ({1} ms). Killing the stop script and forcing the app exit.", - new Object[]{app.getName().getValue(), APP_STOP_TIMEOUT}); - proc.destroyForcibly(); + if (stopExists) { + Map env = assembleAppLauncherEnvironment(""); + final File appFolder + = new File(appsFolderPath + File.separator + curr.getName().getValue()); + final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), + curr.getName().getValue(), curr.getRunAs(), EnvironmentUtils.toStrings(env)); + final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); + pb.environment().clear(); + pb.directory(appFolder); + + LOGGER.log(Level.INFO, + "Stopping native component of ''{0}'' app", + new Object[]{curr.getName().getValue()}); + try { + this.stopNativeApp(appInstId, interaction, true); + } catch (IOException ex) { + Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.SEVERE, + "Stopping native component failed", ex); + } } if (onlyNativeComponent) { return true; From 697cc18168db72405eda168ccf5144d6a83379bb Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 13 Sep 2021 14:51:37 +0200 Subject: [PATCH 015/173] Installation is now supported on the Linux on Phi-Sat-2 --- .../mo/nmf/nmfpackage/HelperNMFPackage.java | 49 ++++++----- .../mo/nmf/nmfpackage/LinuxUsersGroups.java | 81 ++++++++++++++++--- .../nmf/nmfpackage/NMFPackagePMBackend.java | 4 +- 3 files changed, 94 insertions(+), 40 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index d737c3c3a..2421b6b9f 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -56,17 +56,23 @@ public static long calculateCRCFromInputStream(final InputStream inputStream) th return crc.getValue(); } - public static String generateLinuxStartAppScript(String mainclass, String jarFilename, String maxHeap) - throws IOException { + private static String getBanner(){ StringBuilder str = new StringBuilder(); - str.append("#!/bin/sh\n"); - str.append("#########################################################\n"); + str.append("#######################################################\n"); str.append("# This file was auto-generated by the NMF\n"); str.append("# during the installation of this App\n"); str.append("# We do not advise to change it directly!\n"); str.append("# The file is generated by the class: HelperNMFPackage\n"); - str.append("#########################################################\n"); + str.append("#######################################################\n"); str.append("\n"); + return str.toString(); + } + + public static String generateLinuxStartAppScript(String mainclass, + String jarFilename, String maxHeap) throws IOException { + StringBuilder str = new StringBuilder(); + str.append("#!/bin/sh\n"); + str.append(getBanner()); str.append("cd ${0%/*}\n"); str.append("\n"); @@ -96,13 +102,7 @@ public static String generateLinuxStartAppScript(String mainclass, String jarFil public static String generateProviderProperties(String runAs) throws IOException { StringBuilder str = new StringBuilder(); - str.append("#########################################################\n"); - str.append("# This file was auto-generated by the NMF\n"); - str.append("# during the installation of this App\n"); - str.append("# We do not advise to change it directly!\n"); - str.append("# The file is generated by the class: HelperNMFPackage\n"); - str.append("#########################################################\n"); - str.append("\n"); + str.append(getBanner()); str.append("# MO App configurations\n"); str.append(HelperMisc.PROP_ORGANIZATION_NAME).append("=").append("esa\n"); str.append(HelperMisc.APP_CATEGORY).append("=").append("NMF_App\n"); @@ -131,28 +131,25 @@ public static String generateProviderProperties(String runAs) throws IOException public static String generateTransportProperties() throws IOException { StringBuilder str = new StringBuilder(); - str.append("#########################################################\n"); - str.append("# This file was auto-generated by the NMF\n"); - str.append("# during the installation of this App\n"); - str.append("# We do not advise to change it directly!\n"); - str.append("# The file is generated by the class: HelperNMFPackage\n"); - str.append("#########################################################\n"); - str.append("\n"); + str.append(getBanner()); str.append("# The following property sets the protocol to be used:\n"); str.append("org.ccsds.moims.mo.mal.transport.default.protocol = maltcp://\n"); str.append("\n"); str.append("# TCP/IP protocol properties:\n"); - str.append( - "org.ccsds.moims.mo.mal.transport.protocol.maltcp=esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl\n"); - str.append( - "org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); - str.append( - "#org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.split.SplitBinaryStreamFactory\n"); + str.append("org.ccsds.moims.mo.mal.transport.protocol.maltcp=esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl\n"); + str.append("org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); + + // Bind to localhost + str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); + + /* str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=true\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.host=xxx.xxx.xxx.xxx\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); - str.append("#org.ccsds.moims.mo.mal.transport.tcpip.isServer=true\n"); + */ return str.toString(); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java index 1be04c921..cea75d133 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java @@ -39,6 +39,8 @@ public class LinuxUsersGroups { private static final String MSG_NOT_FOUND = "The command was not found.\n"; + private static final String DEFAULT_SHELL = "/bin/bash"; + /** * Adds a new Linux user account and sets its respective password. The * account can be created without a password by passing a null into the @@ -57,7 +59,6 @@ public class LinuxUsersGroups { public static void useradd(String username, String password, boolean withGroup, String extraGroups) throws IOException { ShellCommander shell = new ShellCommander(); - final String defaultShell = "/bin/bash"; // First, we need to check if the "useradd" exist String cmd1 = "useradd -h"; @@ -71,8 +72,11 @@ public static void useradd(String username, String password, // Second, we need to check if we have permissions to run the commands StringBuilder useradd = new StringBuilder(); useradd.append("sudo "); - useradd.append("useradd ").append(username).append(" --create-home").append(" --shell ").append(defaultShell) - .append(withGroup ? " --user-group" : "").append(" --groups ").append(extraGroups); + useradd.append("useradd ").append(username) + .append(" --create-home") + .append(" --shell ").append(DEFAULT_SHELL) + .append(withGroup ? " --user-group" : "") + .append(" --groups ").append(extraGroups); //String cmd = "useradd $user_nmf_admin -m -s /bin/bash --user-group"; //String cmd = "useradd $user_nmf_admin --create-home --shell /bin/bash --user-group"; @@ -93,6 +97,43 @@ public static void useradd(String username, String password, LinuxUsersGroups.printCommandAndOutput(cmd3, out3); } + /** + * Adds a new Linux group. + * + * @param groupName The name of the group to be created. + * @param isSystemGroup Creates a system group. + * @throws IOException if the group could not be created. + */ + public static void addgroup(String groupName, boolean isSystemGroup) throws IOException { + ShellCommander shell = new ShellCommander(); + + // First, we need to check if the "useradd" exist + String cmd1 = "sudo addgroup -h"; + String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); + + if (out1.contains(NOT_FOUND)) { + String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; + throw new IOException(msg); + } + + StringBuilder addgroup = new StringBuilder(); + addgroup.append("sudo "); + addgroup.append("addgroup ") + .append("-S ") + .append(groupName); + + String cmd2 = addgroup.toString(); + String out2 = shell.runCommandAndGetOutputMessageAndError(cmd2); + + if (out2.contains(PERMISSION_DENIED)) { + String msg = "Permission denied! For command:\n >> " + cmd2 + "\n" + out2; + throw new IOException(msg); + } + + // Print the command output: + LinuxUsersGroups.printCommandAndOutput(cmd2, out2); + } + /** * Adds a new Linux user account and sets its respective password. The * account can be created without a password by passing a null into the @@ -105,13 +146,12 @@ public static void useradd(String username, String password, * created during the user account creation. * @throws IOException if the user could not be created. */ - public static void adduser(String username, String password, + public static void adduser(String username, String password, boolean withGroup) throws IOException { ShellCommander shell = new ShellCommander(); - final String defaultShell = "/bin/bash"; // First, we need to check if the "useradd" exist - String cmd1 = "adduser -h"; + String cmd1 = "sudo adduser -h"; String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); if (out1.contains(NOT_FOUND)) { @@ -119,13 +159,30 @@ public static void adduser(String username, String password, throw new IOException(msg); } + // Different Linux Systems have different syntaxes for the same command + // So we need to check if we are using the adduser from "BusyBox" or not + boolean isBusyBox = out1.contains("BusyBox"); + // Second, we need to check if we have permissions to run the commands StringBuilder useradd = new StringBuilder(); useradd.append("sudo "); - useradd.append("adduser --system ") - .append("--shell ").append(defaultShell) - .append(withGroup ? " --group " : " ") - .append(username); + + if (isBusyBox) { + if (withGroup) { + LinuxUsersGroups.addgroup(username, true); + } + useradd.append("adduser ") + .append("-s ").append(DEFAULT_SHELL) + .append(withGroup ? " -G " : "") + .append(withGroup ? username : "") + .append(" -S ") + .append(username); + } else { + useradd.append("adduser --system ") + .append("--shell ").append(DEFAULT_SHELL) + .append(withGroup ? " --group " : " ") + .append(username); + } //String cmd = "useradd $user_nmf_admin -m -s /bin/bash --user-group"; //String cmd = "useradd $user_nmf_admin --create-home --shell /bin/bash --user-group"; @@ -150,7 +207,7 @@ public static void addUserToGroup(String username, String extraGroup) throws IOE ShellCommander shell = new ShellCommander(); // First, we need to check if the "useradd" exist - String cmd1 = "adduser -h"; + String cmd1 = "sudo adduser -h"; String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); if (out1.contains(NOT_FOUND)) { @@ -173,7 +230,7 @@ public static void addUserToGroup(String username, String extraGroup) throws IOE throw new IOException(msg); } } - + public static void chpasswd(String username, String password) throws IOException { ShellCommander shell = new ShellCommander(); String cmd2 = "chpasswd -h"; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index 2959e8099..f98a0c1bb 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -105,8 +105,8 @@ public void install(final String packageName) { File destination = getNMFDir(); Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, - "Installing the package...\nPackage name: " + packageName + "\nPackage location: " + packageLocation + - "\nDestination: " + destination.getAbsolutePath()); + "Installing the package...\nPackage name: " + packageName + + "\nPackage location: " + packageLocation); try { NMFPackageManager.install(packageLocation, destination); From 58336104f7b46fc6b909511ca0d3d25e9a9eebe7 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 14 Sep 2021 11:47:15 +0200 Subject: [PATCH 016/173] [nmfpack] The NMF Packages can carry fat jars (jar-with-dependencies) now --- .../mo/nmf/nmfpackage/HelperNMFPackage.java | 36 ++++ .../mo/nmf/nmfpackage/NMFPackageCreator.java | 17 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 29 ++-- .../descriptor/NMFPackageDescriptor.java | 19 +- .../descriptor/NMFPackageDetails.java | 11 +- .../nmf/nmfpackage/receipt/ReceiptMaster.java | 60 +++++++ .../nmfpackage/receipt/ReceiptVersion1.java | 4 +- .../nmfpackage/receipt/ReceiptVersion2.java | 4 +- .../nmfpackage/receipt/ReceiptVersion3.java | 162 ++++++++++++++++++ .../tests/SimpleDemoPackageCreation.java | 10 +- .../nmfpackage/GenerateNMFPackageMojo.java | 37 ++-- 11 files changed, 323 insertions(+), 66 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index 2421b6b9f..7412ce9f9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -22,9 +22,11 @@ import esa.mo.helpertools.helpers.HelperMisc; import java.io.BufferedInputStream; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.zip.CRC32; /** @@ -154,4 +156,38 @@ public static String generateTransportProperties() throws IOException { return str.toString(); } + public static File findAppJarInFolder(File folder) throws IOException { + File[] fList = folder.listFiles(); + ArrayList possibleOptions = new ArrayList(); + + for (File file : fList) { + if (file.isDirectory()) { + continue; // Jump over if it is a directory + } + + if (!file.getAbsolutePath().endsWith(".jar")) { + continue; // It is not a Jar file + } + + possibleOptions.add(file); + } + + if (possibleOptions.isEmpty()) { + throw new IOException("Not found!"); + } + + if (possibleOptions.size() == 1) { + return possibleOptions.get(0); + } + + if (possibleOptions.size() == 2) { + for (File option : possibleOptions) { + if (option.getName().contains("-jar-with-dependencies.jar")) { + return option; + } + } + } + + throw new IOException("There are too many jars inside the target folder!"); + } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index e2f3ac5da..29c84cadf 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -24,7 +24,7 @@ import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; -import esa.mo.nmf.nmfpackage.receipt.ReceiptVersion2; +import esa.mo.nmf.nmfpackage.receipt.ReceiptMaster; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedWriter; @@ -104,10 +104,7 @@ public static String nmfPackageCreator(NMFPackageDetails details, ArrayList> name = " + name); getLog().info(">> version = " + version); getLog().info(">> mainClass = " + mainClass); + getLog().info(">> mainJar = " + mainJar); getLog().info(">> privilege = " + privilege); getLog().info(">> nmfVersion = " + nmfVersion); getLog().info(">> maxHeap = " + maxHeap); @@ -140,8 +146,9 @@ public void execute() throws MojoExecutionException { final Time time = new Time(System.currentTimeMillis()); final String timestamp = HelperTime.time2readableString(time); - // Package 1 - NMFPackageDetails details = new NMFPackageDetails(name, version, timestamp, mainClass, maxHeap); + // Package + NMFPackageDetails details = new NMFPackageDetails(name, version, + timestamp, mainClass, mainJar, maxHeap); NMFPackageCreator.nmfPackageCreator(details, inputFiles, locations, "target"); } @@ -160,22 +167,4 @@ private void addFileOrDirectory(String path, String nest) { } } - private File findAppJarInTargetFolder() throws IOException { - File targetFolder = new File("target"); - File[] fList = targetFolder.listFiles(); - - for (File file : fList) { - if (file.isDirectory()) { - continue; // Jump over if it is a directory - } - - if (!file.getAbsolutePath().endsWith(".jar")) { - continue; // It is not a Jar file - } - - return file; - } - - throw new IOException("Not found!"); - } } From c19cecedde8e384b8004e6dd532e3e4aee292aea Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 14 Sep 2021 11:48:26 +0200 Subject: [PATCH 017/173] The AppStorage class is now setting the correct permissions during the creation of the storage folders --- .../java/esa/mo/sm/impl/util/OSValidator.java | 13 ------- .../src/main/java/esa/mo/nmf/AppStorage.java | 39 +++++++++++++++---- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java index 386be9c9e..6161394b2 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java @@ -29,19 +29,6 @@ public class OSValidator { private final String OS = System.getProperty("os.name").toLowerCase(); public OSValidator() { - /* - if (isWindows()) { - System.out.println("This is Windows"); - } else if (isMac()) { - System.out.println("This is Mac"); - } else if (isUnix()) { - System.out.println("This is Unix or Linux"); - } else if (isSolaris()) { - System.out.println("This is Solaris"); - } else { - System.out.println("Your OS is not support!!"); - } - */ } public boolean isWindows() { diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java index 0edbfeee0..0e6665751 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java @@ -22,6 +22,14 @@ import esa.mo.helpertools.helpers.HelperMisc; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; /** * The {@code AppStorage} class allows the retrieval of directory paths to store @@ -132,13 +140,30 @@ private static StringBuilder pathToUserAppDir() { private static void mkDirAndSetPermissions(File directory) { if (!directory.exists()) { - directory.mkdirs(); - directory.setExecutable(false, false); - directory.setExecutable(true, true); - directory.setReadable(false, false); - directory.setReadable(true, true); - directory.setWritable(false, false); - directory.setWritable(true, true); + // If it does not exist, please check if the parent dir exists + // because if not, then we also want to create that directory + // and set the correct permissions + AppStorage.mkDirAndSetPermissions(directory.getParentFile()); + + // We want to give access to both the App itself and the nmf-admin group + Set posix = PosixFilePermissions.fromString("rwxrwx---"); + FileAttribute permissions = PosixFilePermissions.asFileAttribute(posix); + try { + Files.createFile(directory.toPath(), permissions); + } catch (UnsupportedOperationException ex1) { + // Probably we are on Windows... Let's create it with: + directory.mkdirs(); + directory.setExecutable(false, false); + directory.setExecutable(true, true); + directory.setReadable(false, false); + directory.setReadable(true, true); + directory.setWritable(false, false); + directory.setWritable(true, true); + } catch (IOException ex2) { + Logger.getLogger(AppStorage.class.getName()).log(Level.SEVERE, + "Something went wrong...", ex2); + } } } + } From 55fde6e212d55308e6e82778c28841425451fcd3 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Sep 2021 09:58:09 +0200 Subject: [PATCH 018/173] Fixed small bug in the creation of the Directories with the right permissions --- .../src/main/java/esa/mo/nmf/AppStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java index 0e6665751..76b5d4c57 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/AppStorage.java @@ -149,7 +149,7 @@ private static void mkDirAndSetPermissions(File directory) { Set posix = PosixFilePermissions.fromString("rwxrwx---"); FileAttribute permissions = PosixFilePermissions.asFileAttribute(posix); try { - Files.createFile(directory.toPath(), permissions); + Files.createDirectory(directory.toPath(), permissions); } catch (UnsupportedOperationException ex1) { // Probably we are on Windows... Let's create it with: directory.mkdirs(); From 6d4b438ea61b39dadade8d552318adb85a653ad1 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Sep 2021 09:59:01 +0200 Subject: [PATCH 019/173] Fixed the package receipt version 3. The mainjar was not being correctly set --- .../java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 69121cdc0..abf94f38c 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -137,7 +137,7 @@ public static void writeReceipt(final BufferedWriter bw, bw.newLine(); bw.write(MAINCLASS + descriptor.getDetails().getMainclass()); bw.newLine(); - bw.write(MAINJAR + descriptor.getDetails().getMainclass()); + bw.write(MAINJAR + descriptor.getDetails().getMainJar()); bw.newLine(); // Iterate the newLocations and write them down on the file From 13770e04800896a1a7184b9d2ce54f30dcf2b053 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Sep 2021 10:32:46 +0200 Subject: [PATCH 020/173] Reduced logger verbosity on the Package Manager --- .../java/esa/mo/nmf/nmfpackage/NMFPackageManager.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 88f9ce841..d56b0d150 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -429,7 +429,8 @@ public static boolean isPackageInstalled(final String packageLocation) { // Compare the versions String version = descriptorFromExistingReceipt.getDetails().getVersion(); if (!details.getVersion().equals(version)) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, "The version does not match!"); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, + "The version does not match!"); return false; } @@ -440,8 +441,10 @@ public static boolean isPackageInstalled(final String packageLocation) { return false; } - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "The package " + details.getPackageName() + - " installation folder was found!"); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, + "The package " + + details.getPackageName() + + " installation folder was found!"); return true; } From f06243c25f9ec9e3b4139ecef2c135757533e088 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Sep 2021 13:40:53 +0200 Subject: [PATCH 021/173] Fixed the update operation. Code cleanup. Enabled the keepUserData functionality --- .../PackageManagementProviderServiceImpl.java | 10 +-- .../mo/nmf/nmfpackage/NMFPackageManager.java | 70 ++++++++----------- .../nmf/nmfpackage/NMFPackagePMBackend.java | 50 +++++++------ .../descriptor/NMFPackageDescriptor.java | 18 +++++ .../sm/PackageManagementConsumerPanel.java | 2 +- 5 files changed, 83 insertions(+), 67 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java index 529023542..56b0cd774 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java @@ -308,11 +308,13 @@ public void uninstall(final IdentifierList names, final BooleanList keepConfigur throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); } - for (Identifier packageName : names) { - Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).log(Level.INFO, "Uninstalling: {0}", - packageName.getValue()); + for (int i = 0; i < names.size(); i++) { + Identifier packageName = names.get(i); + Boolean keepConfiguration = keepConfigurations.get(i); + Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).log( + Level.INFO, "Uninstalling: {0}", packageName.getValue()); - backend.uninstall(packageName.getValue(), true); + backend.uninstall(packageName.getValue(), keepConfiguration); } interaction.sendResponse(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index d56b0d150..f54d31d79 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -68,15 +68,11 @@ public static void install(final String packageLocation, final File nmfDir) thro System.console().printf(SEPARATOR); // Get the File to be installed ZipFile zipFile = new ZipFile(packageLocation); - ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); // Verify integrity of the file: Are all the declared files matching their CRCs? System.out.print("Reading the receipt file that " + "includes the list of files to be installed... "); - // Get the text out of that file and parse it into a NMFPackageDescriptor object - final InputStream stream = zipFile.getInputStream(receipt); - final NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseInputStream(stream); - stream.close(); + final NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); System.out.println("Done!"); // Safety check... should never happen... @@ -120,7 +116,7 @@ public static void install(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the files to the new locations... "); - copyFiles(descriptor, zipFile, nmfDir); + installFiles(zipFile, nmfDir); String username = null; String password = null; @@ -183,7 +179,6 @@ public static void install(final String packageLocation, final File nmfDir) thro // --------------------------------------- // Store a copy of the receipt to know that it has been installed! - // Default location of the folder File receiptsFolder = getReceiptsFolder(); String receiptFilename = appName + NMFPackageManager.RECEIPT_ENDING; String receiptPath = receiptsFolder.getCanonicalPath() + File.separator + receiptFilename; @@ -191,8 +186,8 @@ public static void install(final String packageLocation, final File nmfDir) thro //create the file otherwise we get FileNotFoundException new File(receiptFile.getParent()).mkdirs(); - // ----------------- + ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); final FileOutputStream fos = new FileOutputStream(receiptFile); final InputStream zis = zipFile.getInputStream(receipt); byte[] buffer = new byte[1024]; @@ -212,23 +207,10 @@ public static void install(final String packageLocation, final File nmfDir) thro System.console().printf(SEPARATOR); } - public static void uninstall(final String packageLocation, + public static void uninstall(final NMFPackageDescriptor descriptor, final boolean keepUserData) throws IOException { System.console().printf(SEPARATOR); - // Get the Package to be uninstalled - ZipFile zipFile = new ZipFile(packageLocation); - ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); - - // Verify integrity of the file: Are all the declared files matching their CRCs? - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Reading the receipt file that includes the list of files to be uninstalled..."); - - // Get the text out of that file and parse it into a NMFPackageDescriptor object - final InputStream stream = zipFile.getInputStream(receipt); - final NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseInputStream(stream); - stream.close(); - // Safety check... should never happen... if (descriptor == null) { throw new IOException("The parsed descriptor is null."); @@ -269,10 +251,13 @@ public static void uninstall(final String packageLocation, // We need to delete the respective user here!! //LinuxUsersGroups.userdel(generateUsername(appName), true); - LinuxUsersGroups.deluser(generateUsername(appName), true); + if(!keepUserData){ + String username = generateUsername(appName); + LinuxUsersGroups.deluser(username, true); + } Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Package successfully uninstalled from: " + packageLocation); + "Package successfully uninstalled from: " + installationDir); System.console().printf(SEPARATOR); } @@ -287,32 +272,32 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Reading the receipt file that includes the list of files to be upgraded..."); - // Get the text out of that file and parse it into a NMFPackageDescriptor object - final InputStream stream = zipFile.getInputStream(receipt); - final NMFPackageDescriptor descriptorFromPackage = NMFPackageDescriptor.parseInputStream(stream); - stream.close(); + // Get the descriptor inside the zip file + final NMFPackageDescriptor newDescriptor = NMFPackageDescriptor.parseZipFile(zipFile); // Safety check... should never happen... - if (descriptorFromPackage == null) { + if (newDescriptor == null) { throw new IOException("The parsed descriptor is null."); } File receiptsFolder = getReceiptsFolder(); - String receiptFilename = descriptorFromPackage.getDetails().getPackageName() + NMFPackageManager.RECEIPT_ENDING; + String receiptFilename = newDescriptor.getDetails().getPackageName() + NMFPackageManager.RECEIPT_ENDING; File receiptFile = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); // Get the text out of that file and parse it into a NMFPackageDescriptor object final InputStream stream2 = new FileInputStream(receiptFile); - final NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseInputStream(stream2); + final NMFPackageDescriptor oldDescriptor = NMFPackageDescriptor.parseInputStream(stream2); stream2.close(); - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Upgrading from version: '" + descriptor - .getDetails().getVersion() + "'" + " To version: '" + descriptorFromPackage.getDetails().getVersion() + - "'"); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "Upgrading..." + + "\n >> From version: " + oldDescriptor.getDetails().getVersion() + + "\n >> To version: " + newDescriptor.getDetails().getVersion() + ); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Removing the previous files..."); - removeFiles(descriptor); + removeFiles(oldDescriptor); if (!receiptFile.delete()) { // The file could not be deleted... Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, @@ -323,7 +308,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the new files to the locations..."); - copyFiles(descriptor, zipFile, nmfDir); + installFiles(zipFile, nmfDir); // --------------------------------------- // Store a copy of the receipt to know that it has been installed! @@ -480,8 +465,9 @@ private static String generateFilePathForSystem(final String path) { return out1.replace('\\', File.separatorChar); } - private static void copyFiles(final NMFPackageDescriptor descriptor, final ZipFile zipFile, File installationFolder) - throws IOException { + private static void installFiles(final ZipFile zipFile, File to) throws IOException { + NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); + File newFile; byte[] buffer = new byte[1024]; @@ -491,7 +477,7 @@ private static void copyFiles(final NMFPackageDescriptor descriptor, final ZipFi ZipEntry entry = zipFile.getEntry(file.getPath()); final String path = generateFilePathForSystem(entry.getName()); - newFile = new File(installationFolder.getCanonicalPath() + File.separator + path); + newFile = new File(to.getCanonicalPath() + File.separator + path); File parent = new File(newFile.getParent()); if (!parent.exists()) { @@ -555,11 +541,11 @@ private static void removeFiles(final NMFPackageDescriptor descriptor) throws IO } private static void removeFile(File file) throws IOException { - System.out.println(" >> Removing file on: " + file.getCanonicalPath()); + System.out.println(" >> Removing: " + file.getCanonicalPath()); if (!file.exists()) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, "The file no longer exists: " + file - .getCanonicalPath()); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, + "Not Found / Does not exist: " + file.getCanonicalPath()); return; } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index f98a0c1bb..14549f8ff 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -21,11 +21,13 @@ package esa.mo.nmf.nmfpackage; import esa.mo.helpertools.misc.Const; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import java.io.File; import esa.mo.sm.impl.util.PMBackend; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.zip.ZipFile; import org.ccsds.moims.mo.mal.structures.StringList; /** @@ -39,8 +41,8 @@ public class NMFPackagePMBackend implements PMBackend { @Deprecated private static final String PACKAGES_FOLDER = "packages"; // dir name - - private final File folderWithPackages; // Location of the folder + + private final File packagesFolder; // Location of the folder /** * Initializes a backend for NMF Packages. The backend will look for @@ -49,7 +51,7 @@ public class NMFPackagePMBackend implements PMBackend { * @param folder The folder to look for packages */ public NMFPackagePMBackend(String folder) { - folderWithPackages = new File(folder); + packagesFolder = new File(folder); } /** @@ -62,9 +64,9 @@ public NMFPackagePMBackend(String folder) { public NMFPackagePMBackend() { // If there is a property for that, then use it!! if (System.getProperty(FOLDER_LOCATION_PROPERTY) != null) { - folderWithPackages = new File(System.getProperty(FOLDER_LOCATION_PROPERTY)); - } else { - folderWithPackages = new File(PACKAGES_FOLDER); + packagesFolder = new File(System.getProperty(FOLDER_LOCATION_PROPERTY)); + }else{ + packagesFolder = new File(PACKAGES_FOLDER); } } @@ -72,16 +74,16 @@ public NMFPackagePMBackend() { public StringList getListOfPackages() throws IOException { // Go to the folder that contains the Packages and return the list of files! - if (!folderWithPackages.exists()) { // The folder does not exist + if (!packagesFolder.exists()) { // The folder does not exist // Then create a new folder with a default name Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, - "The packages folder does not exist. It will be created in path: {0}", folderWithPackages - .getCanonicalPath()); + "The packages folder does not exist. It will be created in path: {0}", + packagesFolder.getCanonicalPath()); - folderWithPackages.mkdir(); + packagesFolder.mkdir(); } - File[] files = folderWithPackages.listFiles(); + File[] files = packagesFolder.listFiles(); StringList packageNames = new StringList(files.length); @@ -119,11 +121,19 @@ public void install(final String packageName) { @Override public void uninstall(final String packageName, final boolean keepUserData) { String folderLocation = this.getFolderLocation(packageName); - Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, "Uninstalling the package from: {0}", - folderLocation); - + Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, + "Uninstalling the package from: {0}", folderLocation); + try { - NMFPackageManager.uninstall(folderLocation, keepUserData); + // Get the Package and descriptor to be uninstalled + ZipFile zipFile = new ZipFile(folderLocation); + + // Verify integrity of the file: Are all the declared files matching their CRCs? + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "Reading the receipt file that includes the list of files to be uninstalled..."); + + NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); + NMFPackageManager.uninstall(descriptor, keepUserData); } catch (IOException ex) { Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, "The package '" + packageName + "' could not be uninstalled!", ex); @@ -132,15 +142,15 @@ public void uninstall(final String packageName, final boolean keepUserData) { @Override public void upgrade(final String packageName) { - String folderLocation = this.getFolderLocation(packageName); - Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, "Upgrading the package from: {0}", - folderLocation); + String packageLocation = this.getFolderLocation(packageName); + Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, + "Upgrading the package from: {0}", packageLocation); // Define the location to be installed! File destination = getNMFDir(); try { - NMFPackageManager.upgrade(folderLocation, destination); + NMFPackageManager.upgrade(packageLocation, destination); } catch (IOException ex) { Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, null, ex); } @@ -166,7 +176,7 @@ public boolean checkPackageIntegrity(final String packageName) throws Unsupporte } private String getFolderLocation(final String packageName) { - return folderWithPackages.getAbsolutePath() + File.separator + packageName; + return packagesFolder.getAbsolutePath() + File.separator + packageName; } private File getNMFDir() { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java index 98ca0c82f..d8f98471d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java @@ -28,6 +28,8 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** * @@ -86,4 +88,20 @@ public static NMFPackageDescriptor parseInputStream(final InputStream stream) th return newDescriptor; } + /** + * Parses a ZipFile, finds the receipt file and generated the respective + * NMFPackageDescriptor. + * + * @param zipFile The zip file with the receipt file. + * @return The descriptor of the NMF Package. + */ + public static NMFPackageDescriptor parseZipFile(final ZipFile zipFile) throws IOException { + ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); + + // Try to open the the receipt file inside the Zip file + // and parse it into a NMFPackageDescriptor object + try (InputStream stream = zipFile.getInputStream(receipt)) { + return NMFPackageDescriptor.parseInputStream(stream); + } + } } diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/sm/PackageManagementConsumerPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/sm/PackageManagementConsumerPanel.java index b567a00f6..75cae75cd 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/sm/PackageManagementConsumerPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/sm/PackageManagementConsumerPanel.java @@ -242,7 +242,7 @@ private void uninstallButtonActionPerformed(java.awt.event.ActionEvent evt) {//G IdentifierList ids = new IdentifierList(); ids.add(packagesTable.getSelectedPackage()); BooleanList keep = new BooleanList(); - keep.add(true); + keep.add(false); try { this.serviceSMPackageManagement.getPackageManagementStub().uninstall(ids, keep, From a0ec42802ff65736a29a9151051da8862cec45e6 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 30 Sep 2021 18:23:58 +0200 Subject: [PATCH 022/173] The upgrade operation is now regeneration the Auxiliary files, e.g. start_App script. The start_Aoo script will now select the best Java Runtime Environment available. --- .../mo/nmf/nmfpackage/HelperNMFPackage.java | 129 ++++++++++++++++-- .../mo/nmf/nmfpackage/NMFPackageManager.java | 83 +++++++++-- 2 files changed, 190 insertions(+), 22 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index 7412ce9f9..f0d8f4169 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -24,9 +24,13 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.zip.CRC32; /** @@ -70,8 +74,8 @@ private static String getBanner(){ return str.toString(); } - public static String generateLinuxStartAppScript(String mainclass, - String jarFilename, String maxHeap) throws IOException { + public static String generateLinuxStartAppScript(String javaCommand, + String mainclass, String jarFilename, String maxHeap) throws IOException { StringBuilder str = new StringBuilder(); str.append("#!/bin/sh\n"); str.append(getBanner()); @@ -79,7 +83,7 @@ public static String generateLinuxStartAppScript(String mainclass, str.append("\n"); str.append("# Constants set at installation time:\n"); - str.append("JAVA_CMD=java\n"); + str.append("JAVA_CMD=").append(javaCommand).append("\n"); str.append("MAIN_JAR_NAME=").append(jarFilename).append("\n"); str.append("MAIN_CLASS_NAME=").append(mainclass).append("\n"); str.append("MAX_HEAP=").append(maxHeap).append("\n"); @@ -87,7 +91,9 @@ public static String generateLinuxStartAppScript(String mainclass, str.append("NMF_LIB=").append("`cd ../../libs > /dev/null; pwd`").append("\n"); str.append("\n"); - str.append("JAVA_OPTS=\"-Xms32m -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); + str.append("if [ -z \"$JAVA_OPTS\" ] ; then\n"); + str.append(" JAVA_OPTS=\"-Xms32m -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); + str.append("fi\n"); str.append("\n"); str.append("export JAVA_OPTS\n"); @@ -141,7 +147,7 @@ public static String generateTransportProperties() throws IOException { str.append("# TCP/IP protocol properties:\n"); str.append("org.ccsds.moims.mo.mal.transport.protocol.maltcp=esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl\n"); str.append("org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); - + // Bind to localhost str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); @@ -151,8 +157,7 @@ public static String generateTransportProperties() throws IOException { str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=true\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.host=xxx.xxx.xxx.xxx\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); - */ - + */ return str.toString(); } @@ -189,5 +194,113 @@ public static File findAppJarInFolder(File folder) throws IOException { } throw new IOException("There are too many jars inside the target folder!"); - } + } + + /** + * Find the best Java Runtime Environment for the App based on a recommended + * version, a minimum version, and a maximum version. + * + * @param recommended The recommended version to run the App. + * @param min The minimum version needed to run the App. + * @param max The maximum version to run the App. + * @return The Best JRE available for . + */ + public static String findJREPath(File nmfDir, int recommended, int min, int max) { + if (min < max) { + Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, + "The JRE minimum version cannot be greater than the maximum!"); + } + + if (recommended < min || recommended > max) { + Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, + "The JRE recommended version should be between the min and max!"); + } + + File javaNMFDir = new File(nmfDir.getAbsolutePath() + File.separator + "java"); + String bestJRE = "java"; // Default value and worst-case scenario + + if (javaNMFDir.exists()) { + File[] list = javaNMFDir.listFiles(); + final String VERSION_PROP = "JAVA_VERSION"; + + for (File dir : list) { + if (!dir.isDirectory()) { + continue; // Jump over if it is not a directory + } + + try { + // Check which java version it is from the release file... + String path = dir.getAbsolutePath(); + File release = new File(path + File.separator + "release"); + + if (!release.exists()) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JRE release file does not " + + "exist in: " + release.getAbsolutePath()); + continue; + } + + Properties props = new Properties(); + props.load(new FileInputStream(release)); + String version = (String) props.get(VERSION_PROP); + + if (version == null) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JAVA_VERSION property " + + "was not be found on release file: " + path); + continue; + } + + String[] subs = version.replace("\"", "").split("\\."); + + if (subs.length < 3) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JRE version '" + version + + "' could not be determined from the release file: " + + release.getAbsolutePath()); + continue; + } + + // Java version used to start with 1 until at least Java 8 + int java_version = (Integer.parseInt(subs[0]) != 1) + ? Integer.parseInt(subs[0]) + : Integer.parseInt(subs[1]); + + String jre = dir.getAbsolutePath() + File.separator + + "bin" + File.separator + "java"; + + if ((new File(jre)).exists()) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, + "The JRE could not found in directory: " + path); + continue; + } + + if (java_version == recommended) { + // Perfect, just return it directly! + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.INFO, "The JRE version " + java_version + + " was successfully found in directory:" + + "\n >> " + jre); + + return jre; + } + + // The version is outside boundaries? + if (java_version < min && java_version > max) { + continue; + } + bestJRE = jre; + } catch (FileNotFoundException ex) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "Something went wrong...", ex); + } catch (IOException ex) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "Something went wrong...", ex); + } + } + } + + return bestJRE; + } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index f54d31d79..da63e2369 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -148,7 +148,12 @@ public static void install(final String packageLocation, final File nmfDir) thro File jar = HelperNMFPackage.findAppJarInFolder(installationDir); jarName = jar.getName(); } - String content = HelperNMFPackage.generateLinuxStartAppScript(mainclass, jarName, maxHeap); + + // The Java version for now will be forced to 8, however in + // the future the package should recommend a version + String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); + String content = HelperNMFPackage.generateLinuxStartAppScript( + javaCMD, mainclass, jarName, maxHeap); String path = installationDir.getAbsolutePath() + File.separator + "start_" + appName + ".sh"; @@ -227,17 +232,7 @@ public static void uninstall(final NMFPackageDescriptor descriptor, File nmfDir = getInstallationFolder(); File installationDir = new File(nmfDir.getAbsolutePath() + File.separator + "apps" + File.separator + appName); - String providerPath = installationDir.getAbsolutePath() + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; - String transportPath = installationDir.getAbsolutePath() + File.separator + - HelperMisc.TRANSPORT_PROPERTIES_FILE; - String startPath = installationDir.getAbsolutePath() + File.separator + "start_" + appName + ".sh"; - - // Remove the provider.properties - // Remove the transport.properties - // Remove the start_benchmark.sh - NMFPackageManager.removeFile(new File(providerPath)); - NMFPackageManager.removeFile(new File(transportPath)); - NMFPackageManager.removeFile(new File(startPath)); + removeAuxiliaryFiles(installationDir, appName); File receiptsFolder = getReceiptsFolder(); String receiptFilename = descriptor.getDetails().getPackageName() + NMFPackageManager.RECEIPT_ENDING; @@ -251,7 +246,7 @@ public static void uninstall(final NMFPackageDescriptor descriptor, // We need to delete the respective user here!! //LinuxUsersGroups.userdel(generateUsername(appName), true); - if(!keepUserData){ + if (!keepUserData) { String username = generateUsername(appName); LinuxUsersGroups.deluser(username, true); } @@ -262,6 +257,22 @@ public static void uninstall(final NMFPackageDescriptor descriptor, System.console().printf(SEPARATOR); } + private static void removeAuxiliaryFiles(File installationDir, String appName) throws IOException { + String providerPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; + String transportPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; + String startPath = installationDir.getAbsolutePath() + + File.separator + "start_" + appName + ".sh"; + + // Remove the provider.properties + // Remove the transport.properties + // Remove the start_benchmark.sh + NMFPackageManager.removeFile(new File(providerPath)); + NMFPackageManager.removeFile(new File(transportPath)); + NMFPackageManager.removeFile(new File(startPath)); + } + public static void upgrade(final String packageLocation, final File nmfDir) throws IOException { System.console().printf(SEPARATOR); // Get the Package to be uninstalled @@ -299,6 +310,15 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro removeFiles(oldDescriptor); + String appName = oldDescriptor.getDetails().getPackageName(); + + // This directory should be passed in the method signature: + File installationDir = new File(nmfDir.getAbsolutePath() + + File.separator + "apps" + + File.separator + appName); + + removeAuxiliaryFiles(installationDir, appName); + if (!receiptFile.delete()) { // The file could not be deleted... Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, "The receipt file could not be deleted from: " @@ -309,6 +329,41 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro "Copying the new files to the locations..."); installFiles(zipFile, nmfDir); + String username = null; + + if ((new OSValidator()).isUnix()) { + username = generateUsername(appName); + String jarName = newDescriptor.getDetails().getMainJar(); + if (jarName.equals("")) { + File jar = HelperNMFPackage.findAppJarInFolder(installationDir); + jarName = jar.getName(); + } + // The Java version for now will be forced to 8, however in + // the future the package should recommend a version + String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); + String mainClass = newDescriptor.getDetails().getMainclass(); + String maxHeap = newDescriptor.getDetails().getMaxHeap(); + String content = HelperNMFPackage.generateLinuxStartAppScript( + javaCMD, mainClass, jarName, maxHeap); + String path = installationDir.getAbsolutePath() + + File.separator + "start_" + appName + ".sh"; + + NMFPackageManager.writeFile(path, content); + File startApp = new File(path); + startApp.setExecutable(true, true); + } + + // Generate provider.properties + String providerPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; + String providerContent = HelperNMFPackage.generateProviderProperties(username); + NMFPackageManager.writeFile(providerPath, providerContent); + + // Generate transport.properties + String transportPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; + String transportContent = HelperNMFPackage.generateTransportProperties(); + NMFPackageManager.writeFile(transportPath, transportContent); // --------------------------------------- // Store a copy of the receipt to know that it has been installed! @@ -467,7 +522,7 @@ private static String generateFilePathForSystem(final String path) { private static void installFiles(final ZipFile zipFile, File to) throws IOException { NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); - + File newFile; byte[] buffer = new byte[1024]; From 956c1acd915477ac338b0e06e6f50b3b2d9c8979 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 1 Oct 2021 14:08:13 +0200 Subject: [PATCH 023/173] Set correct permissions recursively to the App folder after ugrading it --- .../mo/nmf/nmfpackage/NMFPackageManager.java | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index da63e2369..6736505a5 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -183,7 +183,7 @@ public static void install(final String packageLocation, final File nmfDir) thro LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); // --------------------------------------- - // Store a copy of the receipt to know that it has been installed! + // Store a copy of the newReceipt to know that it has been installed! File receiptsFolder = getReceiptsFolder(); String receiptFilename = appName + NMFPackageManager.RECEIPT_ENDING; String receiptPath = receiptsFolder.getCanonicalPath() + File.separator + receiptFilename; @@ -277,7 +277,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro System.console().printf(SEPARATOR); // Get the Package to be uninstalled ZipFile zipFile = new ZipFile(packageLocation); - ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); + ZipEntry newReceipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); // Verify integrity of the file: Are all the declared files matching their CRCs? Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, @@ -293,10 +293,10 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro File receiptsFolder = getReceiptsFolder(); String receiptFilename = newDescriptor.getDetails().getPackageName() + NMFPackageManager.RECEIPT_ENDING; - File receiptFile = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); + File oldReceipt = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); // Get the text out of that file and parse it into a NMFPackageDescriptor object - final InputStream stream2 = new FileInputStream(receiptFile); + final InputStream stream2 = new FileInputStream(oldReceipt); final NMFPackageDescriptor oldDescriptor = NMFPackageDescriptor.parseInputStream(stream2); stream2.close(); @@ -319,10 +319,10 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro removeAuxiliaryFiles(installationDir, appName); - if (!receiptFile.delete()) { // The file could not be deleted... + if (!oldReceipt.delete()) { // The file could not be deleted... Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, "The receipt file could not be deleted from: " - + receiptFile.getCanonicalPath()); + + oldReceipt.getCanonicalPath()); } Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, @@ -365,14 +365,22 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro String transportContent = HelperNMFPackage.generateTransportProperties(); NMFPackageManager.writeFile(transportPath, transportContent); + // Change Group owner of the installationDir + if (username != null) { + LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); + } + + // chmod the installation directory with recursive + LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + // --------------------------------------- - // Store a copy of the receipt to know that it has been installed! + // Store a copy of the newReceipt to know that it has been installed! //create the file otherwise we get FileNotFoundException - new File(receiptFile.getParent()).mkdirs(); + new File(oldReceipt.getParent()).mkdirs(); // ----------------- - final FileOutputStream fos = new FileOutputStream(receiptFile); - final InputStream zis = zipFile.getInputStream(receipt); + final FileOutputStream fos = new FileOutputStream(oldReceipt); // Output location + final InputStream zis = zipFile.getInputStream(newReceipt); byte[] buffer = new byte[1024]; int len; @@ -397,8 +405,9 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro * @return If it is installed or not. */ public static boolean isPackageInstalled(final String packageLocation) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, "Verifying if the package is installed..."); - // Find the receipt and get it out of the package + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, + "Verifying if the package is installed..."); + // Find the newReceipt and get it out of the package ZipFile zipFile; try { zipFile = new ZipFile(packageLocation); @@ -445,7 +454,7 @@ public static boolean isPackageInstalled(final String packageLocation) { return false; } - // Check the version of the installed receipt + // Check the version of the installed newReceipt NMFPackageDescriptor descriptorFromExistingReceipt; long crcDescriptorFromExistingReceipt; @@ -612,7 +621,7 @@ private static void removeFile(File file) throws IOException { public static String getPublicKey(String folderLocation) { /* - // Find the receipt and get it out of the package + // Find the newReceipt and get it out of the package ZipFile zipFile; try { zipFile = new ZipFile(packageLocation); From 4c9e212747fe80909439927269eb19c29398bc90 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 1 Oct 2021 18:45:24 +0200 Subject: [PATCH 024/173] Fixed a bug on the validation of the JRE folder. Code cleanup --- .../mo/nmf/nmfpackage/HelperNMFPackage.java | 154 +++++++++--------- 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index f0d8f4169..2197bc6ec 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -197,7 +197,8 @@ public static File findAppJarInFolder(File folder) throws IOException { } /** - * Find the best Java Runtime Environment for the App based on a recommended + * Find the best Java Runtime Environment inside an nmf directory. The best + * JRE will be determined based on arguments containing a recommended * version, a minimum version, and a maximum version. * * @param recommended The recommended version to run the App. @@ -219,85 +220,90 @@ public static String findJREPath(File nmfDir, int recommended, int min, int max) File javaNMFDir = new File(nmfDir.getAbsolutePath() + File.separator + "java"); String bestJRE = "java"; // Default value and worst-case scenario - if (javaNMFDir.exists()) { - File[] list = javaNMFDir.listFiles(); - final String VERSION_PROP = "JAVA_VERSION"; + if (!javaNMFDir.exists()) { + return bestJRE; // Return the default value + } + + final String VERSION_PROP = "JAVA_VERSION"; + File[] list = javaNMFDir.listFiles(); + + for (File dir : list) { + if (!dir.isDirectory()) { + continue; // Jump over if it is not a directory + } + + try { + // Check which java version it is from the release file... + String path = dir.getAbsolutePath(); + File release = new File(path + File.separator + "release"); - for (File dir : list) { - if (!dir.isDirectory()) { - continue; // Jump over if it is not a directory + if (!release.exists()) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JRE release file does not " + + "exist in: " + release.getAbsolutePath()); + continue; } - try { - // Check which java version it is from the release file... - String path = dir.getAbsolutePath(); - File release = new File(path + File.separator + "release"); - - if (!release.exists()) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "The JRE release file does not " - + "exist in: " + release.getAbsolutePath()); - continue; - } - - Properties props = new Properties(); - props.load(new FileInputStream(release)); - String version = (String) props.get(VERSION_PROP); - - if (version == null) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "The JAVA_VERSION property " - + "was not be found on release file: " + path); - continue; - } - - String[] subs = version.replace("\"", "").split("\\."); - - if (subs.length < 3) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "The JRE version '" + version - + "' could not be determined from the release file: " - + release.getAbsolutePath()); - continue; - } - - // Java version used to start with 1 until at least Java 8 - int java_version = (Integer.parseInt(subs[0]) != 1) - ? Integer.parseInt(subs[0]) - : Integer.parseInt(subs[1]); - - String jre = dir.getAbsolutePath() + File.separator - + "bin" + File.separator + "java"; - - if ((new File(jre)).exists()) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, - "The JRE could not found in directory: " + path); - continue; - } - - if (java_version == recommended) { - // Perfect, just return it directly! - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.INFO, "The JRE version " + java_version - + " was successfully found in directory:" - + "\n >> " + jre); - - return jre; - } - - // The version is outside boundaries? - if (java_version < min && java_version > max) { - continue; - } - bestJRE = jre; - } catch (FileNotFoundException ex) { + Properties props = new Properties(); + props.load(new FileInputStream(release)); + String version = (String) props.get(VERSION_PROP); + + if (version == null) { Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "Something went wrong...", ex); - } catch (IOException ex) { + Level.WARNING, "The JAVA_VERSION property " + + "was not be found on release file: " + path); + continue; + } + + String[] subs = version.replace("\"", "").split("\\."); + + if (subs.length < 3) { Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "Something went wrong...", ex); + Level.WARNING, "The JRE version '" + version + + "' could not be determined from the release file: " + + release.getAbsolutePath()); + continue; + } + + // Java version used to start with 1 until at least Java 8 + int java_version = (Integer.parseInt(subs[0]) != 1) + ? Integer.parseInt(subs[0]) + : Integer.parseInt(subs[1]); + + String jre = dir.getAbsolutePath() + File.separator + + "bin" + File.separator + "java"; + + if (!(new File(jre)).exists()) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, + "The JRE could not found in directory: " + path); + continue; + } + + if (java_version == recommended) { + // Perfect, just return it directly! + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.INFO, "The JRE version " + java_version + + " was successfully found in directory:" + + "\n >> " + jre); + + return jre; + } + + // The version is outside boundaries? + if (java_version < min && java_version > max) { + continue; } + bestJRE = jre; + // The code here will need to be improved... + // The objective should be to return the + // highest available version within the choices + } catch (FileNotFoundException ex) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "Something went wrong...", ex); + } catch (IOException ex) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "Something went wrong...", ex); } } From 44138a476b28092fa9f2ea55c78fbabd91a44712 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 1 Oct 2021 19:34:26 +0200 Subject: [PATCH 025/173] Fixed small typo in logger --- .../src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index 2197bc6ec..bf70c07be 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -276,7 +276,7 @@ public static String findJREPath(File nmfDir, int recommended, int min, int max) if (!(new File(jre)).exists()) { Logger.getLogger(HelperNMFPackage.class.getName()).log( Level.WARNING, - "The JRE could not found in directory: " + path); + "The JRE could not be found in directory: " + path); continue; } From 1e6aae8c29ee8f10c2587cbd999c24e21d3d6512 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 4 Oct 2021 11:35:46 +0200 Subject: [PATCH 026/173] System.console() might return null in some cases, so we must use System.out --- .../esa/mo/nmf/nmfpackage/NMFPackageManager.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 6736505a5..dc2f1ab62 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -63,9 +63,9 @@ public class NMFPackageManager { private static final String SEPARATOR = "--------------\n"; - public static void install(final String packageLocation, final File nmfDir) throws FileNotFoundException, - IOException { - System.console().printf(SEPARATOR); + public static void install(final String packageLocation, + final File nmfDir) throws FileNotFoundException, IOException { + System.out.printf(SEPARATOR); // Get the File to be installed ZipFile zipFile = new ZipFile(packageLocation); @@ -209,12 +209,12 @@ public static void install(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully installed from: {0}", packageLocation); - System.console().printf(SEPARATOR); + System.out.printf(SEPARATOR); } public static void uninstall(final NMFPackageDescriptor descriptor, final boolean keepUserData) throws IOException { - System.console().printf(SEPARATOR); + System.out.printf(SEPARATOR); // Safety check... should never happen... if (descriptor == null) { @@ -254,7 +254,7 @@ public static void uninstall(final NMFPackageDescriptor descriptor, Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully uninstalled from: " + installationDir); - System.console().printf(SEPARATOR); + System.out.printf(SEPARATOR); } private static void removeAuxiliaryFiles(File installationDir, String appName) throws IOException { @@ -274,7 +274,7 @@ private static void removeAuxiliaryFiles(File installationDir, String appName) t } public static void upgrade(final String packageLocation, final File nmfDir) throws IOException { - System.console().printf(SEPARATOR); + System.out.printf(SEPARATOR); // Get the Package to be uninstalled ZipFile zipFile = new ZipFile(packageLocation); ZipEntry newReceipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); @@ -395,7 +395,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully upgraded from location: " + packageLocation); - System.console().printf(SEPARATOR); + System.out.printf(SEPARATOR); } /** From 377c5108061d7c7040bd03e69b0d69efd7dd14e9 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 6 Dec 2021 11:37:05 +0100 Subject: [PATCH 027/173] [AppsLauncher] Check if sudo is (not) available using the termination code 127. --- .../sm/impl/provider/AppsLauncherManager.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index b12ca606e..a742ccb53 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -32,7 +32,6 @@ import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.misc.Const; import esa.mo.sm.impl.util.OSValidator; -import esa.mo.sm.impl.util.ShellCommander; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -128,9 +127,23 @@ public Boolean compareName(Long objId, Identifier name) { } if(osValidator.isUnix()){ - ShellCommander shell = new ShellCommander(); - String out = shell.runCommandAndGetOutputMessageAndError("sudo --help"); - sudoAvailable = !out.contains("command not found"); + try { + String[] params = new String[]{"sh", "-c", "sudo --help"}; + Process p = Runtime.getRuntime().exec(params, null, null); + try { + boolean terminated = p.waitFor(1, TimeUnit.SECONDS); + if(terminated){ + sudoAvailable = (p.exitValue() != 127); + } + } catch (InterruptedException ex) { + Logger.getLogger(AppsLauncherManager.class.getName()).log( + Level.SEVERE, "The process did no finish yet...", ex); + sudoAvailable = false; + } + } catch (IOException ex) { + Logger.getLogger(AppsLauncherManager.class.getName()).log( + Level.SEVERE, "The process could not be executed!", ex); + } } } From 78bf1bb16a206d4cf7103aaea9353c54bf2bb4e3 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 17 Feb 2022 12:30:21 +0100 Subject: [PATCH 028/173] Added the AI service --- .../main/resources/xml/ServiceDefPLATFORM.xml | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index 4c5157322..8150f945a 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2151,6 +2151,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Mon, 28 Feb 2022 11:17:19 +0100 Subject: [PATCH 029/173] Added the Artificial Intelligence service consumer and generic provider stub codes to the NMF --- ...ficialIntelligenceConsumerServiceImpl.java | 96 +++++++++++++++ ...rtificialIntelligenceAdapterInterface.java | 29 +++++ ...ficialIntelligenceProviderServiceImpl.java | 114 ++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ArtificialIntelligenceConsumerServiceImpl.java create mode 100644 core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java create mode 100644 core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ArtificialIntelligenceConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ArtificialIntelligenceConsumerServiceImpl.java new file mode 100644 index 000000000..cf5c147eb --- /dev/null +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ArtificialIntelligenceConsumerServiceImpl.java @@ -0,0 +1,96 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.platform.impl.consumer; + +import esa.mo.com.impl.util.COMServicesConsumer; +import esa.mo.helpertools.misc.ConsumerServiceImpl; +import esa.mo.helpertools.connections.SingleConnectionDetails; +import java.net.MalformedURLException; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.consumer.MALConsumer; +import org.ccsds.moims.mo.mal.structures.Blob; +import org.ccsds.moims.mo.platform.artificialintelligence.ArtificialIntelligenceHelper; +import org.ccsds.moims.mo.platform.artificialintelligence.consumer.ArtificialIntelligenceStub; + +/** + * + * @author Cesar Coelho + */ +public class ArtificialIntelligenceConsumerServiceImpl extends ConsumerServiceImpl { + + private ArtificialIntelligenceStub aiService = null; + private COMServicesConsumer comServices; + + public COMServicesConsumer getCOMServices() { + return comServices; + } + + @Override + public Object getStub() { + return this.getArtificialIntelligenceStub(); + } + + public ArtificialIntelligenceStub getArtificialIntelligenceStub() { + return this.aiService; + } + + @Override + public Object generateServiceStub(MALConsumer tmConsumer) { + return new ArtificialIntelligenceStub(tmConsumer); + } + + public ArtificialIntelligenceConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices) + throws MALException, MalformedURLException, MALInteractionException { + this(connectionDetails, comServices, null, null); + } + + public ArtificialIntelligenceConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, Blob authenticationId, + String localNamePrefix) throws MALException, MalformedURLException, + MALInteractionException { + this.connectionDetails = connectionDetails; + this.comServices = comServices; + + // Close old connection + if (tmConsumer != null) { + try { + tmConsumer.close(); + } catch (MALException ex) { + Logger.getLogger(ArtificialIntelligenceConsumerServiceImpl.class.getName()).log(Level.SEVERE, + "The consumer connection could not be closed!", ex); + } + } + + tmConsumer = connection.startService( + this.connectionDetails.getProviderURI(), + this.connectionDetails.getBrokerURI(), + this.connectionDetails.getDomain(), + ArtificialIntelligenceHelper.ARTIFICIALINTELLIGENCE_SERVICE, + authenticationId, localNamePrefix); + + this.aiService = new ArtificialIntelligenceStub(tmConsumer); + } + +} diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java new file mode 100644 index 000000000..be05e7f42 --- /dev/null +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java @@ -0,0 +1,29 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.platform.impl.provider.gen; + +import org.ccsds.moims.mo.mal.structures.Time; + +public interface ArtificialIntelligenceAdapterInterface { + + public Time setModel(); + +} diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java new file mode 100644 index 000000000..6bd38167c --- /dev/null +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -0,0 +1,114 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.platform.impl.provider.gen; + +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.com.COMHelper; +import org.ccsds.moims.mo.mal.MALContextFactory; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALHelper; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.provider.MALInteraction; +import org.ccsds.moims.mo.mal.provider.MALProvider; +import org.ccsds.moims.mo.platform.PlatformHelper; +import org.ccsds.moims.mo.platform.artificialintelligence.ArtificialIntelligenceHelper; +import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; +import esa.mo.helpertools.connections.ConnectionProvider; +import org.ccsds.moims.mo.mal.structures.File; + +public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelligenceInheritanceSkeleton { + + private static final Logger LOGGER = Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()); + private MALProvider aiServiceProvider; + private boolean initialiased = false; + private final ConnectionProvider connection = new ConnectionProvider(); + private ArtificialIntelligenceAdapterInterface adapter; + + /** + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread + * + * @param adapter The Artificial Intelligence adapter + * @throws MALException On initialisation error. + */ + public synchronized void init(ArtificialIntelligenceAdapterInterface adapter) throws MALException { + if (!initialiased) { + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { + PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + try { + ArtificialIntelligenceHelper.init(MALContextFactory.getElementFactoryRegistry()); + } catch (MALException ex) { + // nothing to be done.. + } + } + + // Shut down old service transport + if (null != aiServiceProvider) { + connection.closeAll(); + } + + this.adapter = adapter; + aiServiceProvider = connection.startService( + ArtificialIntelligenceHelper.ARTIFICIALINTELLIGENCE_SERVICE_NAME.toString(), + ArtificialIntelligenceHelper.ARTIFICIALINTELLIGENCE_SERVICE, this); + + initialiased = true; + LOGGER.info("Artificial Intelligence service READY"); + } + + /** + * Closes all running threads and releases the MAL resources. + */ + public void close() { + try { + if (null != aiServiceProvider) { + aiServiceProvider.close(); + } + + connection.closeAll(); + } catch (MALException ex) { + LOGGER.log(Level.WARNING, "Exception during close down of the provider {0}", ex); + } + } + + @Override + public void setModel(File location, MALInteraction interaction) throws MALInteractionException, MALException { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public File doInference(File inputTiles, MALInteraction interaction) throws MALInteractionException, MALException { + throw new UnsupportedOperationException("Not supported yet."); + } + +} From d67fa04711840b2351d89d16f0d3ef06279728f7 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 28 Feb 2022 11:50:03 +0100 Subject: [PATCH 030/173] Code cleanup --- .../connections/ConnectionProvider.java | 2 +- .../AutonomousADCSConsumerServiceImpl.java | 25 ++- .../consumer/CameraConsumerServiceImpl.java | 14 +- .../consumer/ClockConsumerServiceImpl.java | 3 +- .../impl/consumer/GPSConsumerServiceImpl.java | 14 +- ...pticalDataReceiverConsumerServiceImpl.java | 9 +- .../PowerControlConsumerServiceImpl.java | 9 +- ...ftwareDefinedRadioConsumerServiceImpl.java | 9 +- .../gen/AutonomousADCSAdapterInterface.java | 26 ++- .../AutonomousADCSProviderServiceImpl.java | 153 +++++++------ .../provider/gen/CameraAdapterInterface.java | 13 +- .../gen/CameraProviderServiceImpl.java | 126 ++++++----- .../provider/gen/ClockAdapterInterface.java | 3 +- .../gen/ClockProviderServiceImpl.java | 17 +- .../impl/provider/gen/GPSManager.java | 3 +- .../impl/provider/gen/GPSNMEAonlyAdapter.java | 12 +- .../provider/gen/GPSProviderServiceImpl.java | 10 +- .../OpticalDataReceiverAdapterInterface.java | 3 +- ...pticalDataReceiverProviderServiceImpl.java | 34 +-- .../gen/PowerControlProviderServiceImpl.java | 33 +-- .../SoftwareDefinedRadioAdapterInterface.java | 1 + ...ftwareDefinedRadioProviderServiceImpl.java | 90 ++++---- .../esa/mo/platform/impl/util/HelperGPS.java | 76 ++++--- .../mo/platform/impl/util/HelperIADCS100.java | 207 ++++++++++-------- .../impl/util/PlatformServicesConsumer.java | 29 ++- .../NanoSatMOConnectorImpl.java | 26 ++- 26 files changed, 534 insertions(+), 413 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java index 203c257ce..f3bd6ff56 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java @@ -308,7 +308,7 @@ public static boolean shouldInitUriFiles() { /** * Clears the URI links file if its generation is enabled */ - public static void resetURILinksFile() { + public static void resetURILinks() { globalProvidersDetailsPrimary.reset(); globalProvidersDetailsSecondary.reset(); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/AutonomousADCSConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/AutonomousADCSConsumerServiceImpl.java index 508937658..4ae8d6e00 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/AutonomousADCSConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/AutonomousADCSConsumerServiceImpl.java @@ -60,14 +60,17 @@ public Object generateServiceStub(MALConsumer tmConsumer) { return new AutonomousADCSStub(tmConsumer); } - public AutonomousADCSConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices) - throws MALException, MalformedURLException, MALInteractionException { + public AutonomousADCSConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices) throws MALException, MalformedURLException, + MALInteractionException { this(connectionDetails, comServices, null, null); } - public AutonomousADCSConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices, - Blob authenticationID, String localNamePrefix) throws MALException, MalformedURLException, - MALInteractionException { + public AutonomousADCSConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, + Blob authenticationID, + String localNamePrefix) throws MALException, MalformedURLException, + MALInteractionException { this.connectionDetails = connectionDetails; this.comServices = comServices; @@ -76,13 +79,17 @@ public AutonomousADCSConsumerServiceImpl(SingleConnectionDetails connectionDetai try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(AutonomousADCSConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(AutonomousADCSConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } - tmConsumer = connection.startService(this.connectionDetails.getProviderURI(), this.connectionDetails - .getBrokerURI(), this.connectionDetails.getDomain(), AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE, - authenticationID, localNamePrefix); + tmConsumer = connection.startService( + this.connectionDetails.getProviderURI(), + this.connectionDetails.getBrokerURI(), + this.connectionDetails.getDomain(), + AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE, + authenticationID, localNamePrefix); this.autonomousADCSService = new AutonomousADCSStub(tmConsumer); } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/CameraConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/CameraConsumerServiceImpl.java index 6114cb56f..a1520254a 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/CameraConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/CameraConsumerServiceImpl.java @@ -60,14 +60,15 @@ public Object generateServiceStub(MALConsumer tmConsumer) { return new CameraStub(tmConsumer); } - public CameraConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices) - throws MALException, MalformedURLException, MALInteractionException { + public CameraConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { this(connectionDetails, comServices, null, null); } - public CameraConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices, - Blob authenticationId, String localNamePrefix) throws MALException, MalformedURLException, - MALInteractionException { + public CameraConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, Blob authenticationId, + String localNamePrefix) throws MALException, MalformedURLException, + MALInteractionException { this.connectionDetails = connectionDetails; this.comServices = comServices; @@ -76,7 +77,8 @@ public CameraConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMS try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(CameraConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(CameraConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ClockConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ClockConsumerServiceImpl.java index 90169392a..24bfe3662 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ClockConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/ClockConsumerServiceImpl.java @@ -65,7 +65,8 @@ public ClockConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMSe try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(ClockConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(ClockConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/GPSConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/GPSConsumerServiceImpl.java index 80466ba7e..447c1058a 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/GPSConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/GPSConsumerServiceImpl.java @@ -60,14 +60,15 @@ public Object generateServiceStub(MALConsumer tmConsumer) { return new GPSStub(tmConsumer); } - public GPSConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices) - throws MALException, MalformedURLException, MALInteractionException { + public GPSConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { this(connectionDetails, comServices, null, null); } - public GPSConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices, - Blob authenticationId, String localNamePrefix) throws MALException, MalformedURLException, - MALInteractionException { + public GPSConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, + Blob authenticationId, + String localNamePrefix) throws MALException, MalformedURLException, MALInteractionException { this.connectionDetails = connectionDetails; this.comServices = comServices; @@ -76,7 +77,8 @@ public GPSConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServ try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(GPSConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(GPSConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/OpticalDataReceiverConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/OpticalDataReceiverConsumerServiceImpl.java index 57ae7b745..8cda6f9db 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/OpticalDataReceiverConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/OpticalDataReceiverConsumerServiceImpl.java @@ -61,13 +61,13 @@ public Object generateServiceStub(MALConsumer tmConsumer) { } public OpticalDataReceiverConsumerServiceImpl(SingleConnectionDetails connectionDetails, - COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { + COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { this(connectionDetails, comServices, null, null); } public OpticalDataReceiverConsumerServiceImpl(SingleConnectionDetails connectionDetails, - COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) throws MALException, - MalformedURLException, MALInteractionException { + COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) + throws MALException, MalformedURLException, MALInteractionException { this.connectionDetails = connectionDetails; this.comServices = comServices; @@ -76,7 +76,8 @@ public OpticalDataReceiverConsumerServiceImpl(SingleConnectionDetails connection try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(OpticalDataReceiverConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(OpticalDataReceiverConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/PowerControlConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/PowerControlConsumerServiceImpl.java index 29759fbdd..f60eaae55 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/PowerControlConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/PowerControlConsumerServiceImpl.java @@ -65,9 +65,9 @@ public PowerControlConsumerServiceImpl(SingleConnectionDetails connectionDetails this(connectionDetails, comServices, null, null); } - public PowerControlConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices, - Blob authenticationId, String localNamePrefix) throws MALException, MalformedURLException, - MALInteractionException { + public PowerControlConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) + throws MALException, MalformedURLException, MALInteractionException { this.connectionDetails = connectionDetails; this.comServices = comServices; @@ -76,7 +76,8 @@ public PowerControlConsumerServiceImpl(SingleConnectionDetails connectionDetails try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(PowerControlConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(PowerControlConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/SoftwareDefinedRadioConsumerServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/SoftwareDefinedRadioConsumerServiceImpl.java index c1f309e32..720fbddea 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/SoftwareDefinedRadioConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/consumer/SoftwareDefinedRadioConsumerServiceImpl.java @@ -61,13 +61,13 @@ public Object generateServiceStub(MALConsumer tmConsumer) { } public SoftwareDefinedRadioConsumerServiceImpl(SingleConnectionDetails connectionDetails, - COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { + COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { this(connectionDetails, comServices, null, null); } public SoftwareDefinedRadioConsumerServiceImpl(SingleConnectionDetails connectionDetails, - COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) throws MALException, - MalformedURLException, MALInteractionException { + COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) + throws MALException, MalformedURLException, MALInteractionException { this.connectionDetails = connectionDetails; this.comServices = comServices; @@ -76,7 +76,8 @@ public SoftwareDefinedRadioConsumerServiceImpl(SingleConnectionDetails connectio try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(SoftwareDefinedRadioConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(SoftwareDefinedRadioConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSAdapterInterface.java index 9e7d9067e..8906dfbb3 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSAdapterInterface.java @@ -41,13 +41,13 @@ public interface AutonomousADCSAdapterInterface { boolean isUnitAvailable(); /** - * The setDesiredAttitude operation shall set a certain attitude based on the AttitudeMode - * descriptor + * The setDesiredAttitude operation shall set a certain attitude based on + * the AttitudeMode descriptor * * @param attitude * @throws IOException in case of failure on the interface - * @throws UnsupportedOperationException if the implementation does not support the requested ADCS - * mode + * @throws UnsupportedOperationException if the implementation does not + * support the requested ADCS mode */ void setDesiredAttitude(AttitudeMode attitude) throws IOException, UnsupportedOperationException; @@ -59,8 +59,8 @@ public interface AutonomousADCSAdapterInterface { void unset() throws IOException; /** - * The getAttitudeTelemetry returns an object representing the attitude information provided by an - * ADCS unit + * The getAttitudeTelemetry returns an object representing the attitude + * information provided by an ADCS unit * * @return The Attitude Telemetry from the ADCS * @throws IOException @@ -68,8 +68,8 @@ public interface AutonomousADCSAdapterInterface { AttitudeTelemetry getAttitudeTelemetry() throws IOException; /** - * The getActuatorsTelemetry returns an object representing the actuators information provided by - * an ADCS unit + * The getActuatorsTelemetry returns an object representing the actuators + * information provided by an ADCS unit * * @return The Attitude Telemetry from the ADCS * @throws IOException @@ -80,15 +80,16 @@ public interface AutonomousADCSAdapterInterface { * Validate Attitude Descriptor * * @param attitude requested attitude mode descriptor to be validated - * @return null if attitude descriptor is valid. Human readable string with error message if - * validation fails. + * @return null if attitude descriptor is valid. Human readable string with + * error message if validation fails. */ String validateAttitudeDescriptor(AttitudeMode attitude); /** * Get active attitude mode. * - * @return Descriptor of the attitude currently set in the ADCS or NULL if none (IDLE) + * @return Descriptor of the attitude currently set in the ADCS or NULL if + * none (IDLE) */ AttitudeMode getActiveAttitudeMode(); @@ -102,7 +103,8 @@ public interface AutonomousADCSAdapterInterface { * @param wheelV speed for wheel v * @param wheelW speed for wheel w */ - void setAllReactionWheelSpeeds(float wheelX, float wheelY, float wheelZ, float wheelU, float wheelV, float wheelW); + void setAllReactionWheelSpeeds(float wheelX, float wheelY, float wheelZ, float wheelU, + float wheelV, float wheelW); /** * Sets the speed of one Reaction wheel diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java index 2c2c18b3b..2088b13d1 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java @@ -76,7 +76,8 @@ */ public class AutonomousADCSProviderServiceImpl extends AutonomousADCSInheritanceSkeleton { - private final static Logger LOGGER = Logger.getLogger(AutonomousADCSProviderServiceImpl.class.getName()); + private final static Logger LOGGER = Logger.getLogger( + AutonomousADCSProviderServiceImpl.class.getName()); private final static Duration MINIMUM_MONITORING_PERIOD = new Duration(0.1); // 100 Milliseconds private int resultCacheValidityMs; private MALProvider autonomousADCSServiceProvider; @@ -100,22 +101,22 @@ public class AutonomousADCSProviderServiceImpl extends AutonomousADCSInheritance private long lastActuatorsTmTime = 0; /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread * * @param comServices COM services provider - * @param adapter The adapter for the ADCS unit interaction + * @param adapter The adapter for the ADCS unit interaction * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, AutonomousADCSAdapterInterface adapter) - throws MALException { + public synchronized void init(COMServicesProvider comServices, + AutonomousADCSAdapterInterface adapter) throws MALException { if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -123,16 +124,21 @@ public synchronized void init(COMServicesProvider comServices, AutonomousADCSAda COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE_NAME) == null) { AutonomousADCSHelper.init(MALContextFactory.getElementFactoryRegistry()); } } resultCacheValidityMs = Integer.parseInt(System.getProperty(Const.PLATFORM_IADCS_CACHING_PERIOD, "1000")); publisher = createMonitorAttitudePublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton - .getSourceSessionName(), QoSLevel.BESTEFFORT, null, new UInteger(0)); + ConfigurationProviderSingleton.getNetwork(), + SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), + QoSLevel.BESTEFFORT, + null, + new UInteger(0)); // Shut down old service transport if (null != autonomousADCSServiceProvider) { @@ -140,8 +146,9 @@ public synchronized void init(COMServicesProvider comServices, AutonomousADCSAda } this.adapter = adapter; - autonomousADCSServiceProvider = connection.startService(AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE_NAME - .toString(), AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE, true, this); + autonomousADCSServiceProvider = connection.startService( + AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE_NAME.toString(), + AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE, true, this); initialiased = true; LOGGER.info("AutonomousADCS service READY"); @@ -186,13 +193,13 @@ private void publishCurrentAttitude() { try { final AttitudeTelemetry attitudeTelemetry = getAttitudeTelemetry(); - final AttitudeTelemetryList attitudeTelemetryList = (AttitudeTelemetryList) HelperMisc.element2elementList( - attitudeTelemetry); + final AttitudeTelemetryList attitudeTelemetryList + = (AttitudeTelemetryList) HelperMisc.element2elementList(attitudeTelemetry); attitudeTelemetryList.add(attitudeTelemetry); final ActuatorsTelemetry actuatorsTelemetry = getActuatorsTelemetry(); - final ActuatorsTelemetryList actuatorsTelemetryList = (ActuatorsTelemetryList) HelperMisc - .element2elementList(actuatorsTelemetry); + final ActuatorsTelemetryList actuatorsTelemetryList + = (ActuatorsTelemetryList) HelperMisc.element2elementList(actuatorsTelemetry); actuatorsTelemetryList.add(actuatorsTelemetry); final AttitudeMode activeAttitudeMode = getActiveAttitudeMode(); @@ -202,7 +209,8 @@ private void publishCurrentAttitude() { // Pick a dummy concrete type type just to fill it with a null value attitudeModeList = new AttitudeModeBDotList(); } else { - attitudeModeList = (AttitudeModeList) HelperMisc.element2elementList(activeAttitudeMode); + attitudeModeList = (AttitudeModeList) HelperMisc.element2elementList( + activeAttitudeMode); } attitudeModeList.add(activeAttitudeMode); @@ -213,29 +221,30 @@ private void publishCurrentAttitude() { final Time timestamp = HelperTime.getTimestampMillis(); final UpdateHeaderList hdrlst = new UpdateHeaderList(); hdrlst.add(new UpdateHeader(timestamp, connection.getConnectionDetails().getProviderURI(), - UpdateType.UPDATE, ekey)); + UpdateType.UPDATE, ekey)); - publisher.publish(hdrlst, attitudeTelemetryList, actuatorsTelemetryList, durationList, attitudeModeList); + publisher.publish(hdrlst, attitudeTelemetryList, actuatorsTelemetryList, durationList, + attitudeModeList); } catch (IOException | IllegalArgumentException | MALException | MALInteractionException ex) { LOGGER.log(Level.SEVERE, "Error when trying to publish data!", ex); } } @Override - public void enableMonitoring(Boolean enableGeneration, Duration monitoringInterval, MALInteraction interaction) - throws MALInteractionException, MALException { + public void enableMonitoring(Boolean enableGeneration, Duration monitoringInterval, + MALInteraction interaction) throws MALInteractionException, MALException { if (!enableGeneration) { stopGeneration(); return; } if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } // Is the requested streaming rate less than the minimum period? if (monitoringInterval == null || monitoringInterval.getValue() < MINIMUM_MONITORING_PERIOD.getValue()) { throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, - MINIMUM_MONITORING_PERIOD)); + MINIMUM_MONITORING_PERIOD)); } monitoringPeriod = (int) (monitoringInterval.getValue() * 1000); // In milliseconds @@ -245,30 +254,32 @@ public void enableMonitoring(Boolean enableGeneration, Duration monitoringInterv @Override public GetStatusResponse getStatus(MALInteraction interaction) throws MALInteractionException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } try { final AttitudeTelemetry attitudeTelemetry = getAttitudeTelemetry(); final ActuatorsTelemetry actuatorsTelemetry = getActuatorsTelemetry(); final AttitudeMode activeAttitudeMode = getActiveAttitudeMode(); - return new GetStatusResponse(attitudeTelemetry, actuatorsTelemetry, getAttitudeControlRemainingDuration(), - generationEnabled, new Duration(monitoringPeriod / 1000.f), activeAttitudeMode); + return new GetStatusResponse(attitudeTelemetry, actuatorsTelemetry, + getAttitudeControlRemainingDuration(), + generationEnabled, new Duration(monitoringPeriod / 1000.f), activeAttitudeMode); } catch (IOException ex) { Logger.getLogger(AutonomousADCSProviderServiceImpl.class.getName()).log(Level.SEVERE, - "Error when producing getStatus response", ex); - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + "Error when producing getStatus response", ex); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } } private AttitudeTelemetry getAttitudeTelemetry() throws IOException { if (System.currentTimeMillis() - lastAttitudeTmTime < resultCacheValidityMs) { - if (lastAttitudeTm != null) + if (lastAttitudeTm != null) { return lastAttitudeTm; - else + } else { throw lastAttitudeTmException; + } } try { lastAttitudeTm = adapter.getAttitudeTelemetry(); @@ -285,10 +296,11 @@ private AttitudeTelemetry getAttitudeTelemetry() throws IOException { private ActuatorsTelemetry getActuatorsTelemetry() throws IOException { if (System.currentTimeMillis() - lastActuatorsTmTime < resultCacheValidityMs) { - if (lastActuatorsTm != null) + if (lastActuatorsTm != null) { return lastActuatorsTm; - else + } else { throw lastActuatorsTmException; + } } try { lastActuatorsTm = adapter.getActuatorsTelemetry(); @@ -310,10 +322,10 @@ private AttitudeMode getActiveAttitudeMode() { @Override public synchronized void setDesiredAttitude(final Duration duration, AttitudeMode desiredAttitude, - MALInteraction interaction) throws MALInteractionException, MALException { + MALInteraction interaction) throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } if (desiredAttitude == null) { @@ -325,16 +337,16 @@ public synchronized void setDesiredAttitude(final Duration duration, AttitudeMod unsetAttitude(); } else { if (adcsInUse) { // Is the ADCS unit in use? - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_IN_USE_ERROR_NUMBER, - getAttitudeControlRemainingDuration())); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_IN_USE_ERROR_NUMBER, getAttitudeControlRemainingDuration())); } // Validate the attitude definition... String validationResult = adapter.validateAttitudeDescriptor(desiredAttitude); if (validationResult != null) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, HelperAttributes - .javaType2Attribute(validationResult))); + throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, + HelperAttributes.javaType2Attribute(validationResult))); } try { @@ -343,8 +355,8 @@ public synchronized void setDesiredAttitude(final Duration duration, AttitudeMod } catch (IOException ex) { LOGGER.log(Level.SEVERE, "Error when setting desired attitude.", ex); // Operation not supported by the implementation... - throw new MALInteractionException(new MALStandardError(MALHelper.UNSUPPORTED_OPERATION_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + MALHelper.UNSUPPORTED_OPERATION_ERROR_NUMBER, null)); } adcsInUse = true; @@ -358,7 +370,8 @@ private void unsetAttitude() { adapter.unset(); adcsInUse = false; } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Cannot disengage attitude control.", ex); + LOGGER.log(Level.SEVERE, + "Cannot disengage attitude control.", ex); } } @@ -415,11 +428,11 @@ public synchronized Duration getAttitudeControlRemainingDuration() { } @Override - public void setReactionWheelSpeed(ReactionWheelIdentifier wheel, Float speed, MALInteraction interaction) - throws MALInteractionException, MALException { + public void setReactionWheelSpeed(ReactionWheelIdentifier wheel, Float speed, + MALInteraction interaction) throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } adapter.setReactionWheelSpeed(wheel, speed); @@ -427,64 +440,66 @@ public void setReactionWheelSpeed(ReactionWheelIdentifier wheel, Float speed, MA } @Override - public void setAllReactionWheelSpeeds(Float speedX, Float speedY, Float speedZ, Float speedU, Float speedV, - Float speedW, MALInteraction interaction) throws MALInteractionException, MALException { + public void setAllReactionWheelSpeeds(Float speedX, Float speedY, Float speedZ, Float speedU, + Float speedV, Float speedW, MALInteraction interaction) throws MALInteractionException, + MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } adapter.setAllReactionWheelSpeeds(speedX, speedY, speedZ, speedU, speedV, speedW); } @Override - public void setAllReactionWheelParameters(ReactionWheelParameters parameters, MALInteraction interaction) - throws MALInteractionException, MALException { + public void setAllReactionWheelParameters(ReactionWheelParameters parameters, + MALInteraction interaction) throws MALInteractionException, MALException { adapter.setAllReactionWheelParameters(parameters); } @Override public void setAllMagnetorquersDipoleMoments(Float dipoleX, Float dipoleY, Float dipoleZ, - MALInteraction interaction) throws MALInteractionException, MALException { + MALInteraction interaction) throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } adapter.setAllMagnetorquersDipoleMoments(dipoleX, dipoleY, dipoleZ); } @Override - public ReactionWheelParameters getAllReactionWheelParameters(MALInteraction interaction) - throws MALInteractionException, MALException { + public ReactionWheelParameters getAllReactionWheelParameters(MALInteraction interaction) throws + MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } return adapter.getAllReactionWheelParameters(); } - private static class PublishInteractionListener implements MALPublishInteractionListener { + private class PublishInteractionListener implements MALPublishInteractionListener { @Override public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + throws MALException { LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); } @Override public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + final Map qosProperties) + throws MALException { LOGGER.warning("PublishInteractionListener::publishErrorReceived"); } @Override public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + throws MALException { LOGGER.fine("PublishInteractionListener::publishRegisterAckReceived"); } @Override public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + final Map qosProperties) throws MALException { LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java index be9f51764..8cd56a8b2 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java @@ -58,12 +58,15 @@ public interface CameraAdapterInterface { Picture takeAutoExposedPicture(final CameraSettings settings) throws IOException, MALException; /** - * The getMinimumPeriod method shall return the duration of taking a picture. This value is - * intended to be used to limit the number of consecutive calls for the takePicture method and - * therefore the minimum period of the stream shall be the duration of taking a picture. This - * method should be a static method however Java 6 does not allow static methods in interfaces. + * The getMinimumPeriod method shall return the duration of taking a + * picture. This value is intended to be used to limit the number of + * consecutive calls for the takePicture method and therefore the minimum + * period of the stream shall be the duration of taking a picture. This + * method should be a static method however Java 6 does not allow static + * methods in interfaces. * - * @return The minimum period of the stream. Or the duration of taking a picture. + * @return The minimum period of the stream. Or the duration of taking a + * picture. */ Duration getMinimumPeriod(); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java index beeb73d11..23e58d22f 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java @@ -89,20 +89,22 @@ public class CameraProviderServiceImpl extends CameraInheritanceSkeleton { private PictureFormatList availableFormats; /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread * * @param comServices - * @param adapter The Camera adapter + * @param adapter The Camera adapter * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, CameraAdapterInterface adapter) throws MALException { + public synchronized void init(COMServicesProvider comServices, + CameraAdapterInterface adapter) throws MALException { if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -110,15 +112,20 @@ public synchronized void init(COMServicesProvider comServices, CameraAdapterInte COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(CameraHelper.CAMERA_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(CameraHelper.CAMERA_SERVICE_NAME) == null) { CameraHelper.init(MALContextFactory.getElementFactoryRegistry()); } } publisher = createPicturesStreamPublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton - .getSourceSessionName(), QoSLevel.BESTEFFORT, null, new UInteger(0)); + ConfigurationProviderSingleton.getNetwork(), + SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), + QoSLevel.BESTEFFORT, + null, + new UInteger(0)); // Shut down old service transport if (null != cameraServiceProvider) { @@ -127,8 +134,9 @@ public synchronized void init(COMServicesProvider comServices, CameraAdapterInte this.adapter = adapter; minimumPeriod = this.adapter.getMinimumPeriod(); - cameraServiceProvider = connection.startService(CameraHelper.CAMERA_SERVICE_NAME.toString(), - CameraHelper.CAMERA_SERVICE, this); + cameraServiceProvider = connection.startService( + CameraHelper.CAMERA_SERVICE_NAME.toString(), + CameraHelper.CAMERA_SERVICE, this); availableFormats = adapter.getAvailableFormats(); running = true; @@ -148,11 +156,13 @@ public void close() { connection.closeAll(); running = false; } catch (MALException ex) { - LOGGER.log(Level.WARNING, "Exception during close down of the provider {0}", ex); + LOGGER.log(Level.WARNING, + "Exception during close down of the provider {0}", ex); } } - private void streamPicturesUpdate(final Identifier firstEntityKey, final CameraSettings settings) { + private void streamPicturesUpdate(final Identifier firstEntityKey, + final CameraSettings settings) { try { final Long objId; Picture picture = null; @@ -178,29 +188,32 @@ private void streamPicturesUpdate(final Identifier firstEntityKey, final CameraS } else { LOGGER.log(Level.FINER, "Generating streaming Picture update with objId: {0}", objId); - final EntityKey ekey = new EntityKey(firstEntityKey, objId, settings.getResolution().getWidth() - .getValue(), settings.getResolution().getHeight().getValue()); + final EntityKey ekey = new EntityKey(firstEntityKey, objId, + settings.getResolution().getWidth().getValue(), + settings.getResolution().getHeight().getValue()); final UpdateHeaderList hdrlst = new UpdateHeaderList(); - hdrlst.add(new UpdateHeader(HelperTime.getTimestampMillis(), connection.getConnectionDetails() - .getProviderURI(), UpdateType.UPDATE, ekey)); + hdrlst.add(new UpdateHeader(HelperTime.getTimestampMillis(), + connection.getConnectionDetails().getProviderURI(), UpdateType.UPDATE, ekey)); PictureList picList = new PictureList(); picList.add(picture); publisher.publish(hdrlst, picList); } } catch (IllegalArgumentException | MALException | MALInteractionException ex) { - LOGGER.log(Level.WARNING, "Exception during publishing process on the provider {0}", ex); + LOGGER.log(Level.WARNING, + "Exception during publishing process on the provider {0}", ex); } } private void isCapturePossible(final CameraSettings settings) throws MALInteractionException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } if (cameraInUse) { // Is the Camera unit in use? - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_IN_USE_ERROR_NUMBER, null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_IN_USE_ERROR_NUMBER, null)); } final PixelResolutionList availableResolutions = adapter.getAvailableResolutions(); boolean isResolutionAvailable = false; @@ -215,8 +228,8 @@ private void isCapturePossible(final CameraSettings settings) throws MALInteract // If not, then send the available resolutions to the consumer so they can pick... if (!isResolutionAvailable) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, - availableResolutions)); + throw new MALInteractionException(new MALStandardError( + COMHelper.INVALID_ERROR_NUMBER, availableResolutions)); } boolean isFormatsAvailable = false; @@ -229,13 +242,15 @@ private void isCapturePossible(final CameraSettings settings) throws MALInteract // If not, then send the available formats to the consumer so they can pick... if (!isFormatsAvailable) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, availableFormats)); + throw new MALInteractionException(new MALStandardError( + COMHelper.INVALID_ERROR_NUMBER, availableFormats)); } } @Override - public void enableStream(Boolean enable, final Duration streamingRate, final Identifier firstEntityKey, - final CameraSettings settings, MALInteraction interaction) throws MALInteractionException, MALException { + public void enableStream(Boolean enable, final Duration streamingRate, + final Identifier firstEntityKey, final CameraSettings settings, + MALInteraction interaction) throws MALInteractionException, MALException { if (!enable) { cameraInUse = false; publishTimer.stopLast(); @@ -246,20 +261,22 @@ public void enableStream(Boolean enable, final Duration streamingRate, final Ide // Is the requested streaming rate less than the minimum period? if (streamingRate.getValue() < minimumPeriod.getValue()) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, minimumPeriod)); + throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, + minimumPeriod)); } // Is the requested streaming rate less than the service lowest minimum period? if (streamingRate.getValue() < serviceLowestMinimumPeriod.getValue()) { // This is a protection to avoid having crazy implementations with super low streaming rates! throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, - serviceLowestMinimumPeriod)); + serviceLowestMinimumPeriod)); } isCapturePossible(settings); - if (firstEntityKey.getValue() == null || "*".equals(firstEntityKey.getValue()) || "".equals(firstEntityKey - .getValue())) { + if (firstEntityKey.getValue() == null + || "*".equals(firstEntityKey.getValue()) + || "".equals(firstEntityKey.getValue())) { throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, null)); } @@ -279,66 +296,63 @@ public void enableStream(Boolean enable, final Duration streamingRate, final Ide } @Override - public Picture previewPicture(MALInteraction interaction) throws MALInteractionException, MALException { + public Picture previewPicture(MALInteraction interaction) + throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } // Get some preview Picture from the camera... synchronized (lock) { try { return adapter.getPicturePreview(); } catch (IOException ex) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } } } @Override public void takePicture(final CameraSettings settings, TakePictureInteraction interaction) - throws MALInteractionException, MALException { + throws MALInteractionException, MALException { isCapturePossible(settings); interaction.sendAcknowledgement(); synchronized (lock) { try { Picture picture = adapter.takePicture(settings); - LOGGER.log(Level.INFO, "The picture has been taken!"); - interaction.sendResponse(picture); LOGGER.log(Level.INFO, "The picture has been sent!"); - } catch (IOException ex) { - interaction.sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + interaction.sendError(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } } } @Override - public void takeAutoExposedPicture(CameraSettings settings, TakeAutoExposedPictureInteraction interaction) - throws MALInteractionException, MALException { + public void takeAutoExposedPicture(CameraSettings settings, + TakeAutoExposedPictureInteraction interaction) throws MALInteractionException, MALException { isCapturePossible(settings); interaction.sendAcknowledgement(); synchronized (lock) { try { Picture picture = adapter.takeAutoExposedPicture(settings); - LOGGER.log(Level.INFO, "The picture has been taken!"); - interaction.sendResponse(picture); LOGGER.log(Level.INFO, "The picture has been sent!"); - } catch (IOException ex) { - interaction.sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + interaction.sendError(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } } } @Override - public GetPropertiesResponse getProperties(MALInteraction interaction) throws MALInteractionException, - MALException { + public GetPropertiesResponse getProperties(MALInteraction interaction) throws + MALInteractionException, MALException { final PixelResolutionList availableResolutions = adapter.getAvailableResolutions(); String extraInfo = adapter.getExtraInfo(); @@ -348,26 +362,26 @@ public GetPropertiesResponse getProperties(MALInteraction interaction) throws MA public static final class PublishInteractionListener implements MALPublishInteractionListener { @Override - public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + public void publishDeregisterAckReceived(final MALMessageHeader header, + final Map qosProperties) throws MALException { LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); } @Override - public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + public void publishErrorReceived(final MALMessageHeader header, + final MALErrorBody body, final Map qosProperties) throws MALException { LOGGER.warning("PublishInteractionListener::publishErrorReceived"); } @Override - public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + public void publishRegisterAckReceived(final MALMessageHeader header, + final Map qosProperties) throws MALException { LOGGER.log(Level.INFO, "Registration Ack: {0}", header.toString()); } @Override - public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + public void publishRegisterErrorReceived(final MALMessageHeader header, + final MALErrorBody body, final Map qosProperties) throws MALException { LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockAdapterInterface.java index 0988b674b..4b0f4186b 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockAdapterInterface.java @@ -23,7 +23,8 @@ import org.ccsds.moims.mo.mal.structures.Time; public interface ClockAdapterInterface { + public Time getTime(); public int getTimeFactor(); -} \ No newline at end of file +} diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java index 926034fae..aef96c0f2 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java @@ -44,9 +44,10 @@ public class ClockProviderServiceImpl extends ClockInheritanceSkeleton { private ClockAdapterInterface adapter; /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread * - * @param adapter The Clock adapter + * @param adapter The Clock adapter * @throws MALException On initialisation error. */ public synchronized void init(ClockAdapterInterface adapter) throws MALException { @@ -55,8 +56,8 @@ public synchronized void init(ClockAdapterInterface adapter) throws MALException MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -77,16 +78,16 @@ public synchronized void init(ClockAdapterInterface adapter) throws MALException } this.adapter = adapter; - clockServiceProvider = connection.startService(ClockHelper.CLOCK_SERVICE_NAME.toString(), - ClockHelper.CLOCK_SERVICE, this); + clockServiceProvider = connection.startService( + ClockHelper.CLOCK_SERVICE_NAME.toString(), ClockHelper.CLOCK_SERVICE, this); initialiased = true; LOGGER.info("Clock service READY"); } /** - * Closes all running threads and releases the MAL resources. - */ + * Closes all running threads and releases the MAL resources. + */ public void close() { try { if (null != clockServiceProvider) { diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSManager.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSManager.java index bae5702a1..dfe71e574 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSManager.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSManager.java @@ -118,7 +118,8 @@ public boolean delete(final Long objId) { return this.deleteDef(objId); } - protected Long storeAndGenerateNearbyPositionAlertId(final Boolean inside, final Long objId, final URI uri) { + protected Long storeAndGenerateNearbyPositionAlertId(final Boolean inside, + final Long objId, final URI uri) { if (super.getArchiveService() != null) { BooleanList isEnteringList = new BooleanList(); isEnteringList.add(inside); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java index 10d8acff2..2a8a7e268 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java @@ -33,6 +33,7 @@ * @author Cesar Coelho */ public abstract class GPSNMEAonlyAdapter implements GPSAdapterInterface { + private static final Logger LOGGER = Logger.getLogger(GPSNMEAonlyAdapter.class.getName()); private final int resultCacheValidityMs; @@ -47,8 +48,9 @@ public GPSNMEAonlyAdapter() { @Override public synchronized Position getCurrentPosition() { - if (System.currentTimeMillis() - lastPositionTime < resultCacheValidityMs) + if (System.currentTimeMillis() - lastPositionTime < resultCacheValidityMs) { return lastPosition; + } String nmeaLog = ""; try { lastPosition = null; @@ -60,9 +62,8 @@ public synchronized Position getCurrentPosition() { lastPosition = HelperGPS.gpggalong2Position(nmeaLog); } } catch (IOException ex) { - LOGGER.log(Level.FINE, - "The current position could not be retrieved! The receiver is likely offline or not returning proper position.", - ex); + LOGGER.log(Level.FINE, "The current position could not be retrieved! " + + "The receiver is likely offline or not returning proper position.", ex); } lastPositionTime = System.currentTimeMillis(); return lastPosition; @@ -70,8 +71,9 @@ public synchronized Position getCurrentPosition() { @Override public SatelliteInfoList getSatelliteInfoList() { - if (System.currentTimeMillis() - lastSatInfoTime < resultCacheValidityMs) + if (System.currentTimeMillis() - lastSatInfoTime < resultCacheValidityMs) { return lastSatInfo; + } try { lastSatInfo = null; String nmeaLog = HelperGPS.sanitizeNMEALog(this.getNMEASentence("LOG GPGSV\r\n").trim()); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java index ff6a1a4b6..39b824580 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java @@ -217,14 +217,8 @@ private void publishNearbyPositionUpdate(final Long objId, final Boolean isInsid } } - LOGGER.log(Level.FINER, "Generating GPS Nearby Position update for: {0} (Identifier: {1})", new Object[]{ - objId, - new Identifier( - manager - .get( - objId) - .getName() - .toString())}); + LOGGER.log(Level.FINER, "Generating GPS Nearby Position update for: {0} (Identifier: {1})", + new Object[]{objId, new Identifier(manager.get(objId).getName().toString())}); final URI uri = connection.getConnectionDetails().getProviderURI(); final Long pValObjId = manager.storeAndGenerateNearbyPositionAlertId(isInside, objId, uri); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverAdapterInterface.java index 8a52a698d..9b305c74a 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverAdapterInterface.java @@ -36,7 +36,8 @@ public interface OpticalDataReceiverAdapterInterface { boolean isUnitAvailable(); /** - * Synchronous method to records data by the optical receiver and return the recorded buffer. + * Synchronous method to records data by the optical receiver and return the + * recorded buffer. * * @param recordingLength The duration of the recording. * @return Raw buffer of the data received from the optical receiver. diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java index 0cf6d328c..ef3383469 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java @@ -48,7 +48,7 @@ public class OpticalDataReceiverProviderServiceImpl extends OpticalDataReceiverI private boolean initialiased = false; private final ConnectionProvider connection = new ConnectionProvider(); private OpticalDataReceiverAdapterInterface adapter; - public static final double MAX_RECORDING_DURATION = 10.0; // 10 seconds + public static double MAX_RECORDING_DURATION = 10.0; // 10 seconds /** * Initializes the Optical Receiver Provider service @@ -58,13 +58,12 @@ public class OpticalDataReceiverProviderServiceImpl extends OpticalDataReceiverI */ public synchronized void init(OpticalDataReceiverAdapterInterface adapter) throws MALException { if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -72,8 +71,9 @@ public synchronized void init(OpticalDataReceiverAdapterInterface adapter) throw COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE_NAME) == null) { OpticalDataReceiverHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -85,12 +85,12 @@ public synchronized void init(OpticalDataReceiverAdapterInterface adapter) throw this.adapter = adapter; opticalDataReceiverServiceProvider = connection.startService( - OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE_NAME.toString(), - OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE, this); + OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE_NAME.toString(), + OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE, this); initialiased = true; Logger.getLogger(OpticalDataReceiverProviderServiceImpl.class.getName()).info( - "Optical Data Receiver service READY"); + "Optical Data Receiver service READY"); } /** @@ -103,18 +103,18 @@ public void close() { } connection.closeAll(); } catch (MALException ex) { - Logger.getLogger(OpticalDataReceiverProviderServiceImpl.class.getName()).log(Level.WARNING, - "Exception during close down of the provider {0}", ex); + Logger.getLogger(OpticalDataReceiverProviderServiceImpl.class.getName()).log( + Level.WARNING, "Exception during close down of the provider {0}", ex); } } @Override - public void recordSamples(Duration recordingDuration, RecordSamplesInteraction interaction) - throws MALInteractionException, MALException { + public void recordSamples(Duration recordingDuration, RecordSamplesInteraction interaction) + throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { // TODO Add error code to the service spec - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } if (recordingDuration == null || recordingDuration.getValue() == 0.0) { // TODO Add error code to the service spec @@ -122,8 +122,8 @@ public void recordSamples(Duration recordingDuration, RecordSamplesInteraction i return; } if (recordingDuration.getValue() > MAX_RECORDING_DURATION) { - interaction.sendError(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, new Duration( - MAX_RECORDING_DURATION))); + interaction.sendError(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, + new Duration(MAX_RECORDING_DURATION))); return; } interaction.sendAcknowledgement(); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java index 9c436f844..f8c7cebbf 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java @@ -53,7 +53,8 @@ public class PowerControlProviderServiceImpl extends PowerControlInheritanceSkel private boolean running = false; private final ConnectionProvider connection = new ConnectionProvider(); private PowerControlAdapterInterface adapter; - private static final Logger LOGGER = Logger.getLogger(PowerControlProviderServiceImpl.class.getName()); + private static final Logger LOGGER = Logger.getLogger( + PowerControlProviderServiceImpl.class.getName()); /** * Initializes the Power Control service. @@ -63,13 +64,12 @@ public class PowerControlProviderServiceImpl extends PowerControlInheritanceSkel */ public synchronized void init(PowerControlAdapterInterface adapter) throws MALException { if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -77,8 +77,9 @@ public synchronized void init(PowerControlAdapterInterface adapter) throws MALEx COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(PowerControlHelper.POWERCONTROL_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(PowerControlHelper.POWERCONTROL_SERVICE_NAME) == null) { PowerControlHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -89,8 +90,9 @@ public synchronized void init(PowerControlAdapterInterface adapter) throws MALEx } this.adapter = adapter; - powerControlServiceProvider = connection.startService(PowerControlHelper.POWERCONTROL_SERVICE_NAME.toString(), - PowerControlHelper.POWERCONTROL_SERVICE, this); + powerControlServiceProvider = connection.startService( + PowerControlHelper.POWERCONTROL_SERVICE_NAME.toString(), + PowerControlHelper.POWERCONTROL_SERVICE, this); running = true; initialiased = true; @@ -114,8 +116,8 @@ public void close() { } @Override - public DeviceList listDevices(IdentifierList names, MALInteraction interaction) throws MALInteractionException, - MALException { + public DeviceList listDevices(IdentifierList names, MALInteraction interaction) + throws MALInteractionException, MALException { if (names == null) { throw new MALException("IdentifierList cannot be empty."); } @@ -136,20 +138,21 @@ public DeviceList listDevices(IdentifierList names, MALInteraction interaction) } } if (!unkIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); + throw new MALInteractionException(new MALStandardError( + MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); } return ret; } @Override - public void enableDevices(DeviceList devices, MALInteraction interaction) throws MALInteractionException, - MALException { + public void enableDevices(DeviceList devices, MALInteraction interaction) + throws MALInteractionException, MALException { try { adapter.enableDevices(devices); } catch (IOException ex) { LOGGER.log(Level.SEVERE, "adapter.enableDevices failed", ex); - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioAdapterInterface.java index c21297df7..5eb5ae437 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioAdapterInterface.java @@ -54,6 +54,7 @@ public interface SoftwareDefinedRadioAdapterInterface { /** * Gets SDR I/Q buffer + * * @return Buffer of I/Q data */ IQComponents getIQComponents(); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java index b55a5483f..b5fc51b5a 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java @@ -88,8 +88,8 @@ public synchronized void init(SoftwareDefinedRadioAdapterInterface adapter) thro MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -97,15 +97,21 @@ public synchronized void init(SoftwareDefinedRadioAdapterInterface adapter) thro COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE_NAME) == null) { SoftwareDefinedRadioHelper.init(MALContextFactory.getElementFactoryRegistry()); } } - publisher = createStreamRadioPublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton - .getSourceSessionName(), QoSLevel.BESTEFFORT, null, new UInteger(0)); + publisher = createStreamRadioPublisher( + ConfigurationProviderSingleton.getDomain(), + ConfigurationProviderSingleton.getNetwork(), + SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), + QoSLevel.BESTEFFORT, + null, + new UInteger(0)); // Shut down old service transport if (null != softwareDefinedRadioServiceProvider) { @@ -114,13 +120,13 @@ public synchronized void init(SoftwareDefinedRadioAdapterInterface adapter) thro this.adapter = adapter; softwareDefinedRadioServiceProvider = connection.startService( - SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE_NAME.toString(), - SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE, this); + SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE_NAME.toString(), + SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE, this); running = true; initialiased = true; Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).info( - "Software-defined Radio service READY"); + "Software-defined Radio service READY"); } /** @@ -135,8 +141,8 @@ public void close() { connection.closeAll(); running = false; } catch (MALException ex) { - Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log(Level.WARNING, - "Exception during close down of the provider {0}", ex); + Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log( + Level.WARNING, "Exception during close down of the provider {0}", ex); } } @@ -160,37 +166,38 @@ private void streamRadioUpdate() { objId = uniqueObjId.incrementAndGet(); } - Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log(Level.FINER, - "Generating streaming Radio update with objId: " + objId); + Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log( + Level.FINER, "Generating streaming Radio update with objId: " + objId); final EntityKey ekey = new EntityKey(null, null, null, null); final UpdateHeaderList hdrlst = new UpdateHeaderList(); - hdrlst.add(new UpdateHeader(HelperTime.getTimestampMillis(), connection.getConnectionDetails() - .getProviderURI(), UpdateType.UPDATE, ekey)); + hdrlst.add(new UpdateHeader(HelperTime.getTimestampMillis(), + connection.getConnectionDetails().getProviderURI(), UpdateType.UPDATE, ekey)); publisher.publish(hdrlst, iqComponentsList); } catch (IllegalArgumentException | MALInteractionException | MALException ex) { - Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log(Level.WARNING, - "Exception during publishing process on the provider {0}", ex); + Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log( + Level.WARNING, "Exception during publishing process on the provider {0}", ex); } } @Override - public synchronized void enableSDR(final Boolean enable, final SDRConfiguration initialConfiguration, - final Duration publishingPeriod, final MALInteraction interaction) throws MALInteractionException, - MALException { + public synchronized void enableSDR(final Boolean enable, + final SDRConfiguration initialConfiguration, final Duration publishingPeriod, + final MALInteraction interaction) throws MALInteractionException, MALException { publishTimer.cancel(); if (!enable) { sdrInUse = false; } else { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } if (!adapter.setConfiguration(initialConfiguration)) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, null)); + throw new MALInteractionException(new MALStandardError( + COMHelper.INVALID_ERROR_NUMBER, null)); } sdrInUse = true; int period = (int) (publishingPeriod.getValue() * 1000); // In milliseconds @@ -208,16 +215,17 @@ public void run() { }, period, period); } if (!adapter.enableSDR(enable)) { - throw new MALInteractionException(new MALStandardError(MALHelper.INTERNAL_ERROR_NUMBER, null)); + throw new MALInteractionException( + new MALStandardError(MALHelper.INTERNAL_ERROR_NUMBER, null)); } } @Override public synchronized void updateConfiguration(final SDRConfiguration sdrConfiguration, - final MALInteraction interaction) throws MALInteractionException, MALException { + final MALInteraction interaction) throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException(new MALStandardError( + PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } if (!adapter.setConfiguration(sdrConfiguration)) { throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, null)); @@ -227,31 +235,31 @@ public synchronized void updateConfiguration(final SDRConfiguration sdrConfigura public static final class PublishInteractionListener implements MALPublishInteractionListener { @Override - public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + public void publishDeregisterAckReceived(final MALMessageHeader header, + final Map qosProperties) throws MALException { Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).fine( - "PublishInteractionListener::publishDeregisterAckReceived"); + "PublishInteractionListener::publishDeregisterAckReceived"); } @Override - public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + public void publishErrorReceived(final MALMessageHeader header, + final MALErrorBody body, final Map qosProperties) throws MALException { Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).warning( - "PublishInteractionListener::publishErrorReceived"); + "PublishInteractionListener::publishErrorReceived"); } @Override - public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { - Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log(Level.INFO, - "Registration Ack: {0}", header.toString()); + public void publishRegisterAckReceived(final MALMessageHeader header, + final Map qosProperties) throws MALException { + Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).log( + Level.INFO, "Registration Ack: {0}", header.toString()); } @Override - public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + public void publishRegisterErrorReceived(final MALMessageHeader header, + final MALErrorBody body, final Map qosProperties) throws MALException { Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).warning( - "PublishInteractionListener::publishRegisterErrorReceived"); + "PublishInteractionListener::publishRegisterErrorReceived"); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/HelperGPS.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/HelperGPS.java index b777b8123..2a29d2c81 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/HelperGPS.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/HelperGPS.java @@ -119,45 +119,51 @@ public static Position gpgga2Position(String gpgga) throws IOException { String[] items = gpgga.split(","); try { pos.setAltitude(Float.parseFloat(items[GPGGA_GEN_COL.ALTITUDE])); - pos.setLatitude(degMinutes2Degrees(items[GPGGA_GEN_COL.LAT]) * ((items[GPGGA_GEN_COL.LAT_DIR]).equals("S") ? - -1 : 1)); - pos.setLongitude(degMinutes2Degrees(items[GPGGA_GEN_COL.LONG]) * ((items[GPGGA_GEN_COL.LONG_DIR]).equals( - "W") ? -1 : 1)); + pos.setLatitude( + degMinutes2Degrees(items[GPGGA_GEN_COL.LAT]) * ((items[GPGGA_GEN_COL.LAT_DIR]).equals("S") + ? -1 : 1)); + pos.setLongitude( + degMinutes2Degrees(items[GPGGA_GEN_COL.LONG]) * ((items[GPGGA_GEN_COL.LONG_DIR]).equals( + "W") ? -1 : 1)); PositionExtraDetails posExtraDetails = new PositionExtraDetails(); posExtraDetails.setPositionSource(PositionSourceType.GNSS); - if (items[GPGGA_GEN_COL.QUAL].length() != 0) + if (items[GPGGA_GEN_COL.QUAL].length() != 0) { posExtraDetails.setFixQuality(Integer.parseInt(items[GPGGA_GEN_COL.QUAL])); - else + } else { posExtraDetails.setFixQuality(null); - if (items[GPGGA_GEN_COL.HDOP].length() != 0) + } + if (items[GPGGA_GEN_COL.HDOP].length() != 0) { posExtraDetails.setHdop(Float.parseFloat(items[GPGGA_GEN_COL.HDOP])); - else + } else { posExtraDetails.setHdop(null); - if (items[GPGGA_GEN_COL.SATS_IN_USE].length() != 0) + } + if (items[GPGGA_GEN_COL.SATS_IN_USE].length() != 0) { posExtraDetails.setNumberOfSatellites(Integer.parseInt(items[GPGGA_GEN_COL.SATS_IN_USE])); - else + } else { posExtraDetails.setNumberOfSatellites(null); - if (items[GPGGA_GEN_COL.UNDULATION].length() != 0) + } + if (items[GPGGA_GEN_COL.UNDULATION].length() != 0) { posExtraDetails.setUndulation(Float.parseFloat(items[GPGGA_GEN_COL.UNDULATION])); - else + } else { posExtraDetails.setUndulation(null); + } /* - * Time needs to be calculated, because GGA message only contains - * Hours, minutes and seconds but not day and year - * Format: hhmmss.ss - * with: - * hh = hour of day (24h format) - * mm = minute of hour - * ss.ss = second in Minute (with fractional second) - */ + * Time needs to be calculated, because GGA message only contains + * Hours, minutes and seconds but not day and year + * Format: hhmmss.ss + * with: + * hh = hour of day (24h format) + * mm = minute of hour + * ss.ss = second in Minute (with fractional second) + */ String time = items[GPGGA_GEN_COL.UTC]; int hours = Integer.parseInt(time.substring(0, 2)); int minutes = Integer.parseInt(time.substring(2, 4)); int seconds = Integer.parseInt(time.substring(4, 6)); // The GGALONG sentence also contains the fractions of second witch is not contained in the GGA sentence - int milliSeconds = (int) (Double.parseDouble(time.substring(6, 9)) * 1000); // convert fractional seconds to milliseconds + int miliSeconds = (int) (Double.valueOf(time.substring(6, 9)) * 1000); // convert fractional seconds to milliseconds // Get current time Calendar cal = (Calendar) Calendar.getInstance().clone(); @@ -171,7 +177,7 @@ public static Position gpgga2Position(String gpgga) throws IOException { cal.set(Calendar.HOUR_OF_DAY, hours); cal.set(Calendar.MINUTE, minutes); cal.set(Calendar.SECOND, seconds); - cal.set(Calendar.MILLISECOND, milliSeconds); + cal.set(Calendar.MILLISECOND, miliSeconds); // In case, the current time is shortly after midnight and the message was received before midnight if (cal.after(cal2)) { @@ -204,18 +210,16 @@ public static SatelliteInfoList gpgsv2SatelliteInfoList(final String gpgsv) thro int count = words.length; int sentenceSatCount = (count - 5) / 4; if (sentenceSatCount <= 0 || sentenceSatCount > 4) { - throw new IOException("Sentence [" + sentence + "] has calculated [" + sentenceSatCount + - "] sat count"); + throw new IOException("Sentence [" + sentence + "] has calculated [" + sentenceSatCount + "] sat count"); } int expectedSize = sentenceSatCount * 4 + 5; if (count != expectedSize) { - throw new IOException("Sentence [" + sentence + "] has wrong GPS sentence size [" + count + - "], expected minimum [" + expectedSize + "]"); + throw new IOException("Sentence [" + sentence + "] has wrong GPS sentence size [" + count + "], expected minimum [" + expectedSize + "]"); } if (!"$GPGSV".equals(words[GPGSV_COL.HEADER])) { - throw new IOException("Sentence [" + sentence + "] has wrong header [" + words[GPGSV_COL.HEADER] + - "], expected [$GPGSV]"); + throw new IOException("Sentence [" + sentence + "] has wrong header [" + + words[GPGSV_COL.HEADER] + "], expected [$GPGSV]"); } for (int satOffset = 0, i = 0; i < sentenceSatCount; i++, satOffset += 4) { float azimuth = 0, elevation = 0; @@ -230,8 +234,8 @@ public static SatelliteInfoList gpgsv2SatelliteInfoList(final String gpgsv) thro snr = null; // Workaround for OEM615 not sending SNR of some sats } if (prn > 0) { - sats.add(new SatelliteInfo(azimuth, elevation, prn, null, null, null, null, null, snr, null, - null)); + sats.add(new SatelliteInfo(azimuth, elevation, prn, + null, null, null, null, null, snr, null, null)); } } } @@ -251,8 +255,8 @@ public static float degMinutes2Degrees(String in) throws IOException { throw new IOException("Did not find decimal in " + in); } try { - return Float.parseFloat(in.substring(0, decimalAt - 2)) + Float.parseFloat(in.substring(decimalAt - 2, - len)) / 60; + return Float.parseFloat(in.substring(0, decimalAt - 2)) + + Float.parseFloat(in.substring(decimalAt - 2, len)) / 60; } catch (NumberFormatException e) { throw new IOException("Failed to parse degrees and minutes.", e); } @@ -281,15 +285,17 @@ public static String getHeaderFromBestXYZ(String bestXYZ) { return bestXYZ.split(";")[0]; } - /** Removes details from the NMEA log like Date: Mon, 28 Feb 2022 18:27:13 +0100 Subject: [PATCH 031/173] Added to the AI service to the Platform services' hooks --- .../impl/util/PlatformServicesConsumer.java | 54 ++++++++++++++++--- .../PlatformServicesConsumerInterface.java | 5 +- .../PlatformServicesProviderInterface.java | 3 ++ 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java index dd54811b3..42b654ba3 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java @@ -26,6 +26,7 @@ import esa.mo.platform.impl.consumer.GPSConsumerServiceImpl; import esa.mo.helpertools.connections.ConnectionConsumer; import esa.mo.helpertools.connections.SingleConnectionDetails; +import esa.mo.platform.impl.consumer.ArtificialIntelligenceConsumerServiceImpl; import esa.mo.platform.impl.consumer.AutonomousADCSConsumerServiceImpl; import esa.mo.platform.impl.consumer.OpticalDataReceiverConsumerServiceImpl; import esa.mo.platform.impl.consumer.PowerControlConsumerServiceImpl; @@ -37,6 +38,8 @@ import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; import org.ccsds.moims.mo.mal.structures.Blob; +import org.ccsds.moims.mo.platform.artificialintelligence.ArtificialIntelligenceHelper; +import org.ccsds.moims.mo.platform.artificialintelligence.consumer.ArtificialIntelligenceStub; import org.ccsds.moims.mo.platform.autonomousadcs.AutonomousADCSHelper; import org.ccsds.moims.mo.platform.autonomousadcs.consumer.AutonomousADCSStub; import org.ccsds.moims.mo.platform.camera.CameraHelper; @@ -58,6 +61,7 @@ */ public class PlatformServicesConsumer implements PlatformServicesConsumerInterface { + private ArtificialIntelligenceConsumerServiceImpl aiService; private AutonomousADCSConsumerServiceImpl autonomousADCSService; private CameraConsumerServiceImpl cameraService; private GPSConsumerServiceImpl gpsService; @@ -75,49 +79,62 @@ public void init(ConnectionConsumer connectionConsumer, SingleConnectionDetails details; try { + // Initialize the ArtificialIntelligence service + details = connectionConsumer.getServicesDetails().get( + ArtificialIntelligenceHelper.ARTIFICIALINTELLIGENCE_SERVICE_NAME); + if (details != null) { + aiService = new ArtificialIntelligenceConsumerServiceImpl( + details, comServices, authenticationID, localNamePrefix); + } + // Initialize the AutonomousADCS service details = connectionConsumer.getServicesDetails().get( AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE_NAME); if (details != null) { - autonomousADCSService = new AutonomousADCSConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); + autonomousADCSService = new AutonomousADCSConsumerServiceImpl( + details, comServices, authenticationID, localNamePrefix); } // Initialize the Camera service details = connectionConsumer.getServicesDetails().get(CameraHelper.CAMERA_SERVICE_NAME); if (details != null) { - cameraService = new CameraConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); + cameraService = new CameraConsumerServiceImpl(details, + comServices, authenticationID, localNamePrefix); } // Initialize the GPS service details = connectionConsumer.getServicesDetails().get(GPSHelper.GPS_SERVICE_NAME); if (details != null) { - gpsService = new GPSConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); + gpsService = new GPSConsumerServiceImpl(details, + comServices, authenticationID, localNamePrefix); } // Initialize the Optical Data Receiver service details = connectionConsumer.getServicesDetails().get( OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE_NAME); if (details != null) { - odrService = new OpticalDataReceiverConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); + odrService = new OpticalDataReceiverConsumerServiceImpl(details, + comServices, authenticationID, localNamePrefix); } // Initialize the Software Defined Radio service details = connectionConsumer.getServicesDetails().get( SoftwareDefinedRadioHelper.SOFTWAREDEFINEDRADIO_SERVICE_NAME); if (details != null) { - sdrService = new SoftwareDefinedRadioConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); + sdrService = new SoftwareDefinedRadioConsumerServiceImpl(details, + comServices, authenticationID, localNamePrefix); } // Initialize the Power Control service details = connectionConsumer.getServicesDetails().get( PowerControlHelper.POWERCONTROL_SERVICE_NAME); if (details != null) { - powerControlService = new PowerControlConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); + powerControlService = new PowerControlConsumerServiceImpl(details, + comServices, authenticationID, localNamePrefix); } // Initialize the Clock service - details = connectionConsumer.getServicesDetails().get( - ClockHelper.CLOCK_SERVICE_NAME); + details = connectionConsumer.getServicesDetails().get(ClockHelper.CLOCK_SERVICE_NAME); if (details != null) { clockService = new ClockConsumerServiceImpl(details, comServices); } @@ -126,6 +143,15 @@ public void init(ConnectionConsumer connectionConsumer, } } + @Override + public ArtificialIntelligenceStub getAIService() throws IOException { + if (this.aiService == null) { + throw new IOException("The service consumer is not connected to the provider."); + } + + return this.aiService.getArtificialIntelligenceStub(); + } + @Override public AutonomousADCSStub getAutonomousADCSService() throws IOException { if (this.autonomousADCSService == null) { @@ -190,6 +216,10 @@ public ClockStub getClockService() throws IOException { } // Setters + public void setArtificialIntelligenceService(ArtificialIntelligenceConsumerServiceImpl aiService) { + this.aiService = aiService; + } + public void setAutonomousADCSService(AutonomousADCSConsumerServiceImpl autonomousADCSService) { this.autonomousADCSService = autonomousADCSService; } @@ -223,6 +253,10 @@ public void setClockService(ClockConsumerServiceImpl clockService) { * */ public void closeConnections() { + if (this.aiService != null) { + this.aiService.close(); + } + if (this.autonomousADCSService != null) { this.autonomousADCSService.close(); } @@ -249,6 +283,10 @@ public void closeConnections() { } public void setAuthenticationId(Blob authenticationId) { + if (this.aiService != null) { + this.aiService.setAuthenticationId(authenticationId); + } + if (this.autonomousADCSService != null) { this.autonomousADCSService.setAuthenticationId(authenticationId); } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumerInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumerInterface.java index 489b78333..6692db35b 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumerInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumerInterface.java @@ -21,6 +21,7 @@ package esa.mo.platform.impl.util; import java.io.IOException; +import org.ccsds.moims.mo.platform.artificialintelligence.consumer.ArtificialIntelligenceStub; import org.ccsds.moims.mo.platform.autonomousadcs.consumer.AutonomousADCSStub; import org.ccsds.moims.mo.platform.camera.consumer.CameraStub; import org.ccsds.moims.mo.platform.clock.consumer.ClockStub; @@ -35,8 +36,10 @@ */ public interface PlatformServicesConsumerInterface { - AutonomousADCSStub getAutonomousADCSService() throws IOException; + ArtificialIntelligenceStub getAIService() throws IOException; + AutonomousADCSStub getAutonomousADCSService() throws IOException; + CameraStub getCameraService() throws IOException; GPSStub getGPSService() throws IOException; diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java index d80b4bc94..622520d97 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java @@ -23,6 +23,7 @@ import esa.mo.com.impl.util.COMServicesProvider; import esa.mo.helpertools.connections.ConnectionConsumer; import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; import org.ccsds.moims.mo.platform.autonomousadcs.provider.AutonomousADCSInheritanceSkeleton; import org.ccsds.moims.mo.platform.camera.provider.CameraInheritanceSkeleton; import org.ccsds.moims.mo.platform.gps.provider.GPSInheritanceSkeleton; @@ -40,6 +41,8 @@ default void init(COMServicesProvider comServices) throws MALException { default void startStatusTracking(ConnectionConsumer connection) { } + ArtificialIntelligenceInheritanceSkeleton getAIService(); + CameraInheritanceSkeleton getCameraService(); GPSInheritanceSkeleton getGPSService(); From d22c3e39b60ebb76c85a9e62bb8224a8fa30c87f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 3 Mar 2022 13:34:44 +0100 Subject: [PATCH 032/173] Fixed compilation problem on the Mission Simulator --- .../platform/impl/util/PlatformServicesProviderSoftSim.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index 695fb8459..480ca5e1e 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -51,6 +51,7 @@ import esa.mo.platform.impl.provider.gen.SoftwareDefinedRadioAdapterInterface; import esa.mo.platform.impl.provider.gen.SoftwareDefinedRadioProviderServiceImpl; import opssat.simulator.main.ESASimulator; +import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; /** * @@ -278,4 +279,9 @@ public SoftwareDefinedRadioInheritanceSkeleton getSoftwareDefinedRadioService() return this.sdrService; } + @Override + public ArtificialIntelligenceInheritanceSkeleton getAIService() { + throw new UnsupportedOperationException("Not supported yet."); + } + } From 7fff8102117de7ade405c0e2161ecde3aad7d9ef Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 7 Apr 2022 11:01:19 +0200 Subject: [PATCH 033/173] Removed the startStatusTracking method from the interface as that method does not belong to an interface that is implemented by multiple missions, instead is a Simulator-specific method --- .../PlatformServicesProviderInterface.java | 43 ++++++++-- .../NanoSatMOSupervisor.java | 83 ++++++++++++++++++- .../NanosatMOSupervisorBasicImpl.java | 34 ++++---- .../util/PlatformServicesProviderSoftSim.java | 7 +- 4 files changed, 141 insertions(+), 26 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java index 622520d97..c4475a710 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderInterface.java @@ -21,7 +21,6 @@ package esa.mo.platform.impl.util; import esa.mo.com.impl.util.COMServicesProvider; -import esa.mo.helpertools.connections.ConnectionConsumer; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; import org.ccsds.moims.mo.platform.autonomousadcs.provider.AutonomousADCSInheritanceSkeleton; @@ -31,26 +30,60 @@ import org.ccsds.moims.mo.platform.softwaredefinedradio.provider.SoftwareDefinedRadioInheritanceSkeleton; /** - * The Platform services provider interface + * The Platform services provider interface. Allows the retrieval of the default + * set of services that are part of the Platform services. */ public interface PlatformServicesProviderInterface { + /** + * The init method initializes the Platform services. + * + * @param comServices The COM services + * @throws MALException if there is an error during the initialization. + */ default void init(COMServicesProvider comServices) throws MALException { } - default void startStatusTracking(ConnectionConsumer connection) { - } - + /** + * Returns the Artificial Intelligence service. + * + * @return The Artificial Intelligence service. + */ ArtificialIntelligenceInheritanceSkeleton getAIService(); + /** + * Returns the Camera service. + * + * @return The Camera service. + */ CameraInheritanceSkeleton getCameraService(); + /** + * Returns the GPS service. + * + * @return The GPS service. + */ GPSInheritanceSkeleton getGPSService(); + /** + * Returns the Autonomous ADCS service. + * + * @return The Autonomous ADCS service. + */ AutonomousADCSInheritanceSkeleton getAutonomousADCSService(); + /** + * Returns the Optical Data Receiver service. + * + * @return The Optical Data Receiver service. + */ OpticalDataReceiverInheritanceSkeleton getOpticalDataReceiverService(); + /** + * Returns the Software Defined Radio service. + * + * @return The Software Defined Radio service. + */ SoftwareDefinedRadioInheritanceSkeleton getSoftwareDefinedRadioService(); } diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index e4d851b24..be9f1bdd6 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -249,9 +249,88 @@ public final void closeGracefully(final ObjectId source) { System.exit(0); } + } + + @Override + public void init(MissionPlanningNMFAdapter mpAdapter) { + // Not implemented. MP services are accessible only from connector. + } + + @Override + public void setCloseAppListener(final CloseAppListener closeAppAdapter) { + this.closeAppAdapter = closeAppAdapter; + } + + /** + * It closes the App gracefully. + * + * @param source The source of the triggering. Can be null + */ + @Override + public final void closeGracefully(final ObjectId source) { + try { + AppShutdownGuard.start(); + long timestamp = System.currentTimeMillis(); + + // Acknowledge the reception of the request to close (Closing...) + Long eventId = this.getCOMServices().getEventService().generateAndStoreEvent( + AppsLauncherHelper.STOPPING_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + null, + null, + source, + null); + + final URI uri + = this.getCOMServices().getEventService().getConnectionProvider().getConnectionDetails().getProviderURI(); + + try { + this.getCOMServices().getEventService().publishEvent(uri, eventId, + AppsLauncherHelper.STOPPING_OBJECT_TYPE, null, source, null); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + + // Close the app... + // Make a call on the app layer to close nicely... + if (this.closeAppAdapter != null) { + LOGGER.log(Level.INFO, + "Triggering the closeAppAdapter of the app business logic..."); + this.closeAppAdapter.onClose(); // Time to sleep, boy! + } + + Long eventId2 = this.getCOMServices().getEventService().generateAndStoreEvent( + AppsLauncherHelper.STOPPED_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + null, + null, + source, + null); + + try { + this.getCOMServices().getEventService().publishEvent(uri, eventId2, + AppsLauncherHelper.STOPPED_OBJECT_TYPE, null, source, null); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + + // Should close them safely as well... +// provider.getMCServices().closeServices(); +// provider.getCOMServices().closeServices(); + this.getCOMServices().closeAll(); + + // Exit the Java application + LOGGER.log(Level.INFO, + "Success! The currently running Java Virtual Machine will now terminate. " + + "(NanoSat MO Supervisor closed in: " + (System.currentTimeMillis() - timestamp) + " ms)\n"); + + } catch (NMFException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } - public abstract void initPlatformServices(COMServicesProvider comServices); + System.exit(0); + } - protected abstract void startStatusTracking(); + public abstract void initPlatformServices(COMServicesProvider comServices); } diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java index bdf449ef6..8eb102b46 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java @@ -28,20 +28,23 @@ import esa.mo.nmf.nmfpackage.NMFPackagePMBackend; import esa.mo.platform.impl.util.PlatformServicesConsumer; import esa.mo.platform.impl.util.PlatformServicesProviderInterface; +import esa.mo.platform.impl.util.PlatformServicesProviderSoftSim; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.mal.MALException; /** - * This is a specific implementation of the NMF supervisor which is currently being used by - * the SDK and the OPS-SAT mission. Using the property "nmf.platform.impl" one can select - * the class of the platform services implementation which shall be used by the supervisor. If no - * such property is provided, it will use the simulated platform services by default. + * This is a specific implementation of the NMF supervisor which is currently + * being used by the SDK and the OPS-SAT mission. Using the property + * "nmf.platform.impl" one can select the class of the platform services + * implementation which shall be used by the supervisor. If no such property is + * provided, it will use the simulated platform services by default. * * @author yannick */ public class NanosatMOSupervisorBasicImpl extends NanoSatMOSupervisor { + private static final Logger LOGGER = Logger.getLogger(NanosatMOSupervisorBasicImpl.class.getName()); private PlatformServicesProviderInterface platformServicesProvider; private ConnectionConsumer connectionConsumer; @@ -49,17 +52,16 @@ public class NanosatMOSupervisorBasicImpl extends NanoSatMOSupervisor { @Override public void initPlatformServices(COMServicesProvider comServices) { try { - String platformProviderClass = System.getProperty("nmf.platform.impl", - "esa.mo.platform.impl.util.PlatformServicesProviderSoftSim"); + String platformProviderClass = System.getProperty("nmf.platform.impl", "esa.mo.platform.impl.util.PlatformServicesProviderSoftSim"); try { - platformServicesProvider = (PlatformServicesProviderInterface) Class.forName(platformProviderClass) - .newInstance(); + platformServicesProvider + = (PlatformServicesProviderInterface) Class.forName(platformProviderClass).newInstance(); platformServicesProvider.init(comServices); - } catch (NullPointerException | - ClassNotFoundException | - InstantiationException | - IllegalAccessException ex) { - LOGGER.log(Level.SEVERE, "Something went wrong when initializing the platform services.", ex); + } catch (NullPointerException | ClassNotFoundException | InstantiationException + | IllegalAccessException ex) { + LOGGER.log(Level.SEVERE, + "Something went wrong when initializing the platform services.", + ex); System.exit(-1); } } catch (MALException ex) { @@ -75,14 +77,16 @@ public void initPlatformServices(COMServicesProvider comServices) { } } - @Override protected void startStatusTracking() { - platformServicesProvider.startStatusTracking(connectionConsumer); + if (platformServicesProvider instanceof PlatformServicesProviderSoftSim) { + ((PlatformServicesProviderSoftSim) platformServicesProvider).startStatusTracking(connectionConsumer); + } } @Override public void init(MonitorAndControlNMFAdapter mcAdapter) { init(mcAdapter, new PlatformServicesConsumer(), new NMFPackagePMBackend("packages")); + this.startStatusTracking(); } /** diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index 480ca5e1e..46b70f03e 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -248,10 +248,9 @@ public void init(COMServicesProvider comServices) throws MALException { clockService.init(clockAdapter); } - @Override - public void startStatusTracking(ConnectionConsumer connection) { - pcAdapter.startStatusTracking(connection); - } + public void startStatusTracking(ConnectionConsumer connection) { + pcAdapter.startStatusTracking(connection); + } @Override public AutonomousADCSProviderServiceImpl getAutonomousADCSService() { From 008b2798371a198b910a5cbd43dbf78c670a9489 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 7 Apr 2022 17:57:45 +0200 Subject: [PATCH 034/173] [nmfpack] Fixed bug on Receipt version 3. The receipt could not be read correctly. --- .../nmf/nmfpackage/receipt/ReceiptVersion3.java | 2 ++ .../tests/SimpleDemoPackageCreation.java | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index abf94f38c..9546c0e88 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -139,6 +139,8 @@ public static void writeReceipt(final BufferedWriter bw, bw.newLine(); bw.write(MAINJAR + descriptor.getDetails().getMainJar()); bw.newLine(); + bw.write(MAXHEAP + descriptor.getDetails().getMainJar()); + bw.newLine(); // Iterate the newLocations and write them down on the file for (NMFPackageFile f : descriptor.getFiles()) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index afaa036f6..e39f100f8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -22,11 +22,14 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.nmfpackage.NMFPackageCreator; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.zip.ZipFile; import org.ccsds.moims.mo.mal.structures.Time; /** @@ -56,7 +59,7 @@ public static void createPackage() { // Step 1: Fill in app details... // App Name, Description, Category // Step 2: Is it a NMF app? - // If No:s + // If Not: // Select the binary files to be installed // Additional libraries? final Time time = new Time(System.currentTimeMillis()); @@ -85,7 +88,15 @@ public static void createPackage() { // Package 3 NMFPackageDetails details3 = new NMFPackageDetails("TestPackage", "3.0", timestamp, "noclass", "", "96m"); - NMFPackageCreator.nmfPackageCreator(details3, files, newLocations); + String location = NMFPackageCreator.nmfPackageCreator(details3, files, newLocations); + + try { + // Test if the created file can be parsed + ZipFile writtenFile = new ZipFile(location); + NMFPackageDescriptor theDescriptor = NMFPackageDescriptor.parseZipFile(writtenFile); + } catch (IOException ex) { + Logger.getLogger(SimpleDemoPackageCreation.class.getName()).log(Level.SEVERE, null, ex); + } // If Yes: // Select the jar file (without dependencies) From 330742e274aecf28ef492cbd46a7c2c17af458ac Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 7 Apr 2022 19:50:58 +0200 Subject: [PATCH 035/173] New App that triggers an external Python script --- sdk/examples/space/pom.xml | 1 + sdk/examples/space/python-script/.gitignore | 1 + sdk/examples/space/python-script/README.md | 68 +++++++ sdk/examples/space/python-script/pom.xml | 131 ++++++++++++ .../apps/pythonscript/PythonScriptApp.java | 46 +++++ .../nmf/apps/pythonscript/run/FileUtils.java | 63 ++++++ .../run/LoggingExecuteResultHandler.java | 61 ++++++ .../nmf/apps/pythonscript/run/MCAdapter.java | 192 ++++++++++++++++++ .../run/PythonScriptExecutor.java | 124 +++++++++++ .../src/main/resources/scripts/myScript.py | 8 + 10 files changed, 695 insertions(+) create mode 100644 sdk/examples/space/python-script/.gitignore create mode 100644 sdk/examples/space/python-script/README.md create mode 100644 sdk/examples/space/python-script/pom.xml create mode 100644 sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/PythonScriptApp.java create mode 100644 sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/FileUtils.java create mode 100644 sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/LoggingExecuteResultHandler.java create mode 100644 sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/MCAdapter.java create mode 100644 sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java create mode 100644 sdk/examples/space/python-script/src/main/resources/scripts/myScript.py diff --git a/sdk/examples/space/pom.xml b/sdk/examples/space/pom.xml index c7ec27355..52ad1258b 100644 --- a/sdk/examples/space/pom.xml +++ b/sdk/examples/space/pom.xml @@ -80,6 +80,7 @@ periodic-alert picture-processor publish-clock + python-script serialized-object waveform mp-space-demo diff --git a/sdk/examples/space/python-script/.gitignore b/sdk/examples/space/python-script/.gitignore new file mode 100644 index 000000000..3475b2ff7 --- /dev/null +++ b/sdk/examples/space/python-script/.gitignore @@ -0,0 +1 @@ +toGround/ diff --git a/sdk/examples/space/python-script/README.md b/sdk/examples/space/python-script/README.md new file mode 100644 index 000000000..ba235478c --- /dev/null +++ b/sdk/examples/space/python-script/README.md @@ -0,0 +1,68 @@ +# Python Script NMF App + + + +NMF App that allows to: + + - start and stop an external process (starts a python script in this demo app) + - provide to the external process environment variables and input arguments + - set a timeout in order to force the automatic termination of the external process + - redirect the external process standard output and standard error to a file + + + +## Prerequisites: + +Python is a pre-requisite since the process launched by this demo will be instantiated from a python script. The App can be easily modified to run other processes. + + + +## MO Actions: + +The App exposes two MO Actions: "*RunPythonScript*" and "*DestroyProcess*". + + + +### RunPythonScript + +When this action is triggered, the App will run the python script: "*myScript.py*". The script will print on the screen "Hello World!" followed by a counter. + + + +The standard output and standard error of the process will be logged in a file within the "*logs*" folder. The log file name will have the following format: "logs\log_output.log" + + + +When the external process terminates the App will publish a MO Parameter whose name have the following format: "Process Request ID: \ exitCode: \". + + + +#### Arguments: + +1. Minimum Process Duration in seconds: this is the first action argument and can be used to simulate a long running process. The default value is 0. This value will be passed to the process through an environment variable. +2. Maximum Process Duration in seconds: this is the second action argument and can be used to set a timeout after which the process is killed. The default value is -1, which is interpreted as "*infinity*" + + + +### DestroyProcess: + +When this action is triggered, the App will attempt to terminate the process having the provided "Action Request ID" + + + +The "Action Request ID" is printed on the console of the "Apps Launcher Service" of the Supervisor whenever the "*RunPythonScript*" action is triggered. + +Example: + +``` +INFO: Process 1614083521462 is starting. It will last at least 0 seconds and at most 30000 ms +``` + + + +#### Arguments: + +1. Action Request ID: the action request ID of the "*RunPythonScript*" Action that triggered the external process. + + + diff --git a/sdk/examples/space/python-script/pom.xml b/sdk/examples/space/python-script/pom.xml new file mode 100644 index 000000000..7f9ec501a --- /dev/null +++ b/sdk/examples/space/python-script/pom.xml @@ -0,0 +1,131 @@ + + + + + + 4.0.0 + + + int.esa.nmf + parent + 2.1.0-SNAPSHOT + ../../../../parent/pom.xml + + + int.esa.nmf.sdk.examples.space + python-script + jar + + ESA NMF SDK App Example - Python Script + A demo that call a simple python script. + http://www.esa.int + + + ESA + http://www.esa.int + + + + + European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + https://raw.github.com/esa/nanosat-mo-framework/master/LICENCE.md + repo + + + + + scm:git:git@github.com:esa/nanosat-mo-framework.git + scm:git:git@github.com:esa/nanosat-mo-framework.git + https://github.com/esa/nanosat-mo-framework + + + + GitHub + https://github.com/esa/nanosat-mo-framework/issues + + + + + CesarCoelho + César Coelho + https://github.com/CesarCoelho + + + + + esa.mo.nmf.apps.pythonscript.PythonScriptApp + + + + + int.esa.nmf.core + nanosat-mo-connector + + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.codehaus.mojo + build-helper-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-resources-plugin + + + + + + + generate-nmf-package + + + + int.esa.nmf.core + nmf-package-maven-plugin + + + package + + generate-nmf-package + + + ${assembly.mainClass} + + ${basedir}/src/main/resources/scripts + + + + + + + + + + diff --git a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/PythonScriptApp.java b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/PythonScriptApp.java new file mode 100644 index 000000000..6182d2048 --- /dev/null +++ b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/PythonScriptApp.java @@ -0,0 +1,46 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.pythonscript; + +import esa.mo.nmf.apps.pythonscript.run.MCAdapter; +import esa.mo.nmf.nanosatmoconnector.NanoSatMOConnectorImpl; + +/** + * An NMF App that runs a python script + */ +public class PythonScriptApp { + + public PythonScriptApp() { + NanoSatMOConnectorImpl connector = new NanoSatMOConnectorImpl(); + connector.init(new MCAdapter(connector)); + } + + /** + * Main command line entry point. + * + * @param args the command line arguments + * @throws java.lang.Exception If there is an error + */ + public static void main(final String[] args) throws Exception { + PythonScriptApp pythonScriptApp = new PythonScriptApp(); + } + +} diff --git a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/FileUtils.java b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/FileUtils.java new file mode 100644 index 000000000..9daa4dfef --- /dev/null +++ b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/FileUtils.java @@ -0,0 +1,63 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.pythonscript.run; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.logging.Level; +import java.util.logging.Logger; + +public final class FileUtils { + + private static final Logger LOG = Logger.getLogger(FileUtils.class.getName()); + + public static Path createDirectoriesIfNotExist(Path directory) { + if (Files.exists(directory)) { + return directory; + } + try { + return Files.createDirectories(directory); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public static OutputStream newOutpuStreamSafe(Path file) { + try { + return Files.newOutputStream(file); + } catch (IOException e) { + LOG.log(Level.SEVERE, "Failed to create output stream for file: " + file, e); + return null; + } + } + + public static void closeSafe(OutputStream outputStream) { + try { + outputStream.close(); + } catch (IOException e) { + LOG.log(Level.SEVERE, "Failed to close output stream", e); + } + } + +} diff --git a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/LoggingExecuteResultHandler.java b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/LoggingExecuteResultHandler.java new file mode 100644 index 000000000..895fb4310 --- /dev/null +++ b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/LoggingExecuteResultHandler.java @@ -0,0 +1,61 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.pythonscript.run; + +import java.io.OutputStream; +import java.util.logging.Logger; +import org.apache.commons.exec.DefaultExecuteResultHandler; +import org.apache.commons.exec.ExecuteException; + +public class LoggingExecuteResultHandler extends DefaultExecuteResultHandler { + + private static final Logger LOG = Logger.getLogger(LoggingExecuteResultHandler.class.getName()); + + private final OutputStream processOutputStream; + private final MCAdapter processEventListener; + private final Long processRequestId; + + public LoggingExecuteResultHandler(MCAdapter processEventListener, + Long processRequestId, OutputStream processOutputStream) { + this.processOutputStream = processOutputStream; + this.processEventListener = processEventListener; + this.processRequestId = processRequestId; + } + + @Override + public void onProcessComplete(final int exitValue) { + super.onProcessComplete(exitValue); + LOG.info("Process execution completed. ExitValue: " + exitValue); + handleProcessTermination(exitValue); + } + + @Override + public void onProcessFailed(final ExecuteException e) { + super.onProcessFailed(e); + LOG.info("Process execution failed: " + e); + handleProcessTermination(e.getExitValue()); + } + + private void handleProcessTermination(int exitValue) { + FileUtils.closeSafe(processOutputStream); + processEventListener.onProcessCompleted(processRequestId, exitValue); + } +} diff --git a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/MCAdapter.java b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/MCAdapter.java new file mode 100644 index 000000000..f2ec72322 --- /dev/null +++ b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/MCAdapter.java @@ -0,0 +1,192 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.pythonscript.run; + +import static esa.mo.helpertools.helpers.HelperAttributes.attribute2JavaType; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.mal.provider.MALInteraction; +import org.ccsds.moims.mo.mal.structures.Attribute; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.UInteger; +import org.ccsds.moims.mo.mal.structures.UOctet; +import org.ccsds.moims.mo.mal.structures.UShort; +import org.ccsds.moims.mo.mc.action.structures.ActionDefinitionDetails; +import org.ccsds.moims.mo.mc.action.structures.ActionDefinitionDetailsList; +import org.ccsds.moims.mo.mc.structures.ArgumentDefinitionDetails; +import org.ccsds.moims.mo.mc.structures.ArgumentDefinitionDetailsList; +import org.ccsds.moims.mo.mc.structures.AttributeValue; +import org.ccsds.moims.mo.mc.structures.AttributeValueList; +import esa.mo.nmf.MCRegistration; +import esa.mo.nmf.MonitorAndControlNMFAdapter; +import esa.mo.nmf.NMFException; +import esa.mo.nmf.NMFInterface; +import esa.mo.nmf.NMFProvider; + +/** + * The adapter for the NMF App + */ +public class MCAdapter extends MonitorAndControlNMFAdapter { + + private static final Logger LOG = Logger.getLogger(MCAdapter.class.getName()); + + private static final String ACTION_RUN_PYTHON_SCRIPT = "RunPythonScript"; + private static final String ACTION_DESTROY_PROCESS = "DestroyProcess"; + private static final int TOTAL_STAGES = 1; + + private final Map processMap = new ConcurrentHashMap<>(); + private final NMFInterface connector; + + public MCAdapter(NMFProvider connector) { + this.connector = connector; + } + + @Override + public void initialRegistrations(MCRegistration registration) { + registration.setMode(MCRegistration.RegistrationMode.DONT_UPDATE_IF_EXISTS); + + // ------------------ Actions ------------------ + ActionDefinitionDetailsList actionDefs = new ActionDefinitionDetailsList(); + IdentifierList actionNames = new IdentifierList(); + + registerActionDestroyProcess(actionDefs, actionNames); + registerActionRunPython(actionDefs, actionNames); + // ---- + + registration.registerActions(actionNames, actionDefs); + } + + @Override + public UInteger actionArrived(Identifier name, AttributeValueList attributeValues, + Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { + + if (ACTION_RUN_PYTHON_SCRIPT.equals(name.getValue())) { + runPythonScript(actionInstanceObjId, attributeValues); + return null; // Success! + } else if (ACTION_DESTROY_PROCESS.equals(name.getValue())) { + destroyProcess(attributeValues); + return null; + } + + return new UInteger(0); // Action service not integrated + } + + public void onProcessCompleted(Long id, int exitCode) { + processMap.remove(id); + LOG.info("Process with Request Id: " + id + " exited with code: " + exitCode); + publishParameter(id.toString(), exitCode); + } + + private void registerActionRunPython(ActionDefinitionDetailsList actionDefs, IdentifierList actionNames) { + ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); + { + Byte rawType = Attribute._INTEGER_TYPE_SHORT_FORM; + arguments.add(new ArgumentDefinitionDetails( + new Identifier("Min Process duration"), + "Minimum Process duration", + rawType, "seconds", null, null, null)); + } + { + Byte rawType = Attribute._INTEGER_TYPE_SHORT_FORM; + arguments.add(new ArgumentDefinitionDetails( + new Identifier("Max Process duration"), + "Max Picture processing duration", + rawType, "seconds", null, null, null)); + } + + actionDefs.add(new ActionDefinitionDetails( + "Runs a python script", + new UOctet((short) 0), + new UShort(TOTAL_STAGES), + arguments)); + actionNames.add(new Identifier(ACTION_RUN_PYTHON_SCRIPT)); + } + + private void registerActionDestroyProcess(ActionDefinitionDetailsList actionDefs, IdentifierList actionNames) { + ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); + { + Byte rawType = Attribute._LONG_TYPE_SHORT_FORM; + arguments.add(new ArgumentDefinitionDetails( + new Identifier("process id"), + "process id", + rawType, "", null, null, null)); + } + + actionDefs.add(new ActionDefinitionDetails( + "Destroy a process", + new UOctet((short) 0), + new UShort(1), + arguments)); + actionNames.add(new Identifier(ACTION_DESTROY_PROCESS)); + } + + private void runPythonScript(Long actionInstanceObjId, AttributeValueList attributeValues) { + int minProcessingDurationSeconds = getAs(attributeValues.get(0)); + int maxProcessingDurationSeconds = getAs(attributeValues.get(1)); + + LOG.info("Requested to run the python script..."); + LOG.info("Process Min duration " + minProcessingDurationSeconds); + LOG.info("Process Max duration " + maxProcessingDurationSeconds); + LOG.info("Process Request Id " + actionInstanceObjId); + + PythonScriptExecutor exec = new PythonScriptExecutor(this, + actionInstanceObjId, minProcessingDurationSeconds, + maxProcessingDurationSeconds + ); + + exec.runPythonScript(""); + + processMap.put(actionInstanceObjId, exec); + } + + private void destroyProcess(AttributeValueList attributeValues) { + Long processRequestId = getAs(attributeValues.get(0)); + LOG.info("Requested to destroy Process with Id: " + processRequestId); + + PythonScriptExecutor adapter = processMap.remove(processRequestId); + if (adapter != null) { + LOG.info("Killing process Process with Id: " + processRequestId); + adapter.destroyProcess(); + } else { + LOG.info("Process Request Id " + processRequestId + " not found"); + } + } + + private void publishParameter(String id, int exitCode) { + try { + String str = "Process Request ID: " + id + " exitCode: " + exitCode; + connector.pushParameterValue(str, exitCode); + } catch (NMFException e) { + LOG.log(Level.SEVERE, "Failed to publish parameter", e); + } + } + + private static T getAs(AttributeValue attributeValue) { + if (attributeValue == null) { + return null; + } + return (T) attribute2JavaType(attributeValue.getValue()); + } + +} diff --git a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java new file mode 100644 index 000000000..cac531649 --- /dev/null +++ b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java @@ -0,0 +1,124 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.pythonscript.run; + +import esa.mo.nmf.AppStorage; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.PumpStreamHandler; + +public class PythonScriptExecutor { + + private static final Logger LOG = Logger.getLogger(PythonScriptExecutor.class.getName()); + private static final String ENV_PROCESS_DURATION = "ENV_PROCESS_DURATION"; + private static final String LOG_PATH = "logs"; + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss_SSSS") + .withZone(ZoneId.systemDefault()); + + private final DefaultExecutor executor = new DefaultExecutor(); + private final long minDurationSeconds; + private final long maxDurationMillis; + private final MCAdapter mcAdapter; + private final Long id; + + public PythonScriptExecutor(MCAdapter mcAdapter, Long id, + Integer minDurationSeconds, Integer maxDurationSeconds) { + this.minDurationSeconds = toMinDuration(minDurationSeconds); + this.maxDurationMillis = toWatchdogTimeout(maxDurationSeconds); + this.mcAdapter = mcAdapter; + this.id = id; + this.executor.setWatchdog(new ExecuteWatchdog(maxDurationMillis)); + } + + public boolean runPythonScript(String argument0) { + LOG.info("Process " + id + " is starting:" + + "\n >> Min duration: " + minDurationSeconds + " seconds" + + "\n >> Max duration: " + maxDurationMillis + " ms"); + + OutputStream outputStream = initLogStream(generateLogFilename()); + if (outputStream == null) { + return false; + } + + CommandLine commandLine = new CommandLine("python3") + .addArgument("scripts/myScript.py") + .addArgument(argument0); + + executor.setStreamHandler(new PumpStreamHandler(outputStream)); + + Map environment = new HashMap<>(); + environment.put(ENV_PROCESS_DURATION, String.valueOf(minDurationSeconds)); + + try { + executor.execute(commandLine, environment, + new LoggingExecuteResultHandler(mcAdapter, id, outputStream) + ); + } catch (IOException e) { + LOG.log(Level.SEVERE, "The script could not be executed", e); + return false; + } + + return true; + } + + public void destroyProcess() { + executor.getWatchdog().destroyProcess(); + } + + private static long toWatchdogTimeout(Integer timeoutSeconds) { + if (timeoutSeconds == null || timeoutSeconds <= 0) { + return ExecuteWatchdog.INFINITE_TIMEOUT; + } + return timeoutSeconds * 1000L; + } + + private static int toMinDuration(Integer minDurationMillis) { + if (minDurationMillis == null || minDurationMillis < 0) { + return 0; + } + return minDurationMillis; + } + + private static OutputStream initLogStream(String fileName) { + String path = AppStorage.getAppUserdataDir() + File.separator + LOG_PATH; + Path logDir = FileUtils.createDirectoriesIfNotExist(Paths.get(path)); + Path logFileName = Paths.get(logDir.toString(), fileName); + return FileUtils.newOutpuStreamSafe(logFileName); + } + + private static String generateLogFilename() { + return String.format("log_%s.jpg", DATE_FORMATTER.format(Instant.now())); + } + +} diff --git a/sdk/examples/space/python-script/src/main/resources/scripts/myScript.py b/sdk/examples/space/python-script/src/main/resources/scripts/myScript.py new file mode 100644 index 000000000..981251b7b --- /dev/null +++ b/sdk/examples/space/python-script/src/main/resources/scripts/myScript.py @@ -0,0 +1,8 @@ +import time + +def start_demo(): + for x in range(1, 6): + print ("Hello, World! Counter:",x) + time.sleep(1) + +start_demo() From 9397313e823dca8e8e4b4827da9ce2760e764349 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 8 Apr 2022 16:11:57 +0200 Subject: [PATCH 036/173] Make the tcpip configuration to bind automatically. --- .../main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index bf70c07be..1116b72c4 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -149,15 +149,16 @@ public static String generateTransportProperties() throws IOException { str.append("org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); // Bind to localhost + /* str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); + */ - /* str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=true\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.host=xxx.xxx.xxx.xxx\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); - */ + return str.toString(); } From 6722b6a9c37a2d5bbb67003a3b90295ccb5aa890 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 14:03:56 +0200 Subject: [PATCH 037/173] [python-script app] Updated the output folder name and the file type (.log instead of .jpg) --- .../nmf/apps/pythonscript/run/PythonScriptExecutor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java index cac531649..264f686bb 100644 --- a/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java +++ b/sdk/examples/space/python-script/src/main/java/esa/mo/nmf/apps/pythonscript/run/PythonScriptExecutor.java @@ -42,9 +42,9 @@ public class PythonScriptExecutor { private static final Logger LOG = Logger.getLogger(PythonScriptExecutor.class.getName()); private static final String ENV_PROCESS_DURATION = "ENV_PROCESS_DURATION"; - private static final String LOG_PATH = "logs"; - private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss_SSSS") - .withZone(ZoneId.systemDefault()); + private static final String LOG_PATH = "output_logs"; + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter + .ofPattern("yyyyMMdd_HHmmss_SSSS").withZone(ZoneId.systemDefault()); private final DefaultExecutor executor = new DefaultExecutor(); private final long minDurationSeconds; @@ -118,7 +118,7 @@ private static OutputStream initLogStream(String fileName) { } private static String generateLogFilename() { - return String.format("log_%s.jpg", DATE_FORMATTER.format(Instant.now())); + return String.format("%s.log", DATE_FORMATTER.format(Instant.now())); } } From 1b839fd6c256fbe20b5f6f956acd79613812cf88 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 14:26:57 +0200 Subject: [PATCH 038/173] Code cleanup --- .../AppsLauncherProviderServiceImpl.java | 277 ++++++------ .../CommandExecutorProviderServiceImpl.java | 408 +++++++++--------- 2 files changed, 335 insertions(+), 350 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index cebfe2cfa..278bc060d 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -74,57 +74,110 @@ */ public class AppsLauncherProviderServiceImpl extends AppsLauncherInheritanceSkeleton implements ReconfigurableService { - public final static String PROVIDER_PREFIX_NAME = "App: "; - private static final Logger LOGGER = Logger.getLogger(AppsLauncherProviderServiceImpl.class.getName()); - // Maximum length of a stderr/stdout chunk to be persisted - allows downlinking it via SPP without issues - private static final int MAX_SEGMENT_SIZE = UShort.MAX_VALUE - 256; - private MALProvider appsLauncherServiceProvider; - private MonitorExecutionPublisher publisher; - private boolean initialiased = false; - private boolean running = false; - private boolean isRegistered = false; - private final Object lock = new Object(); - private AppsLauncherManager manager; - private final ConnectionProvider connection = new ConnectionProvider(); - private COMServicesProvider comServices; - private DirectoryProviderServiceImpl directoryService; - private ConfigurationChangeListener configurationAdapter; - private int stdLimit; // Limit of stdout/stderr to allow in the archive. - // Set of app ids for which the warning about verbose logging was sent - private final Set verboseLoggingWarningSent = new HashSet<>(); - /** - * Object used to track archive usage by STD output of each app - */ - private Quota stdQuota = new Quota(); - - /** - * Initializes the Event service provider - * - * @param comServices - * @param directoryService - * @throws MALException On initialization error. - */ - public synchronized void init(final COMServicesProvider comServices, - final DirectoryProviderServiceImpl directoryService) throws MALException { - if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { - COMHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { - SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + public final static String PROVIDER_PREFIX_NAME = "App: "; + private static final Logger LOGGER = Logger.getLogger( + AppsLauncherProviderServiceImpl.class.getName()); + // Maximum length of a stderr/stdout chunk to be persisted - allows downlinking it via SPP without issues + private static final int MAX_SEGMENT_SIZE = UShort.MAX_VALUE - 256; + private MALProvider appsLauncherServiceProvider; + private MonitorExecutionPublisher publisher; + private boolean initialiased = false; + private boolean running = false; + private boolean isRegistered = false; + private final Object lock = new Object(); + private AppsLauncherManager manager; + private final ConnectionProvider connection = new ConnectionProvider(); + private COMServicesProvider comServices; + private DirectoryProviderServiceImpl directoryService; + private ConfigurationChangeListener configurationAdapter; + private int stdLimit; // Limit of stdout/stderr to allow in the archive. + // Set of app ids for which the warning about verbose logging was sent + private final Set verboseLoggingWarningSent = new HashSet<>(); + /** + * Object used to track archive usage by STD output of each app + */ + private Quota stdQuota = new Quota(); + + /** + * Initializes the Event service provider + * + * @param comServices + * @param directoryService + * @throws MALException On initialization error. + */ + public synchronized void init(final COMServicesProvider comServices, + final DirectoryProviderServiceImpl directoryService) throws MALException { + if (!initialiased) { + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { + AppsLauncherHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + } + int kbyte = Integer.parseInt(System.getProperty(Const.APPSLAUNCHER_STD_LIMIT_PROPERTY, + Const.APPSLAUNCHER_STD_LIMIT_DEFAULT)); + stdLimit = kbyte * 1024; // init limit with value of property + publisher = createMonitorExecutionPublisher(ConfigurationProviderSingleton.getDomain(), + ConfigurationProviderSingleton.getNetwork(), + SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), + QoSLevel.BESTEFFORT, + null, + new UInteger(0)); + + // Shut down old service transport + if (null != appsLauncherServiceProvider) { + connection.closeAll(); + } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { - AppsLauncherHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + this.comServices = comServices; + this.directoryService = directoryService; + manager = new AppsLauncherManager(comServices); + appsLauncherServiceProvider = connection.startService( + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME.toString(), + AppsLauncherHelper.APPSLAUNCHER_SERVICE, this); + running = true; + initialiased = true; + + LOGGER.log(Level.INFO, "Apps Launcher service READY"); + } + + public ConnectionProvider getConnectionProvider() { + return this.connection; + } + + /** + * Set the common quota object used by ArchiveSync service and AppsLauncherService. The quota gets + * freed by ArchiveSync after synchronizing STDOUT/STDERR entries. + * + * @param q The same Quota object passed to ArchiveSyncProviderServiceImpl. + */ + public void setStdQuotaPerApp(Quota q) { + this.stdQuota = q; + } + + private void publishExecutionMonitoring(final Long appObjId, final String outputText, + ObjectType objType) { + try { + synchronized (lock) { + if (!isRegistered) { + final EntityKeyList lst = new EntityKeyList(); + lst.add(new EntityKey(new Identifier("*"), 0L, 0L, 0L)); + publisher.register(lst, new PublishInteractionListener()); + isRegistered = true; } int kbyte = Integer.parseInt(System.getProperty(Const.APPSLAUNCHER_STD_LIMIT_PROPERTY, Const.APPSLAUNCHER_STD_LIMIT_DEFAULT)); @@ -266,10 +319,11 @@ public void runApp(LongList appInstIds, MALInteraction interaction) throws MALIn } } - // Errors - if (!invIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); - } + if (!unkIndexList.isEmpty()) { + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList) + ); + } if (!unkIndexList.isEmpty()) { throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); @@ -510,96 +564,30 @@ public ListAppResponse listApp(final IdentifierList appNames, final Identifier c } } - if (!unkIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); - } - - for (Long id : ids) { // Is the app running? - runningApps.add(manager.isAppRunning(id)); - } - - outList.setBodyElement0(ids); - outList.setBodyElement1(runningApps); - - return outList; + @Override + public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) + throws MALException { + LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); } @Override - public void setOnConfigurationChangeListener(final ConfigurationChangeListener configurationAdapter) { - this.configurationAdapter = configurationAdapter; + public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, + final Map qosProperties) + throws MALException { + LOGGER.warning("PublishInteractionListener::publishErrorReceived"); } @Override - public Boolean reloadConfiguration(ConfigurationObjectDetails configurationObjectDetails) { - // Validate the configuration... - if (configurationObjectDetails == null) { - return false; - } - - if (configurationObjectDetails.getConfigObjects() == null) { - return false; - } - - // Is the size 1? - if (configurationObjectDetails.getConfigObjects().size() != 1) { // 1 because we just have Apps as configuration objects in this service - return false; - } - - ConfigurationObjectSet confSet = configurationObjectDetails.getConfigObjects().get(0); - - // Confirm the objType - if (!confSet.getObjType().equals(AppsLauncherHelper.APP_OBJECT_TYPE)) { - return false; - } - - // Confirm the domain - if (!confSet.getDomain().equals(ConfigurationProviderSingleton.getDomain())) { - return false; - } - - // If the list is empty, reconfigure the service with nothing... - if (confSet.getObjInstIds().isEmpty()) { - manager.reconfigureDefinitions(new LongList(), new AppDetailsList()); // Reconfigures the Manager - return true; - } - - // ok, we're good to go... - // Load the App Details from this configuration... - AppDetailsList pDefs = (AppDetailsList) HelperArchive.getObjectBodyListFromArchive(manager.getArchiveService(), - AppsLauncherHelper.APP_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), confSet.getObjInstIds()); - - if (manager.reconfigureDefinitions(confSet.getObjInstIds(), pDefs)) { - for (Long id : confSet.getObjInstIds()) { // Set all running state to false - manager.setRunning(id, false, null); - } - } else { - LOGGER.log(Level.WARNING, "Failed to reconfigure definitions. Ids: {0} pDefs: {1}", new Object[]{confSet - .getObjInstIds(), pDefs}); - } - return true; + public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) + throws MALException { + LOGGER.fine("PublishInteractionListener::publishRegisterAckReceived"); +// Logger.getLogger(AppsLauncherProviderServiceImpl.class.getName()).log(Level.INFO, "Registration Ack: {0}", header.toString()); } @Override - public ConfigurationObjectDetails getCurrentConfiguration() { - // Get all the current objIds in the serviceImpl - // Create a Configuration Object with all the objs of the provider - final HashMap defObjs = manager.getCurrentDefinitionsConfiguration(); - - final ConfigurationObjectSet objsSet = new ConfigurationObjectSet(); - objsSet.setDomain(ConfigurationProviderSingleton.getDomain()); - LongList currentObjIds = new LongList(); - currentObjIds.addAll(defObjs.keySet()); - objsSet.setObjInstIds(currentObjIds); - objsSet.setObjType(AppsLauncherHelper.APP_OBJECT_TYPE); - - final ConfigurationObjectSetList list = new ConfigurationObjectSetList(); - list.add(objsSet); - - // Needs the Common API here! - final ConfigurationObjectDetails set = new ConfigurationObjectDetails(); - set.setConfigObjects(list); - - return set; + public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, + final Map qosProperties) throws MALException { + LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); } @Override @@ -635,22 +623,9 @@ public void publishRegisterErrorReceived(final MALMessageHeader header, final MA } } - private class CallbacksImpl implements ProcessExecutionHandler.Callbacks { - - @Override - public void flushStdout(Long objId, String data) { - publishExecutionMonitoring(objId, data, CommandExecutorHelper.STANDARDOUTPUT_OBJECT_TYPE); - } - - @Override - public void flushStderr(Long objId, String data) { - publishExecutionMonitoring(objId, data, CommandExecutorHelper.STANDARDERROR_OBJECT_TYPE); - } - - @Override - public void processStopped(Long objId, int exitCode) { - manager.setRunning(objId, false, null); - } + @Override + public void processStopped(Long objId, int exitCode) { + manager.setRunning(objId, false, null); } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java index 5187aad85..7f09f29dc 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java @@ -62,232 +62,242 @@ import org.ccsds.moims.mo.softwaremanagement.commandexecutor.structures.CommandDetailsList; /** - * Apps Launcher service Provider. + * Command Executor service Provider. */ public class CommandExecutorProviderServiceImpl extends CommandExecutorInheritanceSkeleton { - private static final Logger LOGGER = Logger.getLogger(CommandExecutorProviderServiceImpl.class.getName()); - private final ConnectionProvider connection = new ConnectionProvider(); - private MALProvider commandExecutorServiceProvider; - private boolean initialiased = false; - private EventProviderServiceImpl eventService; - private ArchiveProviderServiceImpl archiveService; - private final OSValidator osValidator = new OSValidator(); - private final Map cachedCommandDetails = new HashMap<>(); + private static final Logger LOGGER = Logger.getLogger( + CommandExecutorProviderServiceImpl.class.getName()); + private final ConnectionProvider connection = new ConnectionProvider(); + private MALProvider commandExecutorServiceProvider; + private boolean initialiased = false; + private EventProviderServiceImpl eventService; + private ArchiveProviderServiceImpl archiveService; + private final OSValidator osValidator = new OSValidator(); + private final Map cachedCommandDetails = new HashMap<>(); - /** - * Initializes the service provider - * - * @param comServices - * @throws MALException On initialization error. - */ - public synchronized void init(final COMServicesProvider comServices) throws MALException { - if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + /** + * Initializes the service provider + * + * @param comServices + * @throws MALException On initialization error. + */ + public synchronized void init(final COMServicesProvider comServices) throws MALException { + if (!initialiased) { + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { - COMHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { - SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME) == null) { - CommandExecutorHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - } - archiveService = comServices.getArchiveService(); - if (archiveService == null) { - throw new MALException("Cannot access the COM Archive Service."); - } - eventService = comServices.getEventService(); - if (eventService == null) { - throw new MALException("Cannot access the COM Event Service."); - } - // Shut down old service transport - if (null != commandExecutorServiceProvider) { - connection.closeAll(); - } + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME) == null) { + CommandExecutorHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + } + archiveService = comServices.getArchiveService(); + if (archiveService == null) { + throw new MALException("Cannot access the COM Archive Service."); + } + eventService = comServices.getEventService(); + if (eventService == null) { + throw new MALException("Cannot access the COM Event Service."); + } + // Shut down old service transport + if (null != commandExecutorServiceProvider) { + connection.closeAll(); + } - commandExecutorServiceProvider = connection.startService(CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME - .toString(), CommandExecutorHelper.COMMANDEXECUTOR_SERVICE, this); - initialiased = true; + commandExecutorServiceProvider = connection.startService( + CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME.toString(), + CommandExecutorHelper.COMMANDEXECUTOR_SERVICE, this); + initialiased = true; - LOGGER.log(Level.INFO, "READY"); - } + LOGGER.log(Level.INFO, "Command Executor service READY"); + } - protected String[] assembleCommand(final String command) { - ArrayList ret = new ArrayList<>(); - if (osValidator.isWindows()) { - ret.add("cmd"); - ret.add("/c"); - ret.add(command); - } else { - ret.add("/bin/sh"); - ret.add("-c"); - ret.add(command); - } - return ret.toArray(new String[0]); + protected String[] assembleCommand(final String command) { + ArrayList ret = new ArrayList<>(); + if (osValidator.isWindows()) { + ret.add("cmd"); + ret.add("/c"); + ret.add(command); + } else { + ret.add("/bin/sh"); + ret.add("-c"); + ret.add(command); } + return ret.toArray(new String[0]); + } - @Override - public Long runCommand(CommandDetails command, MALInteraction interaction) throws MALInteractionException, - MALException { - Long storedCommandObject; - if (command == null) { - throw new MALException("Received null CommandDetails."); - } - - // Source could be mapped to an OperationActivity associated with this transaction, but for now - // we don't need such fine tracking... - final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(null, null, connection - .getPrimaryConnectionDetails().getProviderURI()); - final CommandDetailsList objBodies = new CommandDetailsList(1); - objBodies.add(command); - LongList objIds = archiveService.store(true, CommandExecutorHelper.COMMAND_OBJECT_TYPE, connection - .getPrimaryConnectionDetails().getDomain(), archDetails, objBodies, null); + @Override + public Long runCommand(CommandDetails command, MALInteraction interaction) + throws MALInteractionException, MALException { + Long storedCommandObject; + if (command == null) { + throw new MALException("Received null CommandDetails."); + } - if (objIds.size() == 1) { - storedCommandObject = objIds.get(0); - } else { - throw new MALException("Unexpected return from the archive store."); - } + // Source could be mapped to an OperationActivity associated with this transaction, but for now + // we don't need such fine tracking... + final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList( + null, null, connection.getPrimaryConnectionDetails().getProviderURI()); + final CommandDetailsList objBodies = new CommandDetailsList(1); + objBodies.add(command); + LongList objIds = archiveService.store( + true, + CommandExecutorHelper.COMMAND_OBJECT_TYPE, + connection.getPrimaryConnectionDetails().getDomain(), + archDetails, + objBodies, + null); - String[] shellCommand = assembleCommand(command.getCommand()); - final ProcessBuilder pb = new ProcessBuilder(shellCommand); - Map env = pb.environment(); - // Reuse the environment - // env.clear(); - File workingDir = pb.directory(); - if (workingDir == null) { - workingDir = Paths.get("").toFile(); - } - LOGGER.log(Level.INFO, "Running ''{0}'' in dir: {1}, and env: {2}", new Object[]{Arrays.toString(shellCommand), - workingDir.getAbsolutePath(), - Arrays.toString( - EnvironmentUtils.toStrings( - env))}); - final Process proc; - try { - proc = pb.start(); - ProcessExecutionHandler handler = new ProcessExecutionHandler(new CallbacksImpl(), storedCommandObject); - handler.monitorProcess(proc); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - throw new MALException("Cannot start the process!", ex); - } - long pid; - try { - pid = ProcessExecutionHandler.getProcessPid(proc); - } catch (IOException ex) { - pid = -1; - } - command.setPid(pid); - updateCommandDetails(storedCommandObject, command); - return storedCommandObject; + if (objIds.size() == 1) { + storedCommandObject = objIds.get(0); + } else { + throw new MALException("Unexpected return from the archive store."); } - private void commandOutputEvent(final Long objId, final String outputText, final ObjectType objType) { - IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); - URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); - ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, objId)); - Element eventBody = new Union(outputText); - StringList eventBodyList = new StringList(1); - eventBodyList.add(outputText); - final Long eventObjId = eventService.generateAndStoreEvent(objType, domain, eventBody, null, source, connection - .getPrimaryConnectionDetails().getProviderURI(), null); - if (eventObjId != null) { - try { - eventService.publishEvent(sourceURI, eventObjId, objType, null, source, eventBodyList); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Could not publish command output event", ex); - } - } else { - LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); - } + String[] shellCommand = assembleCommand(command.getCommand()); + final ProcessBuilder pb = new ProcessBuilder(shellCommand); + Map env = pb.environment(); + // Reuse the environment + // env.clear(); + File workingDir = pb.directory(); + if (workingDir == null) { + workingDir = Paths.get("").toFile(); + } + LOGGER.log(Level.INFO, "Running ''{0}'' in dir: {1}, and env: {2}", new Object[]{ + Arrays.toString(shellCommand), workingDir.getAbsolutePath(), + Arrays.toString(EnvironmentUtils.toStrings(env))}); + final Process proc; + try { + proc = pb.start(); + ProcessExecutionHandler handler = new ProcessExecutionHandler(new CallbacksImpl(), + storedCommandObject); + handler.monitorProcess(proc); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + throw new MALException("Cannot start the process!", ex); } + long pid; + try { + pid = ProcessExecutionHandler.getProcessPid(proc); + } catch (IOException ex) { + pid = -1; + } + command.setPid(pid); + updateCommandDetails(storedCommandObject, command); + return storedCommandObject; + } - private void commandExitEvent(final Long objId, final int exitCode) { - IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); - URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); - ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, objId)); - Element eventBody = new Union(exitCode); - IntegerList eventBodyList = new IntegerList(1); - eventBodyList.add(exitCode); - final Long eventObjId = eventService.generateAndStoreEvent(CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, - domain, eventBody, null, source, connection.getPrimaryConnectionDetails().getProviderURI(), null); - if (eventObjId != null) { - try { - eventService.publishEvent(sourceURI, eventObjId, CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, - null, source, eventBodyList); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Could not publish command exit event", ex); - } - } else { - LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); - } - try { - CommandDetails command = getCommandDetails(objId); - command.setExitCode(exitCode); - updateCommandDetails(objId, command); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Cannot update COM Command object", ex); - } + private void commandOutputEvent(final Long objId, final String outputText, + final ObjectType objType) { + IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); + URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); + ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, + objId)); + Element eventBody = new Union(outputText); + StringList eventBodyList = new StringList(1); + eventBodyList.add(outputText); + final Long eventObjId = eventService.generateAndStoreEvent(objType, domain, eventBody, null, + source, connection.getPrimaryConnectionDetails().getProviderURI(), null); + if (eventObjId != null) { + try { + eventService.publishEvent(sourceURI, eventObjId, objType, null, source, eventBodyList); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Could not publish command output event", ex); + } + } else { + LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); } + } - private CommandDetails getCommandDetails(Long objId) throws IOException { - if (cachedCommandDetails.containsKey(objId)) { - return cachedCommandDetails.get(objId); - } else { - Element retrievedObject = HelperArchive.getObjectBodyFromArchive(archiveService, - CommandExecutorHelper.COMMAND_OBJECT_TYPE, connection.getPrimaryConnectionDetails().getDomain(), objId); - if (retrievedObject == null) { - throw new IOException("Could not retrieve Command object for objId: " + objId); - } - CommandDetails ret = (CommandDetails) retrievedObject; - cachedCommandDetails.put(objId, ret); - return ret; - } + private void commandExitEvent(final Long objId, final int exitCode) { + IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); + URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); + ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, + objId)); + Element eventBody = new Union(exitCode); + IntegerList eventBodyList = new IntegerList(1); + eventBodyList.add(exitCode); + final Long eventObjId = eventService.generateAndStoreEvent( + CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, domain, eventBody, null, + source, connection.getPrimaryConnectionDetails().getProviderURI(), null); + if (eventObjId != null) { + try { + eventService.publishEvent(sourceURI, eventObjId, + CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, null, source, eventBodyList); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Could not publish command exit event", ex); + } + } else { + LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); + } + try { + CommandDetails command = getCommandDetails(objId); + command.setExitCode(exitCode); + updateCommandDetails(objId, command); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Cannot update COM Command object", ex); } + } - private void updateCommandDetails(Long objId, CommandDetails command) { - cachedCommandDetails.put(objId, command); - final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(null, null, - ConfigurationProviderSingleton.getNetwork(), connection.getPrimaryConnectionDetails().getProviderURI(), - objId); - final CommandDetailsList objBodies = new CommandDetailsList(1); - objBodies.add(command); - try { - archiveService.update(CommandExecutorHelper.COMMAND_OBJECT_TYPE, connection.getPrimaryConnectionDetails() - .getDomain(), archDetails, objBodies, null); - } catch (MALException | MALInteractionException ex) { - Logger.getLogger(CommandExecutorProviderServiceImpl.class.getName()).log(Level.SEVERE, - "Could not update COM Command object", ex); - } + private CommandDetails getCommandDetails(Long objId) throws IOException { + if (cachedCommandDetails.containsKey(objId)) { + return cachedCommandDetails.get(objId); + } else { + Element retrievedObject = HelperArchive.getObjectBodyFromArchive( + archiveService, CommandExecutorHelper.COMMAND_OBJECT_TYPE, + connection.getPrimaryConnectionDetails().getDomain(), objId); + if (retrievedObject == null) { + throw new IOException("Could not retrieve Command object for objId: " + objId); + } + CommandDetails ret = (CommandDetails) retrievedObject; + cachedCommandDetails.put(objId, ret); + return ret; } + } - private class CallbacksImpl implements ProcessExecutionHandler.Callbacks { + private void updateCommandDetails(Long objId, CommandDetails command) { + cachedCommandDetails.put(objId, command); + final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(null, null, + ConfigurationProviderSingleton.getNetwork(), + connection.getPrimaryConnectionDetails().getProviderURI(), objId); + final CommandDetailsList objBodies = new CommandDetailsList(1); + objBodies.add(command); + try { + archiveService.update( + CommandExecutorHelper.COMMAND_OBJECT_TYPE, + connection.getPrimaryConnectionDetails().getDomain(), archDetails, objBodies, null); + } catch (MALException | MALInteractionException ex) { + Logger.getLogger(CommandExecutorProviderServiceImpl.class.getName()).log(Level.SEVERE, + "Could not update COM Command object", ex); + } + } - @Override - public void flushStdout(Long objId, String data) { - commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDOUTPUT_OBJECT_TYPE); - } + private class CallbacksImpl implements ProcessExecutionHandler.Callbacks { - @Override - public void flushStderr(Long objId, String data) { - commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDERROR_OBJECT_TYPE); - } + @Override + public void flushStdout(Long objId, String data) { + commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDOUTPUT_OBJECT_TYPE); + } - @Override - public void processStopped(Long objId, int exitCode) { - commandExitEvent(objId, exitCode); + @Override + public void flushStderr(Long objId, String data) { + commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDERROR_OBJECT_TYPE); + } - } + @Override + public void processStopped(Long objId, int exitCode) { + commandExitEvent(objId, exitCode); } } From 0e0b7a4f30261fc19a2e81a2f08b41933f7115ed Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 14:42:29 +0200 Subject: [PATCH 039/173] More code cleanup --- .../sm/impl/provider/AppsLauncherManager.java | 672 +++++++++--------- .../AppsLauncherProviderServiceImpl.java | 466 ++++++------ .../CommandExecutorProviderServiceImpl.java | 417 +++++------ .../HeartbeatProviderServiceImpl.java | 58 +- .../PackageManagementProviderServiceImpl.java | 14 +- .../provider/ProcessExecutionHandler.java | 22 +- .../mo/sm/impl/util/ClosingAppListener.java | 3 +- .../java/esa/mo/sm/impl/util/PMBackend.java | 4 +- .../mo/sm/impl/util/SMServicesConsumer.java | 54 +- .../mo/sm/impl/util/SMServicesProvider.java | 7 +- .../esa/mo/sm/impl/util/ShellCommander.java | 17 +- .../_OPS-SAT-SIMULATOR-header.txt | 23 + .../_OPS-SAT-SIMULATOR-scheduler.txt | 8 + .../_OPS-SAT-SIMULATOR-templates.txt | 2 + .../platformsim.properties | 6 + 15 files changed, 928 insertions(+), 845 deletions(-) create mode 100644 core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-header.txt create mode 100644 core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-scheduler.txt create mode 100644 core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-templates.txt create mode 100644 core/nmf-composites/nanosat-mo-supervisor/platformsim.properties diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index a742ccb53..afaca5cda 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -73,35 +73,49 @@ * * @author Cesar Coelho */ -public class AppsLauncherManager extends DefinitionsManager -{ +public class AppsLauncherManager extends DefinitionsManager { - private static final int APP_STOP_TIMEOUT = 15000; + private static final int APP_STOP_TIMEOUT = 15000; - private static final Logger LOGGER = Logger.getLogger(AppsLauncherManager.class.getName()); + private static final Logger LOGGER = Logger.getLogger(AppsLauncherManager.class.getName()); - private final OSValidator osValidator = new OSValidator(); + private final OSValidator osValidator = new OSValidator(); - private boolean sudoAvailable = false; - - private static final String FOLDER_LOCATION_PROPERTY - = "esa.mo.sm.impl.provider.appslauncher.FolderLocation"; + private boolean sudoAvailable = false; - private static final String DEFAULT_APPS_FOLDER_PATH - = ".." + File.separator + ".." + File.separator + "apps"; - - /** - * Location of the apps folder, relative to the MO Supervisor - */ - private File appsFolderPath; - private final HashMap handlers - = new HashMap<>(); + private static final String FOLDER_LOCATION_PROPERTY + = "esa.mo.sm.impl.provider.appslauncher.FolderLocation"; + + private static final String DEFAULT_APPS_FOLDER_PATH + = ".." + File.separator + ".." + File.separator + "apps"; + + /** + * Location of the apps folder, relative to the MO Supervisor + */ + private File appsFolderPath; + private final HashMap handlers + = new HashMap<>(); + + private AtomicLong uniqueObjIdDef; // Counter + + public AppsLauncherManager(COMServicesProvider comServices) { + super(comServices); + + // If there is a property for that, then use it!! + if (System.getProperty(FOLDER_LOCATION_PROPERTY) != null) { + appsFolderPath = new File(System.getProperty(FOLDER_LOCATION_PROPERTY)); + } else { + LOGGER.log(Level.INFO, + "Property not set: {0} \nUsing default apps directory: {1}", + new Object[]{FOLDER_LOCATION_PROPERTY, DEFAULT_APPS_FOLDER_PATH}); + appsFolderPath = new File(DEFAULT_APPS_FOLDER_PATH); + } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) != null && MALContextFactory.lookupArea( - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) != null + && MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { try { AppsLauncherHelper.init(MALContextFactory.getElementFactoryRegistry()); } catch (MALException ex) { @@ -115,6 +129,25 @@ public class AppsLauncherManager extends DefinitionsManager // With Archive... } + if (osValidator.isUnix()) { + try { + String[] params = new String[]{"sh", "-c", "sudo --help"}; + Process p = Runtime.getRuntime().exec(params, null, null); + try { + boolean terminated = p.waitFor(1, TimeUnit.SECONDS); + if (terminated) { + sudoAvailable = (p.exitValue() != 127); + } + } catch (InterruptedException ex) { + Logger.getLogger(AppsLauncherManager.class.getName()).log( + Level.SEVERE, "The process did no finish yet...", ex); + sudoAvailable = false; + } + } catch (IOException ex) { + Logger.getLogger(AppsLauncherManager.class.getName()).log( + Level.SEVERE, "The process could not be executed!", ex); + } + } } protected AppDetailsList getAll() { @@ -126,60 +159,9 @@ public Boolean compareName(Long objId, Identifier name) { return this.get(objId).getName().equals(name); } - if(osValidator.isUnix()){ - try { - String[] params = new String[]{"sh", "-c", "sudo --help"}; - Process p = Runtime.getRuntime().exec(params, null, null); - try { - boolean terminated = p.waitFor(1, TimeUnit.SECONDS); - if(terminated){ - sudoAvailable = (p.exitValue() != 127); - } - } catch (InterruptedException ex) { - Logger.getLogger(AppsLauncherManager.class.getName()).log( - Level.SEVERE, "The process did no finish yet...", ex); - sudoAvailable = false; - } - } catch (IOException ex) { - Logger.getLogger(AppsLauncherManager.class.getName()).log( - Level.SEVERE, "The process could not be executed!", ex); - } - } - } - - protected AppDetailsList getAll() - { - return (AppDetailsList) this.getAllDefs(); - } - - @Override - public Boolean compareName(Long objId, Identifier name) - { - return this.get(objId).getName().equals(name); - } - - @Override - public ElementList newDefinitionList() - { - return new AppDetailsList(); - } - - public AppDetails get(Long input) - { - return (AppDetails) this.getDef(input); - } - - protected Long addApp(final AppDetails definition, final ObjectId source, final URI uri) - { - Long objId = null; - Long related = null; - - if (definition.getExtraInfo() != null) { - try { // Read the provider.properties of the app - objId = readAppObjectId(definition); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } + @Override + public ElementList newDefinitionList() { + return new AppDetailsList(); } public AppDetails get(Long input) { @@ -236,8 +218,8 @@ protected Long addApp(final AppDetails definition, final ObjectId source, final private Long readAppObjectId(final AppDetails definition) throws IOException { Long objId; - File fileProps = new File(appsFolderPath.getCanonicalPath() + File.separator + definition.getName().getValue() + - File.separator + definition.getExtraInfo()); + File fileProps = new File(appsFolderPath.getCanonicalPath() + File.separator + definition. + getName().getValue() + File.separator + definition.getExtraInfo()); Properties props = HelperMisc.loadProperties(fileProps.getCanonicalPath()); @@ -249,17 +231,24 @@ private Long readAppObjectId(final AppDetails definition) throws IOException { } private LongList addAppToArchive(final AppDetails definition, final ObjectId source, final URI uri, Long objId, - Long related) throws MALException, MALInteractionException { + Long related) throws MALException, MALInteractionException { AppDetailsList defs = new AppDetailsList(); defs.add(definition); - final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(related, source, uri); + final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(related, + source, uri); archDetails.get(0).setInstId(objId); - return super.getArchiveService().store(true, AppsLauncherHelper.APP_OBJECT_TYPE, ConfigurationProviderSingleton - .getDomain(), archDetails, defs, null); + return super.getArchiveService().store( + true, + AppsLauncherHelper.APP_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + archDetails, + defs, + null); } - protected boolean update(final Long objId, final AppDetails definition, final MALInteraction interaction) { // requirement: 3.3.2.5 + protected boolean update(final Long objId, final AppDetails definition, + final MALInteraction interaction) { // requirement: 3.3.2.5 boolean success = this.updateDef(objId, definition); if (super.getArchiveService() != null) { // It should also update on the COM Archive @@ -275,13 +264,14 @@ protected boolean update(final Long objId, final AppDetails definition, final MA } private void updateAppInArchive(final Long objId, final AppDetails definition, final MALInteraction interaction) - throws MALException, MALInteractionException { + throws MALException, MALInteractionException { AppDetailsList defs = new AppDetailsList(); defs.add(definition); final IdentifierList domain = ConfigurationProviderSingleton.getDomain(); - ArchiveDetails archiveDetails = HelperArchive.getArchiveDetailsFromArchive(super.getArchiveService(), - AppsLauncherHelper.APP_OBJECT_TYPE, domain, objId); + ArchiveDetails archiveDetails = HelperArchive.getArchiveDetailsFromArchive(super. + getArchiveService(), + AppsLauncherHelper.APP_OBJECT_TYPE, domain, objId); if (archiveDetails == null) { throw new MALException("No object present in archive."); } @@ -289,76 +279,41 @@ private void updateAppInArchive(final Long objId, final AppDetails definition, f ArchiveDetailsList archiveDetailsList = new ArchiveDetailsList(); archiveDetailsList.add(archiveDetails); - super.getArchiveService().update(AppsLauncherHelper.APP_OBJECT_TYPE, domain, archiveDetailsList, defs, - interaction); + super.getArchiveService().update( + AppsLauncherHelper.APP_OBJECT_TYPE, + domain, + archiveDetailsList, + defs, + interaction); } - return this.get(appId).getRunning(); - } - - protected String[] assembleCommand(final String workDir, final String appName, final String runAs, final String prefix, final String[] env) - { - ArrayList ret = new ArrayList<>(); - String trimmedAppName = appName.replaceAll("space-app-", ""); - if (osValidator.isWindows()) { - ret.add("cmd"); - ret.add("/c"); - StringBuilder str = new StringBuilder(); - str.append(prefix); - str.append(trimmedAppName); - str.append(".bat"); - ret.add(str.toString()); - } else { - if (runAs != null) { - if(sudoAvailable){ - ret.add("sudo"); - } - ret.add("su"); - ret.add("-"); - ret.add(runAs); - ret.add("-c"); - } else { - ret.add("/bin/sh"); - ret.add("-c"); - } - StringBuilder envString = new StringBuilder(); - for (String envVar : env) { - envString.append(envVar); - envString.append(" "); - } - - ret.add("cd " + workDir + ";" + envString.toString() + "./" + prefix + trimmedAppName + ".sh"); + protected boolean delete(Long objId) { + return this.deleteDef(objId); } - return ret.toArray(new String[0]); - } - protected String[] assembleAppStopCommand(final String workDir, final String appName, final String runAs, final String[] env) - { - return assembleCommand(workDir, appName, runAs, "stop_", env); - } - - protected String[] assembleAppStartCommand(final String workDir, final String appName, final String runAs, final String[] env) - { - return assembleCommand(workDir, appName, runAs, "start_", env); - } - - protected HashMap assembleAppLauncherEnvironment(final String directoryServiceURI) - { - final HashMap targetEnv = new HashMap<>(); - try { - // Inherit NMF HOME and NMF LIB from the supervisor - Map parentEnv = EnvironmentUtils.getProcEnvironment(); - if (parentEnv.containsKey("NMF_LIB")) { - targetEnv.put("NMF_LIB", parentEnv.get("NMF_LIB")); - } - if (parentEnv.containsKey("NMF_HOME")) { - targetEnv.put("NMF_HOME", parentEnv.get("NMF_HOME")); - } - if (parentEnv.containsKey("PATH")) { - targetEnv.put("PATH", parentEnv.get("PATH")); - } - if (osValidator.isWindows()) { - if (parentEnv.containsKey("TEMP")) { - targetEnv.put("TEMP", parentEnv.get("TEMP")); + + protected boolean refreshAvailableAppsList(final URI providerURI) { + // Go to all the "apps folder" and check if there are new folders + // get all the files from a directory + File[] fList = appsFolderPath.listFiles(); + + if (fList == null) { + LOGGER.log(Level.SEVERE, "The directory could not be found: {0} (full path: {1})", + new Object[]{appsFolderPath.toString(), appsFolderPath.getAbsolutePath()}); + + return false; + } + + boolean anyChanges = false; + AppDetailsList apps = new AppDetailsList(); + + for (File folder : fList) { // Roll all the apps inside the apps folder + if (folder.isDirectory()) { + File propsFile = new File(folder, HelperMisc.PROVIDER_PROPERTIES_FILE); + if (propsFile.exists() && !propsFile.isDirectory()) { + AppDetails app = this.readAppDescriptor(folder.getName(), propsFile); + apps.add(app); + } + } } // Compare with the defs list! @@ -369,7 +324,8 @@ protected HashMap assembleAppLauncherEnvironment(final String di // It didn't exist... if (previousAppDetails == null) { - LOGGER.log(Level.INFO, "New app found! Adding new app: {0}", singleApp.getName().getValue()); + LOGGER.log(Level.INFO, + "New app found! Adding new app: {0}", singleApp.getName().getValue()); // Either is the first time running or it is a newly installed app! ObjectId source = null; @@ -386,123 +342,113 @@ protected HashMap assembleAppLauncherEnvironment(final String di } // Then we have to update it... - LOGGER.log(Level.INFO, "New update found on app: {0}\nPrevious: {1}\nNew: {2}", new Object[]{singleApp - .getName().getValue(), previousAppDetails, singleApp}); + LOGGER.log(Level.INFO, + "New update found on app: {0}\nPrevious: {1}\nNew: {2}", + new Object[]{singleApp.getName().getValue(), + previousAppDetails, singleApp}); this.update(id, singleApp, null); anyChanges = true; } } - } - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "getProcEnvironment failed!", ex); - } - // Extend the current environment by JAVA_OPTS - targetEnv.put("JAVA_OPTS", - "-D" + Const.CENTRAL_DIRECTORY_URI_PROPERTY + "=" + directoryServiceURI + ""); - - return targetEnv; - } - - protected void startAppProcess(final ProcessExecutionHandler handler, - final MALInteraction interaction, final String directoryServiceURI) throws IOException - { - // get it from the list of available apps - AppDetails app = (AppDetails) this.getDef(handler.getObjId()); - String appName = app.getName().getValue(); - - // Go to the folder where the app are installed - final File appFolder = new File(appsFolderPath + File.separator + appName); - Map env = assembleAppLauncherEnvironment(directoryServiceURI); - String[] appLauncherCommand = assembleAppStartCommand( - appFolder.getAbsolutePath(), - appName, - app.getRunAs(), - EnvironmentUtils.toStrings(env)); - - final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); - pb.environment().clear(); - pb.environment().putAll(env); - - pb.directory(appFolder); - LOGGER.log(Level.INFO, - "Initializing ''{0}'' app in dir: {1}, using launcher command: {2}", - new Object[]{appName, appFolder.getAbsolutePath(), Arrays.toString(appLauncherCommand)}); - final Process proc = pb.start(); - handler.monitorProcess(proc); - handlers.put(handler.getObjId(), handler); - this.setRunning(handler.getObjId(), true, interaction); // Update the Archive - } - - protected boolean killAppProcess(final Long appInstId, MALInteraction interaction) - { - AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps - String appName = app.getName().getValue(); - - LOGGER.log(Level.INFO, "Killing app: {0}", appName); - ProcessExecutionHandler handler = handlers.get(appInstId); - - if (handler == null) { - LOGGER.log(Level.INFO, - "Handler of {0} app is null, setting running = false.", appName); - app.setRunning(false); - return false; + + // Also needs to check if we removed a folder! + final LongList ids = this.listAll(); + final AppDetailsList localApps = this.getAll(); + for (int i = 0; i < ids.size(); i++) { // Roll all the apps inside the apps folder + AppDetails localApp = localApps.get(i); + boolean appStillIntact = false; + for (File folder : fList) { // Roll all the apps inside the apps folder + if (folder.isDirectory()) { + if (folder.getName().equals(localApp.getName().getValue())) { + for (File file : folder.listFiles()) { // Roll all the files inside each app folder + // Check if the folder contains the provider properties + if (HelperMisc.PROVIDER_PROPERTIES_FILE.equals(file.getName())) { + // All Good! + appStillIntact = true; + break; + } + } + } + } + } + + if (!appStillIntact) { + LOGGER.log(Level.INFO, + "The app has been removed: {0}", localApp.getName().getValue()); + + this.delete(ids.get(i)); + anyChanges = true; + } + } + + return anyChanges; } - if (handler.getProcess() == null) { - LOGGER.log(Level.INFO, - "Process of {0} app is null, setting running = false.", appName); - app.setRunning(false); - return true; + protected boolean isAppRunning(final Long appId) { + // get it from the list of available apps + AppDetails app = (AppDetails) this.getDef(appId); + ProcessExecutionHandler handler = handlers.get(appId); + + if (handler == null) { + LOGGER.log(Level.FINE, + "The Process handler could not be found!"); + + app.setRunning(false); + return false; + } + + return this.get(appId).getRunning(); } - handler.close(); - this.setRunning(handler.getObjId(), false, interaction); // Update the Archive - handlers.remove(appInstId); // Get rid of it! - - return true; - } - - protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interaction, boolean onlyNativeComponent) throws - IOException, MALInteractionException, MALException - { - AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps - - // Go to the folder where the app is installed - final File appFolder - = new File(appsFolderPath + File.separator + app.getName().getValue()); - Map env = assembleAppLauncherEnvironment(""); - final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), - app.getName().getValue(), app.getRunAs(), EnvironmentUtils.toStrings(env)); - - final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); - pb.environment().clear(); - pb.directory(appFolder); - LOGGER.log(Level.INFO, - "Stopping ''{0}'' app in dir: {1}, using launcher command: {2}", - new Object[]{app.getName().getValue(), appFolder.getAbsolutePath(), Arrays.toString( - appLauncherCommand)}); - final Process proc = pb.start(); - interaction.sendUpdate(appInstId); - boolean exitCleanly = false; - try { - exitCleanly = proc.waitFor(APP_STOP_TIMEOUT, TimeUnit.MILLISECONDS); - } catch (InterruptedException ex) { - LOGGER.log(Level.WARNING, null, ex); + protected String[] assembleCommand(final String workDir, final String appName, + final String runAs, final String prefix, final String[] env) { + ArrayList ret = new ArrayList<>(); + String trimmedAppName = appName.replaceAll("space-app-", ""); + if (osValidator.isWindows()) { + ret.add("cmd"); + ret.add("/c"); + StringBuilder str = new StringBuilder(); + str.append(prefix); + str.append(trimmedAppName); + str.append(".bat"); + ret.add(str.toString()); + } else { + if (runAs != null) { + if (sudoAvailable) { + ret.add("sudo"); + } + ret.add("su"); + ret.add("-"); + ret.add(runAs); + ret.add("-c"); + } else { + ret.add("/bin/sh"); + ret.add("-c"); + } + StringBuilder envString = new StringBuilder(); + for (String envVar : env) { + envString.append(envVar); + envString.append(" "); + } + + ret.add("cd " + workDir + ";" + envString.toString() + "./" + prefix + trimmedAppName + ".sh"); + } + return ret.toArray(new String[0]); } - protected String[] assembleAppStopCommand(final String workDir, final String appName, final String runAs, - final String[] env) { + protected String[] assembleAppStopCommand(final String workDir, + final String appName, final String runAs, final String[] env) { return assembleCommand(workDir, appName, runAs, "stop_", env); } - protected String[] assembleAppStartCommand(final String workDir, final String appName, final String runAs, - final String[] env) { + protected String[] assembleAppStartCommand(final String workDir, + final String appName, final String runAs, final String[] env) { return assembleCommand(workDir, appName, runAs, "start_", env); } - protected void assembleAppLauncherEnvironment(final String directoryServiceURI, - final Map targetEnv) { + protected HashMap assembleAppLauncherEnvironment(final String directoryServiceURI) { + final HashMap targetEnv = new HashMap<>(); try { // Inherit NMF HOME and NMF LIB from the supervisor Map parentEnv = EnvironmentUtils.getProcEnvironment(); @@ -512,10 +458,10 @@ protected void assembleAppLauncherEnvironment(final String directoryServiceURI, if (parentEnv.containsKey("NMF_HOME")) { targetEnv.put("NMF_HOME", parentEnv.get("NMF_HOME")); } + if (parentEnv.containsKey("PATH")) { + targetEnv.put("PATH", parentEnv.get("PATH")); + } if (osValidator.isWindows()) { - if (parentEnv.containsKey("PATH")) { - targetEnv.put("PATH", parentEnv.get("PATH")); - } if (parentEnv.containsKey("TEMP")) { targetEnv.put("TEMP", parentEnv.get("TEMP")); } @@ -527,29 +473,35 @@ protected void assembleAppLauncherEnvironment(final String directoryServiceURI, LOGGER.log(Level.SEVERE, "getProcEnvironment failed!", ex); } // Extend the current environment by JAVA_OPTS - targetEnv.put("JAVA_OPTS", "-D" + Const.CENTRAL_DIRECTORY_URI_PROPERTY + "=" + directoryServiceURI + ""); + targetEnv.put("JAVA_OPTS", + "-D" + Const.CENTRAL_DIRECTORY_URI_PROPERTY + "=" + directoryServiceURI + ""); + + return targetEnv; } - protected void startAppProcess(final ProcessExecutionHandler handler, final MALInteraction interaction, - final String directoryServiceURI) throws IOException { + protected void startAppProcess(final ProcessExecutionHandler handler, + final MALInteraction interaction, final String directoryServiceURI) throws IOException { // get it from the list of available apps AppDetails app = (AppDetails) this.getDef(handler.getObjId()); + String appName = app.getName().getValue(); // Go to the folder where the app are installed - final File appFolder = new File(appsFolderPath + File.separator + app.getName().getValue()); - Map env = new HashMap<>(); - assembleAppLauncherEnvironment(directoryServiceURI, env); - final String[] appLauncherCommand = assembleAppStartCommand(appFolder.getAbsolutePath(), app.getName() - .getValue(), app.getRunAs(), EnvironmentUtils.toStrings(env)); + final File appFolder = new File(appsFolderPath + File.separator + appName); + Map env = assembleAppLauncherEnvironment(directoryServiceURI); + String[] appLauncherCommand = assembleAppStartCommand( + appFolder.getAbsolutePath(), + appName, + app.getRunAs(), + EnvironmentUtils.toStrings(env)); final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); pb.environment().clear(); - if (osValidator.isWindows()) { - pb.environment().putAll(env); - } + pb.environment().putAll(env); + pb.directory(appFolder); - LOGGER.log(Level.INFO, "Initializing ''{0}'' app in dir: {1}, using launcher command: {2}", new Object[]{app - .getName().getValue(), appFolder.getAbsolutePath(), Arrays.toString(appLauncherCommand)}); + LOGGER.log(Level.INFO, + "Initializing ''{0}'' app in dir: {1}, using launcher command: {2}", + new Object[]{appName, appFolder.getAbsolutePath(), Arrays.toString(appLauncherCommand)}); final Process proc = pb.start(); handler.monitorProcess(proc); handlers.put(handler.getObjId(), handler); @@ -558,18 +510,21 @@ protected void startAppProcess(final ProcessExecutionHandler handler, final MALI protected boolean killAppProcess(final Long appInstId, MALInteraction interaction) { AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps + String appName = app.getName().getValue(); - LOGGER.log(Level.INFO, "Killing app: {0}", app.getName().getValue()); + LOGGER.log(Level.INFO, "Killing app: {0}", appName); ProcessExecutionHandler handler = handlers.get(appInstId); if (handler == null) { - LOGGER.log(Level.INFO, "Handler of {0} app is null, setting running = false.", app.getName().getValue()); + LOGGER.log(Level.INFO, + "Handler of {0} app is null, setting running = false.", appName); app.setRunning(false); return false; } if (handler.getProcess() == null) { - LOGGER.log(Level.INFO, "Process of {0} app is null, setting running = false.", app.getName().getValue()); + LOGGER.log(Level.INFO, + "Process of {0} app is null, setting running = false.", appName); app.setRunning(false); return true; } @@ -581,22 +536,24 @@ protected boolean killAppProcess(final Long appInstId, MALInteraction interactio return true; } - protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interaction, boolean onlyNativeComponent) - throws IOException, MALInteractionException, MALException { + protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interaction, + boolean onlyNativeComponent) throws IOException, MALInteractionException, MALException { AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps // Go to the folder where the app is installed - final File appFolder = new File(appsFolderPath + File.separator + app.getName().getValue()); - Map env = new HashMap<>(); - assembleAppLauncherEnvironment("", env); - final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), app.getName() - .getValue(), app.getRunAs(), EnvironmentUtils.toStrings(env)); + final File appFolder + = new File(appsFolderPath + File.separator + app.getName().getValue()); + Map env = assembleAppLauncherEnvironment(""); + final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), + app.getName().getValue(), app.getRunAs(), EnvironmentUtils.toStrings(env)); final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); pb.environment().clear(); pb.directory(appFolder); - LOGGER.log(Level.INFO, "Stopping ''{0}'' app in dir: {1}, using launcher command: {2}", new Object[]{app - .getName().getValue(), appFolder.getAbsolutePath(), Arrays.toString(appLauncherCommand)}); + LOGGER.log(Level.INFO, + "Stopping ''{0}'' app in dir: {1}, using launcher command: {2}", + new Object[]{app.getName().getValue(), appFolder.getAbsolutePath(), Arrays.toString( + appLauncherCommand)}); final Process proc = pb.start(); interaction.sendUpdate(appInstId); boolean exitCleanly = false; @@ -605,25 +562,12 @@ protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interac } catch (InterruptedException ex) { LOGGER.log(Level.WARNING, null, ex); } - if (stopExists) { - Map env = assembleAppLauncherEnvironment(""); - final File appFolder - = new File(appsFolderPath + File.separator + curr.getName().getValue()); - final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), - curr.getName().getValue(), curr.getRunAs(), EnvironmentUtils.toStrings(env)); - final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); - pb.environment().clear(); - pb.directory(appFolder); - - LOGGER.log(Level.INFO, - "Stopping native component of ''{0}'' app", - new Object[]{curr.getName().getValue()}); - try { - this.stopNativeApp(appInstId, interaction, true); - } catch (IOException ex) { - Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.SEVERE, - "Stopping native component failed", ex); - } + if (!exitCleanly) { + LOGGER.log(Level.WARNING, + "App {0} stop script did not exit within the timeout ({1} ms). " + + "Killing the stop script and forcing the app exit.", + new Object[]{app.getName().getValue(), APP_STOP_TIMEOUT}); + proc.destroyForcibly(); } if (onlyNativeComponent) { return true; @@ -632,35 +576,39 @@ protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interac } protected void stopNMFApp(final Long appInstId, final Identifier appDirectoryServiceName, - final SingleConnectionDetails appConnection, final StopAppInteraction interaction) throws MALException, - MALInteractionException { + final SingleConnectionDetails appConnection, + final StopAppInteraction interaction) throws MALException, MALInteractionException { ClosingAppListener listener = null; // Register on the Event service of the respective apps // Select all object numbers from the Apps Launcher service Events - Subscription eventSub = HelperCOM.generateSubscriptionCOMEvent("ClosingAppEvents", - AppsLauncherHelper.APP_OBJECT_TYPE); + Subscription eventSub = HelperCOM.generateSubscriptionCOMEvent( + "ClosingAppEvents", + AppsLauncherHelper.APP_OBJECT_TYPE); try { // Subscribe to events EventConsumerServiceImpl eventServiceConsumer = new EventConsumerServiceImpl(appConnection); - Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.FINE, "Connected to: {0}", appConnection - .toString()); - listener = new ClosingAppListener(interaction, eventServiceConsumer, appInstId); + Logger.getLogger(AppsLauncherManager.class.getName()).log( + Level.FINE, "Connected to: {0}", appConnection.toString()); + listener = new ClosingAppListener(interaction, eventServiceConsumer, + appInstId); eventServiceConsumer.addEventReceivedListener(eventSub, listener); } catch (MalformedURLException ex) { - Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.SEVERE, "Could not connect to the app!"); + Logger.getLogger(AppsLauncherManager.class.getName()).log( + Level.SEVERE, "Could not connect to the app!"); } // Stop the app... ObjectType objType = AppsLauncherHelper.STOPAPP_OBJECT_TYPE; Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.INFO, - "Sending event to app: {0} (Name: ''{1}'')", new Object[]{appInstId, appDirectoryServiceName}); + "Sending event to app: {0} (Name: ''{1}'')", + new Object[]{appInstId, appDirectoryServiceName}); this.setRunning(appInstId, false, interaction.getInteraction()); - ObjectId eventSource = super.getCOMServices().getActivityTrackingService().storeCOMOperationActivity(interaction - .getInteraction(), null); + ObjectId eventSource = super.getCOMServices().getActivityTrackingService() + .storeCOMOperationActivity(interaction.getInteraction(), null); // Generate, store and publish the events to stop the App... - final Long objId = super.getCOMServices().getEventService().generateAndStoreEvent(objType, - ConfigurationProviderSingleton.getDomain(), appDirectoryServiceName, appInstId, eventSource, interaction - .getInteraction()); + final Long objId = super.getCOMServices().getEventService() + .generateAndStoreEvent(objType, ConfigurationProviderSingleton.getDomain(), + appDirectoryServiceName, appInstId, eventSource, interaction.getInteraction()); final URI uri = interaction.getInteraction().getMessageHeader().getURIFrom(); @@ -668,8 +616,8 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer try { IdentifierList eventBodies = new IdentifierList(1); eventBodies.add(appDirectoryServiceName); - super.getCOMServices().getEventService().publishEvent(uri, objId, objType, appInstId, eventSource, - eventBodies); + super.getCOMServices().getEventService().publishEvent(uri, + objId, objType, appInstId, eventSource, eventBodies); } catch (IOException ex) { LOGGER.log(Level.SEVERE, null, ex); } @@ -685,8 +633,8 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer } /** - * Stops multiple apps. - * Blocks until all applications exit or waiting for them times out. + * Stops multiple apps. Blocks until all applications exit or waiting for + * them times out. * * @param appInstIds Applications IDs * @param appDirectoryServiceNames Directory service app name @@ -696,8 +644,8 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer * @throws MALInteractionException */ protected void stopApps(final LongList appInstIds, final IdentifierList appDirectoryServiceNames, - final ArrayList appConnections, final StopAppInteraction interaction) - throws MALException, MALInteractionException { + final ArrayList appConnections, + final StopAppInteraction interaction) throws MALException, MALInteractionException { for (int i = 0; i < appInstIds.size(); i++) { long appInstId = appInstIds.get(i); AppDetails curr = this.get(appInstId); @@ -705,35 +653,45 @@ protected void stopApps(final LongList appInstIds, final IdentifierList appDirec if (osValidator.isWindows()) { fileExt = ".bat"; } - File stopScript = new File(appsFolderPath + File.separator + curr.getName().getValue() + File.separator + - "stop_" + curr.getName().getValue() + fileExt); + File stopScript = new File(appsFolderPath + File.separator + curr.getName().getValue() + + File.separator + "stop_" + curr.getName().getValue() + fileExt); boolean stopExists = stopScript.exists(); if (curr.getCategory().getValue().equalsIgnoreCase("NMF_App")) { if (appDirectoryServiceNames.get(i) == null) { LOGGER.log(Level.WARNING, "appDirectoryServiceName null for ''{0}'' app, falling back to kill", - new Object[]{curr.getName().getValue()}); + new Object[]{curr.getName().getValue()}); this.killAppProcess(appInstId, interaction.getInteraction()); } else if (appConnections.get(i) == null) { - LOGGER.log(Level.WARNING, "appConnection null for ''{0}'' app, falling back to kill", new Object[]{ - curr.getName() - .getValue()}); + LOGGER.log(Level.WARNING, "appConnection null for ''{0}'' app, falling back to kill", + new Object[]{curr.getName().getValue()}); this.killAppProcess(appInstId, interaction.getInteraction()); } else { this.stopNMFApp(appInstId, appDirectoryServiceNames.get(i), appConnections.get(i), interaction); } if (stopExists) { - LOGGER.log(Level.INFO, "Stopping native component of ''{0}'' app", new Object[]{curr.getName() - .getValue()}); + Map env = assembleAppLauncherEnvironment(""); + final File appFolder + = new File(appsFolderPath + File.separator + curr.getName().getValue()); + final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), + curr.getName().getValue(), curr.getRunAs(), EnvironmentUtils.toStrings(env)); + final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); + pb.environment().clear(); + pb.directory(appFolder); + + LOGGER.log(Level.INFO, + "Stopping native component of ''{0}'' app", + new Object[]{curr.getName().getValue()}); try { this.stopNativeApp(appInstId, interaction, true); } catch (IOException ex) { Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.SEVERE, - "Stopping native component failed", ex); + "Stopping native component failed", ex); } } } else { if (!stopExists) { - LOGGER.log(Level.INFO, "No stop script present for app {0}. Killing the process.", curr.getName()); + LOGGER.log(Level.INFO, "No stop script present for app {0}. Killing the process.", + curr.getName()); this.killAppProcess(appInstId, interaction.getInteraction()); } else { try { @@ -741,7 +699,7 @@ protected void stopApps(final LongList appInstIds, final IdentifierList appDirec this.stopNativeApp(appInstId, interaction, false); } catch (IOException ex) { Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.SEVERE, - "Stopping native app failed", ex); + "Stopping native app failed", ex); } } } @@ -754,21 +712,23 @@ public void setRunning(Long appInstId, boolean running, MALInteraction interacti } public static SingleConnectionDetails getSingleConnectionDetailsFromProviderSummaryList( - ProviderSummaryList providersList) throws IOException { + ProviderSummaryList providersList) throws IOException { if (providersList.isEmpty()) { // Throw error! - LOGGER.log(Level.WARNING, "The service could not be found in the Directory service... Possible reasons:\n" + - "1. Wrong area number.\n" + - "2. User is trying to control a non-NMF app! If so, one needs to use killApp operation!\n"); + LOGGER.log(Level.WARNING, + "The service could not be found in the Directory service... Possible reasons:\n" + + "1. Wrong area number.\n" + + "2. User is trying to control a non-NMF app! If so, one needs to use killApp operation!\n"); throw new IOException(); } if (providersList.size() != 1) { // Throw error! - throw new IOException("There are more than 1 provider registered for this app! " + - "Most likely the app was forcefully killed before."); + throw new IOException("There are more than 1 provider registered for this app! " + + "Most likely the app was forcefully killed before."); } // Get the service address details lists - ServiceCapabilityList capabilities = providersList.get(0).getProviderDetails().getServiceCapabilities(); + ServiceCapabilityList capabilities = providersList.get(0).getProviderDetails(). + getServiceCapabilities(); // How many addresses do we have? if (capabilities.isEmpty()) { // Throw an error @@ -789,11 +749,14 @@ public static SingleConnectionDetails getSingleConnectionDetailsFromProviderSumm return connectionDetails; } - private static boolean isJustRunningStatusChange(final AppDetails previousAppDetails, final AppDetails single_app) { - if (!previousAppDetails.getCategory().equals(single_app.getCategory()) || !previousAppDetails.getDescription() - .equals(single_app.getDescription()) || !previousAppDetails.getName().equals(single_app.getName()) || - previousAppDetails.getRunAtStartup().booleanValue() != single_app.getRunAtStartup().booleanValue() || - !previousAppDetails.getVersion().equals(single_app.getVersion())) { + private static boolean isJustRunningStatusChange(final AppDetails previousAppDetails, + final AppDetails single_app) { + if (!previousAppDetails.getCategory().equals(single_app.getCategory()) + || !previousAppDetails.getDescription().equals(single_app.getDescription()) + || !previousAppDetails.getName().equals(single_app.getName()) + || previousAppDetails.getRunAtStartup().booleanValue() != single_app.getRunAtStartup(). + booleanValue() + || !previousAppDetails.getVersion().equals(single_app.getVersion())) { return false; } @@ -816,16 +779,17 @@ private AppDetails readAppDescriptor(final String appName, final File properties props.load(inputStream); app.setExtraInfo(HelperMisc.PROVIDER_PROPERTIES_FILE); - final String category = (props.getProperty(HelperMisc.APP_CATEGORY) != null) ? props.getProperty( - HelperMisc.APP_CATEGORY) : "-"; - final String version = (props.getProperty(HelperMisc.APP_VERSION) != null) ? props.getProperty( - HelperMisc.APP_VERSION) : "-"; - final String copyright = (props.getProperty(HelperMisc.APP_COPYRIGHT) != null) ? props.getProperty( - HelperMisc.APP_COPYRIGHT) : "-"; - final String description = (props.getProperty(HelperMisc.APP_DESCRIPTION) != null) ? props.getProperty( - HelperMisc.APP_DESCRIPTION) : "-"; - final String user = (props.getProperty(HelperMisc.APP_USER) != null) ? props.getProperty( - HelperMisc.APP_USER) : null; // Since the user change is only implemented on linux this dependency is fine + final String category = (props.getProperty(HelperMisc.APP_CATEGORY) != null) ? + props.getProperty(HelperMisc.APP_CATEGORY) : "-"; + final String version = (props.getProperty(HelperMisc.APP_VERSION) != null) ? + props.getProperty(HelperMisc.APP_VERSION) : "-"; + final String copyright = (props.getProperty(HelperMisc.APP_COPYRIGHT) != null) ? + props.getProperty(HelperMisc.APP_COPYRIGHT) : "-"; + final String description = (props.getProperty(HelperMisc.APP_DESCRIPTION) != null) ? + props.getProperty(HelperMisc.APP_DESCRIPTION) : "-"; + final String user = (props.getProperty(HelperMisc.APP_USER) != null) ? + props.getProperty(HelperMisc.APP_USER) + : null; // Since the user change is only implemented on linux this dependency is fine app.setCategory(new Identifier(category)); app.setVersion(version); diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index 278bc060d..f343c9454 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -74,117 +74,69 @@ */ public class AppsLauncherProviderServiceImpl extends AppsLauncherInheritanceSkeleton implements ReconfigurableService { - public final static String PROVIDER_PREFIX_NAME = "App: "; - private static final Logger LOGGER = Logger.getLogger( - AppsLauncherProviderServiceImpl.class.getName()); - // Maximum length of a stderr/stdout chunk to be persisted - allows downlinking it via SPP without issues - private static final int MAX_SEGMENT_SIZE = UShort.MAX_VALUE - 256; - private MALProvider appsLauncherServiceProvider; - private MonitorExecutionPublisher publisher; - private boolean initialiased = false; - private boolean running = false; - private boolean isRegistered = false; - private final Object lock = new Object(); - private AppsLauncherManager manager; - private final ConnectionProvider connection = new ConnectionProvider(); - private COMServicesProvider comServices; - private DirectoryProviderServiceImpl directoryService; - private ConfigurationChangeListener configurationAdapter; - private int stdLimit; // Limit of stdout/stderr to allow in the archive. - // Set of app ids for which the warning about verbose logging was sent - private final Set verboseLoggingWarningSent = new HashSet<>(); - /** - * Object used to track archive usage by STD output of each app - */ - private Quota stdQuota = new Quota(); - - /** - * Initializes the Event service provider - * - * @param comServices - * @param directoryService - * @throws MALException On initialization error. - */ - public synchronized void init(final COMServicesProvider comServices, - final DirectoryProviderServiceImpl directoryService) throws MALException { - if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { - COMHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { - SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) - .getServiceByName(AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { - AppsLauncherHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - } - int kbyte = Integer.parseInt(System.getProperty(Const.APPSLAUNCHER_STD_LIMIT_PROPERTY, - Const.APPSLAUNCHER_STD_LIMIT_DEFAULT)); - stdLimit = kbyte * 1024; // init limit with value of property - publisher = createMonitorExecutionPublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), - SessionType.LIVE, - ConfigurationProviderSingleton.getSourceSessionName(), - QoSLevel.BESTEFFORT, - null, - new UInteger(0)); - - // Shut down old service transport - if (null != appsLauncherServiceProvider) { - connection.closeAll(); - } + public final static String PROVIDER_PREFIX_NAME = "App: "; + private static final Logger LOGGER = Logger.getLogger( + AppsLauncherProviderServiceImpl.class.getName()); + // Maximum length of a stderr/stdout chunk to be persisted - allows downlinking it via SPP without issues + private static final int MAX_SEGMENT_SIZE = UShort.MAX_VALUE - 256; + private MALProvider appsLauncherServiceProvider; + private MonitorExecutionPublisher publisher; + private boolean initialiased = false; + private boolean running = false; + private boolean isRegistered = false; + private final Object lock = new Object(); + private AppsLauncherManager manager; + private final ConnectionProvider connection = new ConnectionProvider(); + private COMServicesProvider comServices; + private DirectoryProviderServiceImpl directoryService; + private ConfigurationChangeListener configurationAdapter; + private int stdLimit; // Limit of stdout/stderr to allow in the archive. + // Set of app ids for which the warning about verbose logging was sent + private final Set verboseLoggingWarningSent = new HashSet<>(); + /** + * Object used to track archive usage by STD output of each app + */ + private Quota stdQuota = new Quota(); + + /** + * Initializes the Event service provider + * + * @param comServices + * @param directoryService + * @throws MALException On initialization error. + */ + public synchronized void init(final COMServicesProvider comServices, + final DirectoryProviderServiceImpl directoryService) throws MALException { + if (!initialiased) { + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - this.comServices = comServices; - this.directoryService = directoryService; - manager = new AppsLauncherManager(comServices); - appsLauncherServiceProvider = connection.startService( - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME.toString(), - AppsLauncherHelper.APPSLAUNCHER_SERVICE, this); - running = true; - initialiased = true; - - LOGGER.log(Level.INFO, "Apps Launcher service READY"); - } - - public ConnectionProvider getConnectionProvider() { - return this.connection; - } - - /** - * Set the common quota object used by ArchiveSync service and AppsLauncherService. The quota gets - * freed by ArchiveSync after synchronizing STDOUT/STDERR entries. - * - * @param q The same Quota object passed to ArchiveSyncProviderServiceImpl. - */ - public void setStdQuotaPerApp(Quota q) { - this.stdQuota = q; - } - - private void publishExecutionMonitoring(final Long appObjId, final String outputText, - ObjectType objType) { - try { - synchronized (lock) { - if (!isRegistered) { - final EntityKeyList lst = new EntityKeyList(); - lst.add(new EntityKey(new Identifier("*"), 0L, 0L, 0L)); - publisher.register(lst, new PublishInteractionListener()); - isRegistered = true; + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { + AppsLauncherHelper.init(MALContextFactory.getElementFactoryRegistry()); + } } int kbyte = Integer.parseInt(System.getProperty(Const.APPSLAUNCHER_STD_LIMIT_PROPERTY, - Const.APPSLAUNCHER_STD_LIMIT_DEFAULT)); + Const.APPSLAUNCHER_STD_LIMIT_DEFAULT)); stdLimit = kbyte * 1024; // init limit with value of property publisher = createMonitorExecutionPublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton - .getSourceSessionName(), QoSLevel.BESTEFFORT, null, new UInteger(0)); + ConfigurationProviderSingleton.getNetwork(), + SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), + QoSLevel.BESTEFFORT, + null, + new UInteger(0)); // Shut down old service transport if (null != appsLauncherServiceProvider) { @@ -194,12 +146,13 @@ private void publishExecutionMonitoring(final Long appObjId, final String output this.comServices = comServices; this.directoryService = directoryService; manager = new AppsLauncherManager(comServices); - appsLauncherServiceProvider = connection.startService(AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME.toString(), - AppsLauncherHelper.APPSLAUNCHER_SERVICE, this); + appsLauncherServiceProvider = connection.startService( + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME.toString(), + AppsLauncherHelper.APPSLAUNCHER_SERVICE, this); running = true; initialiased = true; - LOGGER.log(Level.INFO, "Apps Launcher service: READY"); + LOGGER.log(Level.INFO, "Apps Launcher service READY"); } public ConnectionProvider getConnectionProvider() { @@ -207,8 +160,9 @@ public ConnectionProvider getConnectionProvider() { } /** - * Set the common quota object used by ArchiveSync service and AppsLauncherService. The quota gets - * freed by ArchiveSync after synchronizing STDOUT/STDERR entries. + * Set the common quota object used by ArchiveSync service and + * AppsLauncherService. The quota gets freed by ArchiveSync after + * synchronizing STDOUT/STDERR entries. * * @param q The same Quota object passed to ArchiveSyncProviderServiceImpl. */ @@ -216,7 +170,8 @@ public void setStdQuotaPerApp(Quota q) { this.stdQuota = q; } - private void publishExecutionMonitoring(final Long appObjId, final String outputText, ObjectType objType) { + private void publishExecutionMonitoring(final Long appObjId, final String outputText, + ObjectType objType) { try { synchronized (lock) { if (!isRegistered) { @@ -227,24 +182,22 @@ private void publishExecutionMonitoring(final Long appObjId, final String output } } - LOGGER.log(Level.FINER, "Generating update for the App: {0} (Identifier: {1})", new Object[]{appObjId, - new Identifier( - manager - .get( - appObjId) - .getName() - .toString())}); + LOGGER.log(Level.FINER, + "Generating update for the App: {0} (Identifier: {1})", + new Object[]{ + appObjId, new Identifier(manager.get(appObjId).getName().toString()) + }); final StringList outputList = new StringList(); // Should not be store in the Archive... it's too much stuff - final EntityKey ekey = new EntityKey(new Identifier(manager.get(appObjId).getName().toString()), appObjId, - null, null); + final EntityKey ekey = new EntityKey( + new Identifier(manager.get(appObjId).getName().toString()), appObjId, null, null); final Time timestamp = HelperTime.getTimestampMillis(); final UpdateHeaderList hdrlst = new UpdateHeaderList(); hdrlst.add(new UpdateHeader(timestamp, connection.getConnectionDetails().getProviderURI(), - UpdateType.UPDATE, ekey)); + UpdateType.UPDATE, ekey)); EventProviderServiceImpl eventService = this.comServices.getEventService(); int length = outputText.length(); @@ -253,7 +206,7 @@ private void publishExecutionMonitoring(final Long appObjId, final String output String segment = outputText.substring(i, end); outputList.add(segment); if (Boolean.parseBoolean(System.getProperty(Const.APPSLAUNCHER_STD_STORE_PROPERTY, - Const.APPSLAUNCHER_STD_STORE_DEFAULT))) { + Const.APPSLAUNCHER_STD_STORE_DEFAULT))) { // Store in COM archive if the option is enabled and below limit int currentStd = stdQuota.retrieve(appObjId); if (currentStd + segment.length() <= stdLimit) { @@ -261,16 +214,21 @@ private void publishExecutionMonitoring(final Long appObjId, final String output stdQuota.increase(appObjId, segment.length()); IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); ObjectId source = new ObjectId(AppsLauncherHelper.APP_OBJECT_TYPE, new ObjectKey(domain, - appObjId)); - eventService.generateAndStoreEvent(objType, domain, eventBody, appObjId, source, null); + appObjId)); + eventService.generateAndStoreEvent( + objType, + domain, eventBody, appObjId, source, null); } else if (!verboseLoggingWarningSent.contains(appObjId)) { - String errorString = "Your logging is too verbose and reached the limit.\nPlease reduce verbosity."; + String errorString + = "Your logging is too verbose and reached the limit.\nPlease reduce verbosity."; Element eventBody = new Union(errorString); outputList.add(errorString); IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); ObjectId source = new ObjectId(AppsLauncherHelper.APP_OBJECT_TYPE, new ObjectKey(domain, - appObjId)); - eventService.generateAndStoreEvent(objType, domain, eventBody, appObjId, source, null); + appObjId)); + eventService.generateAndStoreEvent( + objType, + domain, eventBody, appObjId, source, null); verboseLoggingWarningSent.add(appObjId); } } @@ -278,12 +236,14 @@ private void publishExecutionMonitoring(final Long appObjId, final String output publisher.publish(hdrlst, outputList); } catch (IllegalArgumentException | MALException | MALInteractionException ex) { - LOGGER.log(Level.WARNING, "Exception during publishing process on the provider {0}", ex); + LOGGER.log(Level.WARNING, + "Exception during publishing process on the provider {0}", ex); } } @Override - public void runApp(LongList appInstIds, MALInteraction interaction) throws MALInteractionException, MALException { + public void runApp(LongList appInstIds, MALInteraction interaction) + throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); @@ -293,8 +253,8 @@ public void runApp(LongList appInstIds, MALInteraction interaction) throws MALIn LOGGER.log(Level.INFO, "runApp received with arguments: {0}", appInstIds); // Refresh the list of available Apps - boolean anyChanges = this.manager.refreshAvailableAppsList(connection.getPrimaryConnectionDetails() - .getProviderURI()); + boolean anyChanges = this.manager.refreshAvailableAppsList( + connection.getPrimaryConnectionDetails().getProviderURI()); if (anyChanges) { // Update the Configuration available on the COM Archive @@ -304,7 +264,8 @@ public void runApp(LongList appInstIds, MALInteraction interaction) throws MALIn } for (int index = 0; index < appInstIds.size(); index++) { - AppDetails app = this.manager.get(appInstIds.get(index)); // get it from the list of available apps + // Get it from the list of available apps: + AppDetails app = this.manager.get(appInstIds.get(index)); // The app id could not be identified? if (app == null) { @@ -319,14 +280,17 @@ public void runApp(LongList appInstIds, MALInteraction interaction) throws MALIn } } - if (!unkIndexList.isEmpty()) { - throw new MALInteractionException( - new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList) - ); - } + // Errors + if (!invIndexList.isEmpty()) { + throw new MALInteractionException( + new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList) + ); + } if (!unkIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList) + ); } // Run the apps! @@ -335,38 +299,39 @@ public void runApp(LongList appInstIds, MALInteraction interaction) throws MALIn String directoryServiceURI; if (directoryService.getConnection().getSecondaryConnectionDetails() != null) { // For applications in space, the primary URI is MALSPP, and secondary a MALTCP - directoryServiceURI = directoryService.getConnection().getSecondaryConnectionDetails() - .getProviderURI().toString(); + directoryServiceURI + = directoryService.getConnection().getSecondaryConnectionDetails().getProviderURI().toString(); } else { - directoryServiceURI = directoryService.getConnection().getConnectionDetails().getProviderURI() - .toString(); + directoryServiceURI + = directoryService.getConnection().getConnectionDetails().getProviderURI().toString(); } AppDetails app = this.manager.get(appInstIds.get(i)); ObjectType objType = AppsLauncherHelper.STARTAPP_OBJECT_TYPE; ObjectId eventSource = this.manager.getCOMServices().getActivityTrackingService() - .storeCOMOperationActivity(interaction, null); + .storeCOMOperationActivity(interaction, null); Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.INFO, - "Generating StartApp event for app: {0} (Name: ''{1}'')", new Object[]{appInstIds.get(i), app - .getName()}); - this.manager.getCOMServices().getEventService().generateAndStoreEvent(objType, - ConfigurationProviderSingleton.getDomain(), app.getName(), appInstIds.get(i), eventSource, - interaction); + "Generating StartApp event for app: {0} (Name: ''{1}'')", new Object[]{appInstIds.get(i), app.getName()}); + this.manager.getCOMServices().getEventService() + .generateAndStoreEvent(objType, ConfigurationProviderSingleton.getDomain(), app.getName(), + appInstIds.get(i), eventSource, interaction); manager.startAppProcess(new ProcessExecutionHandler(new CallbacksImpl(), appInstIds.get(i)), - interaction, directoryServiceURI); + interaction, directoryServiceURI); } catch (IOException ex) { UIntegerList intIndexList = new UIntegerList(); intIndexList.add(new UInteger(i)); Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.INFO, - "Not able to start the application process...", ex); - throw new MALInteractionException(new MALStandardError(MALHelper.INTERNAL_ERROR_NUMBER, intIndexList)); + "Not able to start the application process...", ex); + throw new MALInteractionException(new MALStandardError(MALHelper.INTERNAL_ERROR_NUMBER, + intIndexList)); } } } @Override - public void killApp(LongList appInstIds, MALInteraction interaction) throws MALInteractionException, MALException { + public void killApp(LongList appInstIds, MALInteraction interaction) + throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); @@ -376,8 +341,8 @@ public void killApp(LongList appInstIds, MALInteraction interaction) throws MALI LOGGER.log(Level.INFO, "killApp received with arguments: {0}", appInstIds); // Refresh the list of available Apps - boolean anyChanges = this.manager.refreshAvailableAppsList(connection.getPrimaryConnectionDetails() - .getProviderURI()); + boolean anyChanges = this.manager.refreshAvailableAppsList( + connection.getPrimaryConnectionDetails().getProviderURI()); if (anyChanges) { // Update the Configuration available on the COM Archive @@ -405,11 +370,15 @@ public void killApp(LongList appInstIds, MALInteraction interaction) throws MALI // Errors if (!invIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); + throw new MALInteractionException( + new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList) + ); } if (!unkIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList) + ); } // Kill the apps! @@ -419,8 +388,8 @@ public void killApp(LongList appInstIds, MALInteraction interaction) throws MALI } @Override - public void stopApp(final LongList appInstIds, final StopAppInteraction interaction) throws MALInteractionException, - MALException { + public void stopApp(final LongList appInstIds, final StopAppInteraction interaction) + throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); UIntegerList intIndexList = new UIntegerList(); @@ -431,8 +400,8 @@ public void stopApp(final LongList appInstIds, final StopAppInteraction interact LOGGER.log(Level.INFO, "stopApp received with arguments: {0}", appInstIds); // Refresh the list of available Apps - boolean anyChanges = this.manager.refreshAvailableAppsList(connection.getPrimaryConnectionDetails() - .getProviderURI()); + boolean anyChanges = this.manager.refreshAvailableAppsList( + connection.getPrimaryConnectionDetails().getProviderURI()); if (anyChanges) { // Update the Configuration available on the COM Archive @@ -443,20 +412,23 @@ public void stopApp(final LongList appInstIds, final StopAppInteraction interact IdentifierList appDirectoryServiceNames = new IdentifierList(); - prepareStopApp(appInstIds, interaction, unkIndexList, invIndexList, intIndexList, appConnections, - appDirectoryServiceNames); + prepareStopApp(appInstIds, interaction, unkIndexList, invIndexList, + intIndexList, appConnections, appDirectoryServiceNames); // Errors if (!unkIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); + throw new MALInteractionException(new MALStandardError( + MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); } if (!invIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); + throw new MALInteractionException(new MALStandardError( + COMHelper.INVALID_ERROR_NUMBER, invIndexList)); } if (!intIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.INTERNAL_ERROR_NUMBER, intIndexList)); + throw new MALInteractionException(new MALStandardError( + MALHelper.INTERNAL_ERROR_NUMBER, intIndexList)); } interaction.sendAcknowledgement(); @@ -464,10 +436,9 @@ public void stopApp(final LongList appInstIds, final StopAppInteraction interact interaction.sendResponse(); } - private void prepareStopApp(final LongList appInstIds, final StopAppInteraction interaction, - UIntegerList unkIndexList, UIntegerList invIndexList, UIntegerList intIndexList, - ArrayList appConnections, IdentifierList appDirectoryServiceNames) - throws MALInteractionException, MALException { + private void prepareStopApp(final LongList appInstIds, final StopAppInteraction interaction, UIntegerList unkIndexList, + UIntegerList invIndexList, UIntegerList intIndexList, ArrayList appConnections, + IdentifierList appDirectoryServiceNames) throws MALInteractionException, MALException { for (int i = 0; i < appInstIds.size(); i++) { // Get it from the list of available apps Long appId = appInstIds.get(i); @@ -490,26 +461,26 @@ private void prepareStopApp(final LongList appInstIds, final StopAppInteraction final IdentifierList domain = new IdentifierList(); domain.add(new Identifier("*")); final COMService eventCOM = EventHelper.EVENT_SERVICE; - ServiceKey serviceKey = new ServiceKey(eventCOM.getArea().getNumber(), eventCOM.getNumber(), eventCOM - .getArea().getVersion()); - ServiceFilter sf = new ServiceFilter(serviceProviderName, domain, new Identifier("*"), null, new Identifier( - "*"), serviceKey, new UShortList()); + ServiceKey serviceKey = new ServiceKey(eventCOM.getArea().getNumber(), + eventCOM.getNumber(), eventCOM.getArea().getVersion()); + ServiceFilter sf = new ServiceFilter(serviceProviderName, domain, new Identifier("*"), + null, new Identifier("*"), serviceKey, new UIntegerList()); if (app.getCategory().getValue().equalsIgnoreCase("NMF_App")) { // Do a lookup on the Central Drectory service for the app that we want - ProviderSummaryList providersList = this.directoryService.lookupProvider(sf, interaction - .getInteraction()); + ProviderSummaryList providersList = this.directoryService.lookupProvider(sf, + interaction.getInteraction()); LOGGER.log(Level.FINER, "providersList object: {0}", providersList); try { // Add here the filtering for the best IPC!!! - final SingleConnectionDetails connectionDetails = AppsLauncherManager - .getSingleConnectionDetailsFromProviderSummaryList(providersList); + final SingleConnectionDetails connectionDetails + = AppsLauncherManager.getSingleConnectionDetailsFromProviderSummaryList(providersList); appConnections.add(connectionDetails); // Add to the list of Directory service Obj Ids if (!providersList.isEmpty()) { - appDirectoryServiceNames.add(providersList.get(0).getProviderId()); + appDirectoryServiceNames.add(providersList.get(0).getProviderName()); } else { appDirectoryServiceNames.add(null); } @@ -529,7 +500,7 @@ private void prepareStopApp(final LongList appInstIds, final StopAppInteraction @Override public ListAppResponse listApp(final IdentifierList appNames, final Identifier category, - final MALInteraction interaction) throws MALInteractionException, MALException { + final MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); ListAppResponse outList = new ListAppResponse(); @@ -538,8 +509,8 @@ public ListAppResponse listApp(final IdentifierList appNames, final Identifier c } // Refresh the list of available Apps - boolean anyChanges = manager.refreshAvailableAppsList(connection.getPrimaryConnectionDetails() - .getProviderURI()); + boolean anyChanges = manager.refreshAvailableAppsList( + connection.getPrimaryConnectionDetails().getProviderURI()); if (anyChanges) { // Update the Configuration available on the COM Archive @@ -564,30 +535,101 @@ public ListAppResponse listApp(final IdentifierList appNames, final Identifier c } } - @Override - public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { - LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); + if (!unkIndexList.isEmpty()) { + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList) + ); + } + + for (Long id : ids) { // Is the app running? + runningApps.add(manager.isAppRunning(id)); + } + + outList.setBodyElement0(ids); + outList.setBodyElement1(runningApps); + + return outList; } @Override - public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) - throws MALException { - LOGGER.warning("PublishInteractionListener::publishErrorReceived"); + public void setOnConfigurationChangeListener( + final ConfigurationChangeListener configurationAdapter) { + this.configurationAdapter = configurationAdapter; } @Override - public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { - LOGGER.fine("PublishInteractionListener::publishRegisterAckReceived"); -// Logger.getLogger(AppsLauncherProviderServiceImpl.class.getName()).log(Level.INFO, "Registration Ack: {0}", header.toString()); + public Boolean reloadConfiguration(ConfigurationObjectDetails configurationObjectDetails) { + // Validate the configuration... + if (configurationObjectDetails == null) { + return false; + } + + if (configurationObjectDetails.getConfigObjects() == null) { + return false; + } + + // Is the size 1? + if (configurationObjectDetails.getConfigObjects().size() != 1) { // 1 because we just have Apps as configuration objects in this service + return false; + } + + ConfigurationObjectSet confSet = configurationObjectDetails.getConfigObjects().get(0); + + // Confirm the objType + if (!confSet.getObjType().equals(AppsLauncherHelper.APP_OBJECT_TYPE)) { + return false; + } + + // Confirm the domain + if (!confSet.getDomain().equals(ConfigurationProviderSingleton.getDomain())) { + return false; + } + + // If the list is empty, reconfigure the service with nothing... + if (confSet.getObjInstIds().isEmpty()) { + manager.reconfigureDefinitions(new LongList(), new AppDetailsList()); // Reconfigures the Manager + return true; + } + + // ok, we're good to go... + // Load the App Details from this configuration... + AppDetailsList pDefs = (AppDetailsList) HelperArchive.getObjectBodyListFromArchive( + manager.getArchiveService(), + AppsLauncherHelper.APP_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + confSet.getObjInstIds()); + + if (manager.reconfigureDefinitions(confSet.getObjInstIds(), pDefs)) { + for (Long id : confSet.getObjInstIds()) { // Set all running state to false + manager.setRunning(id, false, null); + } + } else { + LOGGER.log(Level.WARNING, "Failed to reconfigure definitions. Ids: {0} pDefs: {1}", new Object[]{confSet.getObjInstIds(), pDefs}); + } + return true; } @Override - public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { - LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); + public ConfigurationObjectDetails getCurrentConfiguration() { + // Get all the current objIds in the serviceImpl + // Create a Configuration Object with all the objs of the provider + final HashMap defObjs = manager.getCurrentDefinitionsConfiguration(); + + final ConfigurationObjectSet objsSet = new ConfigurationObjectSet(); + objsSet.setDomain(ConfigurationProviderSingleton.getDomain()); + LongList currentObjIds = new LongList(); + currentObjIds.addAll(defObjs.keySet()); + objsSet.setObjInstIds(currentObjIds); + objsSet.setObjType(AppsLauncherHelper.APP_OBJECT_TYPE); + + final ConfigurationObjectSetList list = new ConfigurationObjectSetList(); + list.add(objsSet); + + // Needs the Common API here! + final ConfigurationObjectDetails set = new ConfigurationObjectDetails(); + set.setConfigObjects(list); + + return set; } @Override @@ -599,33 +641,47 @@ public static final class PublishInteractionListener implements MALPublishIntera @Override public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + throws MALException { LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); } @Override public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + final Map qosProperties) + throws MALException { LOGGER.warning("PublishInteractionListener::publishErrorReceived"); } @Override public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + throws MALException { LOGGER.fine("PublishInteractionListener::publishRegisterAckReceived"); - // Logger.getLogger(AppsLauncherProviderServiceImpl.class.getName()).log(Level.INFO, "Registration Ack: {0}", header.toString()); +// Logger.getLogger(AppsLauncherProviderServiceImpl.class.getName()).log(Level.INFO, "Registration Ack: {0}", header.toString()); } @Override public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + final Map qosProperties) throws MALException { LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); } } - @Override - public void processStopped(Long objId, int exitCode) { - manager.setRunning(objId, false, null); + private class CallbacksImpl implements ProcessExecutionHandler.Callbacks { + + @Override + public void flushStdout(Long objId, String data) { + publishExecutionMonitoring(objId, data, CommandExecutorHelper.STANDARDOUTPUT_OBJECT_TYPE); + } + + @Override + public void flushStderr(Long objId, String data) { + publishExecutionMonitoring(objId, data, CommandExecutorHelper.STANDARDERROR_OBJECT_TYPE); + } + + @Override + public void processStopped(Long objId, int exitCode) { + manager.setRunning(objId, false, null); + } } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java index 7f09f29dc..7fbc097f6 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java @@ -66,238 +66,239 @@ */ public class CommandExecutorProviderServiceImpl extends CommandExecutorInheritanceSkeleton { - private static final Logger LOGGER = Logger.getLogger( - CommandExecutorProviderServiceImpl.class.getName()); - private final ConnectionProvider connection = new ConnectionProvider(); - private MALProvider commandExecutorServiceProvider; - private boolean initialiased = false; - private EventProviderServiceImpl eventService; - private ArchiveProviderServiceImpl archiveService; - private final OSValidator osValidator = new OSValidator(); - private final Map cachedCommandDetails = new HashMap<>(); + private static final Logger LOGGER = Logger.getLogger( + CommandExecutorProviderServiceImpl.class.getName()); + private final ConnectionProvider connection = new ConnectionProvider(); + private MALProvider commandExecutorServiceProvider; + private boolean initialiased = false; + private EventProviderServiceImpl eventService; + private ArchiveProviderServiceImpl archiveService; + private final OSValidator osValidator = new OSValidator(); + private final Map cachedCommandDetails = new HashMap<>(); - /** - * Initializes the service provider - * - * @param comServices - * @throws MALException On initialization error. - */ - public synchronized void init(final COMServicesProvider comServices) throws MALException { - if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + /** + * Initializes the service provider + * + * @param comServices + * @throws MALException On initialization error. + */ + public synchronized void init(final COMServicesProvider comServices) throws MALException { + if (!initialiased) { + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { - COMHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { - SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); - } + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); + } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) - .getServiceByName(CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME) == null) { - CommandExecutorHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - } - archiveService = comServices.getArchiveService(); - if (archiveService == null) { - throw new MALException("Cannot access the COM Archive Service."); - } - eventService = comServices.getEventService(); - if (eventService == null) { - throw new MALException("Cannot access the COM Event Service."); - } - // Shut down old service transport - if (null != commandExecutorServiceProvider) { - connection.closeAll(); - } + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME) == null) { + CommandExecutorHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + } + archiveService = comServices.getArchiveService(); + if (archiveService == null) { + throw new MALException("Cannot access the COM Archive Service."); + } + eventService = comServices.getEventService(); + if (eventService == null) { + throw new MALException("Cannot access the COM Event Service."); + } + // Shut down old service transport + if (null != commandExecutorServiceProvider) { + connection.closeAll(); + } - commandExecutorServiceProvider = connection.startService( - CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME.toString(), - CommandExecutorHelper.COMMANDEXECUTOR_SERVICE, this); - initialiased = true; + commandExecutorServiceProvider = connection.startService( + CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME.toString(), + CommandExecutorHelper.COMMANDEXECUTOR_SERVICE, this); + initialiased = true; - LOGGER.log(Level.INFO, "Command Executor service READY"); - } - - protected String[] assembleCommand(final String command) { - ArrayList ret = new ArrayList<>(); - if (osValidator.isWindows()) { - ret.add("cmd"); - ret.add("/c"); - ret.add(command); - } else { - ret.add("/bin/sh"); - ret.add("-c"); - ret.add(command); + LOGGER.log(Level.INFO, "Command Executor service READY"); } - return ret.toArray(new String[0]); - } - @Override - public Long runCommand(CommandDetails command, MALInteraction interaction) - throws MALInteractionException, MALException { - Long storedCommandObject; - if (command == null) { - throw new MALException("Received null CommandDetails."); + protected String[] assembleCommand(final String command) { + ArrayList ret = new ArrayList<>(); + if (osValidator.isWindows()) { + ret.add("cmd"); + ret.add("/c"); + ret.add(command); + } else { + ret.add("/bin/sh"); + ret.add("-c"); + ret.add(command); + } + return ret.toArray(new String[0]); } - // Source could be mapped to an OperationActivity associated with this transaction, but for now - // we don't need such fine tracking... - final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList( - null, null, connection.getPrimaryConnectionDetails().getProviderURI()); - final CommandDetailsList objBodies = new CommandDetailsList(1); - objBodies.add(command); - LongList objIds = archiveService.store( - true, - CommandExecutorHelper.COMMAND_OBJECT_TYPE, - connection.getPrimaryConnectionDetails().getDomain(), - archDetails, - objBodies, - null); + @Override + public Long runCommand(CommandDetails command, MALInteraction interaction) + throws MALInteractionException, MALException { + Long storedCommandObject; + if (command == null) { + throw new MALException("Received null CommandDetails."); + } - if (objIds.size() == 1) { - storedCommandObject = objIds.get(0); - } else { - throw new MALException("Unexpected return from the archive store."); - } + // Source could be mapped to an OperationActivity associated with this transaction, but for now + // we don't need such fine tracking... + final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList( + null, null, connection.getPrimaryConnectionDetails().getProviderURI()); + final CommandDetailsList objBodies = new CommandDetailsList(1); + objBodies.add(command); + LongList objIds = archiveService.store( + true, + CommandExecutorHelper.COMMAND_OBJECT_TYPE, + connection.getPrimaryConnectionDetails().getDomain(), + archDetails, + objBodies, + null); - String[] shellCommand = assembleCommand(command.getCommand()); - final ProcessBuilder pb = new ProcessBuilder(shellCommand); - Map env = pb.environment(); - // Reuse the environment - // env.clear(); - File workingDir = pb.directory(); - if (workingDir == null) { - workingDir = Paths.get("").toFile(); - } - LOGGER.log(Level.INFO, "Running ''{0}'' in dir: {1}, and env: {2}", new Object[]{ - Arrays.toString(shellCommand), workingDir.getAbsolutePath(), - Arrays.toString(EnvironmentUtils.toStrings(env))}); - final Process proc; - try { - proc = pb.start(); - ProcessExecutionHandler handler = new ProcessExecutionHandler(new CallbacksImpl(), - storedCommandObject); - handler.monitorProcess(proc); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - throw new MALException("Cannot start the process!", ex); - } - long pid; - try { - pid = ProcessExecutionHandler.getProcessPid(proc); - } catch (IOException ex) { - pid = -1; - } - command.setPid(pid); - updateCommandDetails(storedCommandObject, command); - return storedCommandObject; - } + if (objIds.size() == 1) { + storedCommandObject = objIds.get(0); + } else { + throw new MALException("Unexpected return from the archive store."); + } - private void commandOutputEvent(final Long objId, final String outputText, - final ObjectType objType) { - IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); - URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); - ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, - objId)); - Element eventBody = new Union(outputText); - StringList eventBodyList = new StringList(1); - eventBodyList.add(outputText); - final Long eventObjId = eventService.generateAndStoreEvent(objType, domain, eventBody, null, - source, connection.getPrimaryConnectionDetails().getProviderURI(), null); - if (eventObjId != null) { - try { - eventService.publishEvent(sourceURI, eventObjId, objType, null, source, eventBodyList); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Could not publish command output event", ex); - } - } else { - LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); + String[] shellCommand = assembleCommand(command.getCommand()); + final ProcessBuilder pb = new ProcessBuilder(shellCommand); + Map env = pb.environment(); + // Reuse the environment + // env.clear(); + File workingDir = pb.directory(); + if (workingDir == null) { + workingDir = Paths.get("").toFile(); + } + LOGGER.log(Level.INFO, "Running ''{0}'' in dir: {1}, and env: {2}", new Object[]{ + Arrays.toString(shellCommand), workingDir.getAbsolutePath(), + Arrays.toString(EnvironmentUtils.toStrings(env))}); + final Process proc; + try { + proc = pb.start(); + ProcessExecutionHandler handler = new ProcessExecutionHandler(new CallbacksImpl(), + storedCommandObject); + handler.monitorProcess(proc); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + throw new MALException("Cannot start the process!", ex); + } + long pid; + try { + pid = ProcessExecutionHandler.getProcessPid(proc); + } catch (IOException ex) { + pid = -1; + } + command.setPid(pid); + updateCommandDetails(storedCommandObject, command); + return storedCommandObject; } - } - private void commandExitEvent(final Long objId, final int exitCode) { - IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); - URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); - ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, - objId)); - Element eventBody = new Union(exitCode); - IntegerList eventBodyList = new IntegerList(1); - eventBodyList.add(exitCode); - final Long eventObjId = eventService.generateAndStoreEvent( - CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, domain, eventBody, null, - source, connection.getPrimaryConnectionDetails().getProviderURI(), null); - if (eventObjId != null) { - try { - eventService.publishEvent(sourceURI, eventObjId, - CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, null, source, eventBodyList); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Could not publish command exit event", ex); - } - } else { - LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); + private void commandOutputEvent(final Long objId, final String outputText, + final ObjectType objType) { + IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); + URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); + ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, + objId)); + Element eventBody = new Union(outputText); + StringList eventBodyList = new StringList(1); + eventBodyList.add(outputText); + final Long eventObjId = eventService.generateAndStoreEvent(objType, domain, eventBody, null, + source, connection.getPrimaryConnectionDetails().getProviderURI(), null); + if (eventObjId != null) { + try { + eventService.publishEvent(sourceURI, eventObjId, objType, null, source, eventBodyList); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Could not publish command output event", ex); + } + } else { + LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); + } } - try { - CommandDetails command = getCommandDetails(objId); - command.setExitCode(exitCode); - updateCommandDetails(objId, command); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "Cannot update COM Command object", ex); + + private void commandExitEvent(final Long objId, final int exitCode) { + IdentifierList domain = connection.getPrimaryConnectionDetails().getDomain(); + URI sourceURI = connection.getPrimaryConnectionDetails().getProviderURI(); + ObjectId source = new ObjectId(CommandExecutorHelper.COMMAND_OBJECT_TYPE, new ObjectKey(domain, + objId)); + Element eventBody = new Union(exitCode); + IntegerList eventBodyList = new IntegerList(1); + eventBodyList.add(exitCode); + final Long eventObjId = eventService.generateAndStoreEvent( + CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, domain, eventBody, null, + source, connection.getPrimaryConnectionDetails().getProviderURI(), null); + if (eventObjId != null) { + try { + eventService.publishEvent(sourceURI, eventObjId, + CommandExecutorHelper.EXECUTIONFINISHED_OBJECT_TYPE, null, source, eventBodyList); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Could not publish command exit event", ex); + } + } else { + LOGGER.log(Level.SEVERE, "generateAndStoreEvent returned null object ID"); + } + try { + CommandDetails command = getCommandDetails(objId); + command.setExitCode(exitCode); + updateCommandDetails(objId, command); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Cannot update COM Command object", ex); + } } - } - private CommandDetails getCommandDetails(Long objId) throws IOException { - if (cachedCommandDetails.containsKey(objId)) { - return cachedCommandDetails.get(objId); - } else { - Element retrievedObject = HelperArchive.getObjectBodyFromArchive( - archiveService, CommandExecutorHelper.COMMAND_OBJECT_TYPE, - connection.getPrimaryConnectionDetails().getDomain(), objId); - if (retrievedObject == null) { - throw new IOException("Could not retrieve Command object for objId: " + objId); - } - CommandDetails ret = (CommandDetails) retrievedObject; - cachedCommandDetails.put(objId, ret); - return ret; + private CommandDetails getCommandDetails(Long objId) throws IOException { + if (cachedCommandDetails.containsKey(objId)) { + return cachedCommandDetails.get(objId); + } else { + Element retrievedObject = HelperArchive.getObjectBodyFromArchive( + archiveService, CommandExecutorHelper.COMMAND_OBJECT_TYPE, + connection.getPrimaryConnectionDetails().getDomain(), objId); + if (retrievedObject == null) { + throw new IOException("Could not retrieve Command object for objId: " + objId); + } + CommandDetails ret = (CommandDetails) retrievedObject; + cachedCommandDetails.put(objId, ret); + return ret; + } } - } - private void updateCommandDetails(Long objId, CommandDetails command) { - cachedCommandDetails.put(objId, command); - final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(null, null, - ConfigurationProviderSingleton.getNetwork(), - connection.getPrimaryConnectionDetails().getProviderURI(), objId); - final CommandDetailsList objBodies = new CommandDetailsList(1); - objBodies.add(command); - try { - archiveService.update( - CommandExecutorHelper.COMMAND_OBJECT_TYPE, - connection.getPrimaryConnectionDetails().getDomain(), archDetails, objBodies, null); - } catch (MALException | MALInteractionException ex) { - Logger.getLogger(CommandExecutorProviderServiceImpl.class.getName()).log(Level.SEVERE, - "Could not update COM Command object", ex); + private void updateCommandDetails(Long objId, CommandDetails command) { + cachedCommandDetails.put(objId, command); + final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(null, null, + ConfigurationProviderSingleton.getNetwork(), + connection.getPrimaryConnectionDetails().getProviderURI(), objId); + final CommandDetailsList objBodies = new CommandDetailsList(1); + objBodies.add(command); + try { + archiveService.update( + CommandExecutorHelper.COMMAND_OBJECT_TYPE, + connection.getPrimaryConnectionDetails().getDomain(), archDetails, objBodies, null); + } catch (MALException | MALInteractionException ex) { + Logger.getLogger(CommandExecutorProviderServiceImpl.class.getName()).log(Level.SEVERE, + "Could not update COM Command object", ex); + } } - } - private class CallbacksImpl implements ProcessExecutionHandler.Callbacks { + private class CallbacksImpl implements ProcessExecutionHandler.Callbacks { - @Override - public void flushStdout(Long objId, String data) { - commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDOUTPUT_OBJECT_TYPE); - } + @Override + public void flushStdout(Long objId, String data) { + commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDOUTPUT_OBJECT_TYPE); + } - @Override - public void flushStderr(Long objId, String data) { - commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDERROR_OBJECT_TYPE); - } + @Override + public void flushStderr(Long objId, String data) { + commandOutputEvent(objId, data, CommandExecutorHelper.STANDARDERROR_OBJECT_TYPE); + } - @Override - public void processStopped(Long objId, int exitCode) { - commandExitEvent(objId, exitCode); + @Override + public void processStopped(Long objId, int exitCode) { + commandExitEvent(objId, exitCode); + } } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java index 9511a9081..c7d4fb425 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java @@ -57,7 +57,8 @@ */ public class HeartbeatProviderServiceImpl extends HeartbeatInheritanceSkeleton { - private static final Logger LOGGER = Logger.getLogger(HeartbeatProviderServiceImpl.class.getName()); + private static final Logger LOGGER + = Logger.getLogger(HeartbeatProviderServiceImpl.class.getName()); private MALProvider heartbeatServiceProvider; private BeatPublisher publisher; private boolean initialiased = false; @@ -69,7 +70,8 @@ public class HeartbeatProviderServiceImpl extends HeartbeatInheritanceSkeleton { protected long period = 10000; // 10 seconds /** - * Creates the MAL objects, the publisher used to create updates and starts the publishing thread + * Creates the MAL objects, the publisher used to create updates and starts + * the publishing thread * * @throws MALException On initialisation error. */ @@ -80,28 +82,33 @@ public synchronized void init() throws MALException { } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - HeartbeatHelper.HEARTBEAT_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(HeartbeatHelper.HEARTBEAT_SERVICE_NAME) == null) { HeartbeatHelper.init(MALContextFactory.getElementFactoryRegistry()); } } - publisher = createBeatPublisher(ConfigurationProviderSingleton.getDomain(), ConfigurationProviderSingleton - .getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton.getSourceSessionName(), QoSLevel.BESTEFFORT, - null, new UInteger(0)); + publisher = createBeatPublisher(ConfigurationProviderSingleton.getDomain(), + ConfigurationProviderSingleton.getNetwork(), + SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), + QoSLevel.BESTEFFORT, + null, + new UInteger(0)); // Shut down old service transport if (null != heartbeatServiceProvider) { connection.closeAll(); } - heartbeatServiceProvider = connection.startService(HeartbeatHelper.HEARTBEAT_SERVICE_NAME.toString(), - HeartbeatHelper.HEARTBEAT_SERVICE, true, this); + heartbeatServiceProvider = connection.startService( + HeartbeatHelper.HEARTBEAT_SERVICE_NAME.toString(), + HeartbeatHelper.HEARTBEAT_SERVICE, true, this); running = true; initialiased = true; @@ -131,7 +138,8 @@ public void close() { connection.closeAll(); running = false; } catch (MALException ex) { - LOGGER.log(Level.WARNING, "Exception during close down of the provider {0}", ex); + LOGGER.log(Level.WARNING, + "Exception during close down of the provider {0}", ex); } } @@ -147,8 +155,14 @@ private void publishHeartbeat() { } final UpdateHeaderList hdrlst = new UpdateHeaderList(1); - hdrlst.add(new UpdateHeader(HelperTime.getTimestampMillis(), connection.getConnectionDetails() - .getProviderURI(), UpdateType.UPDATE, new EntityKey(null, null, null, null))); + hdrlst.add( + new UpdateHeader( + HelperTime.getTimestampMillis(), + connection.getConnectionDetails().getProviderURI(), + UpdateType.UPDATE, + new EntityKey(null, null, null, null) + ) + ); publisher.publish(hdrlst); } catch (IllegalArgumentException | MALException | MALInteractionException ex) { @@ -159,32 +173,32 @@ private void publishHeartbeat() { @Override public Duration getPeriod(MALInteraction interaction) throws MALInteractionException, MALException { // Convert to seconds and return the value - return new Duration(period / 1000.0); + return new Duration(period / 1000); } public static final class PublishInteractionListener implements MALPublishInteractionListener { @Override - public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + public void publishDeregisterAckReceived(final MALMessageHeader header, + final Map qosProperties) throws MALException { LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); } @Override - public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + public void publishErrorReceived(final MALMessageHeader header, + final MALErrorBody body, final Map qosProperties) throws MALException { LOGGER.warning("PublishInteractionListener::publishErrorReceived"); } @Override - public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { + public void publishRegisterAckReceived(final MALMessageHeader header, + final Map qosProperties) throws MALException { LOGGER.log(Level.INFO, "Registration Ack: {0}", header.toString()); } @Override - public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { + public void publishRegisterErrorReceived(final MALMessageHeader header, + final MALErrorBody body, final Map qosProperties) throws MALException { LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java index 56b0cd774..397e2937c 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java @@ -84,13 +84,13 @@ public synchronized void init(final COMServicesProvider comServices, final PMBac } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE_NAME) == null) { PackageManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -275,8 +275,8 @@ public void uninstall(final IdentifierList names, final BooleanList keepConfigur if (!backend.isPackageInstalled(names.get(i).getValue())) { invIndexList.add(new UInteger(i)); - Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).log(Level.SEVERE, - "The package is not installed!"); + Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).log( + Level.SEVERE, "The package is not installed!"); continue; } @@ -286,8 +286,8 @@ public void uninstall(final IdentifierList names, final BooleanList keepConfigur if (!integrity) { invIndexList.add(new UInteger(i)); - Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).log(Level.SEVERE, - "The integrity of the package is bad!"); + Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).log( + Level.SEVERE, "The integrity of the package is bad!"); } } } catch (IOException ex) { diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/ProcessExecutionHandler.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/ProcessExecutionHandler.java index d8b3a1273..d0060829c 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/ProcessExecutionHandler.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/ProcessExecutionHandler.java @@ -38,7 +38,7 @@ public interface Callbacks { * Called to transmit chunk of stdout data. * * @param objId Associated object ID (meaningful in the callee context) - * @param data Chunk of stdout data. + * @param data Chunk of stdout data. */ void flushStdout(Long objId, String data); @@ -46,14 +46,14 @@ public interface Callbacks { * Called to transmit chunk of stderr data. * * @param objId Associated object ID (meaningful in the callee context) - * @param data Chunk of stderr data. + * @param data Chunk of stderr data. */ void flushStderr(Long objId, String data); /** * Called when application exits. * - * @param objId Associated object ID (meaningful in the callee context) + * @param objId Associated object ID (meaningful in the callee context) * @param exitCode Application exit code */ void processStopped(Long objId, int exitCode); @@ -115,7 +115,8 @@ public static synchronized long getProcessPid(Process p) throws IOException { } else { throw new IOException("Trying to resolve PID on an unsupported platform"); } - } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException ex) { + } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException + | SecurityException ex) { throw new IOException("Exception when trying to resolve PID", ex); } return pid; @@ -134,10 +135,10 @@ public void monitorProcess(final Process process) { } catch (IOException ex) { pid = -1; } - stdoutReader = createReaderThread(stdoutBuf, new BufferedReader(new InputStreamReader(process - .getInputStream())), "STDOUT_" + pid); - stderrReader = createReaderThread(stderrBuf, new BufferedReader(new InputStreamReader(process - .getErrorStream())), "STDERR_" + pid); + stdoutReader = createReaderThread(stdoutBuf, new BufferedReader( + new InputStreamReader(process.getInputStream())), "STDOUT_" + pid); + stderrReader = createReaderThread(stderrBuf, new BufferedReader( + new InputStreamReader(process.getErrorStream())), "STDERR_" + pid); stdoutReader.start(); stderrReader.start(); new Thread(() -> { @@ -167,8 +168,9 @@ public void run() { buf.append("\n"); } } catch (IOException ex) { - LOGGER.log(Level.INFO, "The stream of the process (objId: {0}) has been closed.", new Object[]{ - objId}); + LOGGER.log(Level.INFO, + "The stream of the process (objId: {0}) has been closed.", + new Object[]{objId}); close(); } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java index 85fd177c2..89bd78629 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java @@ -86,8 +86,9 @@ public boolean isAppClosed() { public void waitForAppClosing(long timeout) throws InterruptedException { synchronized (semaphore) { - if (!appClosed) + if (!appClosed) { semaphore.wait(timeout); + } } } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/PMBackend.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/PMBackend.java index 9ff0745c6..33715b7f2 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/PMBackend.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/PMBackend.java @@ -24,8 +24,8 @@ import org.ccsds.moims.mo.mal.structures.StringList; /** - * An interface to be implemented in order to allow the Package Management service - * to manage packages. + * An interface to be implemented in order to allow the Package Management + * service to manage packages. * * @author Cesar Coelho */ diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesConsumer.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesConsumer.java index 1e0c8b8a2..9e0ecb69e 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesConsumer.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesConsumer.java @@ -39,8 +39,8 @@ import org.ccsds.moims.mo.softwaremanagement.packagemanagement.PackageManagementHelper; /** - * Class holding all the COM services consumers. The services can all be initialized automatically - * or can be set manually. + * Class holding all the COM services consumers. The services can all be + * initialized automatically or can be set manually. */ public class SMServicesConsumer { @@ -50,55 +50,58 @@ public class SMServicesConsumer { private HeartbeatConsumerServiceImpl heartbeatService; /** - * Initializes the Package Management service and the Applications Manager service + * Initializes the Package Management service and the Applications Manager + * service * * @param connectionConsumer Connection details - * @param comServices COM services + * @param comServices COM services */ public void init(ConnectionConsumer connectionConsumer, COMServicesConsumer comServices) { init(connectionConsumer, comServices, null, null); } /** - * Initializes the Package Management service and the Applications Manager service + * Initializes the Package Management service and the Applications Manager + * service * * @param connectionConsumer Connection details - * @param comServices COM services + * @param comServices COM services * @param authenticationId authenticationId of the logged in user */ - public void init(ConnectionConsumer connectionConsumer, COMServicesConsumer comServices, Blob authenticationId, - String localNamePrefix) { - + public void init(ConnectionConsumer connectionConsumer, COMServicesConsumer comServices, + Blob authenticationId, String localNamePrefix) { SingleConnectionDetails details; try { // Initialize the Apps Launcher service - details = connectionConsumer.getServicesDetails().get(AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME); + details = connectionConsumer.getServicesDetails().get( + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME); if (details != null) { - appsLauncherService = new AppsLauncherConsumerServiceImpl(details, comServices, authenticationId, - localNamePrefix); + appsLauncherService = new AppsLauncherConsumerServiceImpl( + details, comServices, authenticationId, localNamePrefix); } // Initialize the Command Executor Service service - details = connectionConsumer.getServicesDetails().get(CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME); + details = connectionConsumer.getServicesDetails().get( + CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME); if (details != null) { - commandExecutorService = new CommandExecutorConsumerServiceImpl(details, comServices, authenticationId, - localNamePrefix); + commandExecutorService = new CommandExecutorConsumerServiceImpl( + details, comServices, authenticationId, localNamePrefix); } // Initialize the Package Management service details = connectionConsumer.getServicesDetails().get( - PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE_NAME); + PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE_NAME); if (details != null) { - packageManagementService = new PackageManagementConsumerServiceImpl(details, comServices, - authenticationId, localNamePrefix); + packageManagementService = new PackageManagementConsumerServiceImpl( + details, comServices, authenticationId, localNamePrefix); } // Initialize the Heartbeat service details = connectionConsumer.getServicesDetails().get(HeartbeatHelper.HEARTBEAT_SERVICE_NAME); if (details != null) { - heartbeatService = new HeartbeatConsumerServiceImpl(details, comServices, authenticationId, - localNamePrefix); + heartbeatService = new HeartbeatConsumerServiceImpl(details, + comServices, authenticationId, localNamePrefix); } } catch (MALException | MalformedURLException | MALInteractionException ex) { Logger.getLogger(SMServicesConsumer.class.getName()).log(Level.SEVERE, null, ex); @@ -125,13 +128,14 @@ public HeartbeatConsumerServiceImpl getHeartbeatService() { * Sets manually all the COM consumer services * * @param packageManagementService Package Management service consumer - * @param appsLauncherService Applications Manager service consumer - * @param heartbeatService Heartbeat service consumer - * @param commandExecutorService Command Executor Service consumer + * @param appsLauncherService Applications Manager service consumer + * @param heartbeatService Heartbeat service consumer + * @param commandExecutorService Command Executor Service consumer */ public void setServices(PackageManagementConsumerServiceImpl packageManagementService, - AppsLauncherConsumerServiceImpl appsLauncherService, HeartbeatConsumerServiceImpl heartbeatService, - CommandExecutorConsumerServiceImpl commandExecutorService) { + AppsLauncherConsumerServiceImpl appsLauncherService, + HeartbeatConsumerServiceImpl heartbeatService, + CommandExecutorConsumerServiceImpl commandExecutorService) { this.packageManagementService = packageManagementService; this.appsLauncherService = appsLauncherService; this.heartbeatService = heartbeatService; diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesProvider.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesProvider.java index 1799d2676..1e4eb715a 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesProvider.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/SMServicesProvider.java @@ -29,9 +29,10 @@ import org.ccsds.moims.mo.mal.MALException; /** - * Deprecated because it is just an example class on how to start some of the - * Platform services. Although functional, this class should not be used out of - * the box. It's deliberately here just to demonstrate how to initialize services. + * Deprecated because it is just an example class on how to start some of the + * Platform services. Although functional, this class should not be used out of + * the box. It's deliberately here just to demonstrate how to initialize + * services. */ @Deprecated public class SMServicesProvider { diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java index 48bc9fef7..8374a21ef 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java @@ -18,7 +18,6 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ - package esa.mo.sm.impl.util; import java.io.BufferedReader; @@ -59,7 +58,8 @@ public String runCommandAndGetOutputMessage(String cmd) { return output.getMessage(); } catch (InterruptedException ex) { - Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, + "The thread was interrupted!", ex); } return ""; @@ -79,8 +79,8 @@ public String runCommandAndGetOutputMessageAndError(String cmd) { return output.getMessage() + error.getMessage(); } catch (InterruptedException ex) { - Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, "The command could not be executed!", - ex); + Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, + "The command could not be executed!", ex); } return ""; @@ -96,14 +96,14 @@ public Process runCommand(String cmd, File dirPath) { proc = Runtime.getRuntime().exec(new String[]{"cmd", "/c", cmd}, null, dirPath); } else { Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, - "The command could not executed due to an Unknown OS!"); + "The command could not executed due to an Unknown OS!"); return null; } return proc; } catch (IOException ex) { - Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, "The command could not be executed!", - ex); + Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, + "The command could not be executed!", ex); } return null; @@ -137,7 +137,8 @@ public void run() { } message = buffer.toString(); } catch (IOException ioe) { - Logger.getLogger(ShellCommander.class.getName()).log(Level.INFO, "Error: ", ioe); + Logger.getLogger(ShellCommander.class.getName()).log(Level.INFO, + "Error: ", ioe); } } } diff --git a/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-header.txt b/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-header.txt new file mode 100644 index 000000000..9da3494e9 --- /dev/null +++ b/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-header.txt @@ -0,0 +1,23 @@ +#Run the processing of internal models +startModels=true +#Increment the simulated time (depends on startModels) +startTime=true +#Speed up of time factor +timeFactor=1 +#Kepler elements for orbit A[km];E;i[deg];RAAN[deg];ARG_PER[deg];TRUE_A[deg] 7021.0;0.0;98.05;340.0;0.0;0.0 +keplerElements=6886.0;0.0;98.05;340.0;0.0;0.0 +#Enable the Orekit library for orbital and attitude simulation +orekit=true +#Enable updates from Internet (used for gps constellation TLEs) +updateFromInternet=false +#Configuration of the Celestia server +celestia=true +celestiaPort=5909 +#Start and end dates of simulation +startDate=2022:10:26 22:52:09 CEST +endDate=2022:10:26 22:52:09 CEST +#Logging level to files found in $USER_HOME/.ops-sat-simulator/ +#Possible values SEVERE,INFO,FINE,FINER,FINEST,ALL +centralLogLevel=INFO +simulatorLogLevel=INFO +consoleLogLevel=INFO \ No newline at end of file diff --git a/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-scheduler.txt b/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-scheduler.txt new file mode 100644 index 000000000..16d55437d --- /dev/null +++ b/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-scheduler.txt @@ -0,0 +1,8 @@ +#Simulator scheduler data file +#The commands below will be executed when simulator time has exceeded the defined time +#There are two possible ways to define the command, either as a DDDDD:HH:MM:SS:mmm format or directly in milliseconds value +#The simulator shall check the agreement between the two fields, if not equal, the DDDDD:HH:MM:SS:mmm will be used +#If the DDDDD:HH:MM:SS:mmm is zero, the milliseconds value will be used +#The simulator shall also sort the data file chronologically ascending +#days:hours:minutes:seconds:milliseconds|milliseconds|internalID|argument_template_name +#00000:00:00:00:000|0000000000000000000|1001|CUSTOM diff --git a/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-templates.txt b/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-templates.txt new file mode 100644 index 000000000..b6d91c080 --- /dev/null +++ b/core/nmf-composites/nanosat-mo-supervisor/_OPS-SAT-SIMULATOR-templates.txt @@ -0,0 +1,2 @@ +#||] +#2001|GLMLA|inputArgs=[String inputSentence={GLMLA}] \ No newline at end of file diff --git a/core/nmf-composites/nanosat-mo-supervisor/platformsim.properties b/core/nmf-composites/nanosat-mo-supervisor/platformsim.properties new file mode 100644 index 000000000..f9a00500c --- /dev/null +++ b/core/nmf-composites/nanosat-mo-supervisor/platformsim.properties @@ -0,0 +1,6 @@ +#Wed Oct 26 22:52:09 CEST 2022 +camerasim.imagefile=fix/me/earth.jpg +platform.mode=sim +camera.adapter=esa.mo.platform.impl.provider.opssat.CameraOPSSATAdapter +camerasim.imagemode=Fixed +camerasim.imagedirectory=fix/me From f2fe08e4aaceb961aeb834e7ae26b9b979ad91dc Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 14:45:28 +0200 Subject: [PATCH 040/173] Even more code cleanup --- .../AppsLauncherConsumerServiceImpl.java | 13 ++++----- .../CommandExecutorConsumerServiceImpl.java | 11 ++++---- .../HeartbeatConsumerServiceImpl.java | 27 ++++++++++--------- .../PackageManagementConsumerServiceImpl.java | 22 +++++++-------- 4 files changed, 39 insertions(+), 34 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/AppsLauncherConsumerServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/AppsLauncherConsumerServiceImpl.java index f39b35a67..6b8f7e6aa 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/AppsLauncherConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/AppsLauncherConsumerServiceImpl.java @@ -70,8 +70,8 @@ public AppsLauncherConsumerServiceImpl(final SingleConnectionDetails connectionD } public AppsLauncherConsumerServiceImpl(final SingleConnectionDetails connectionDetails, - final COMServicesConsumer comServices, final Blob authenticationId, final String localNamePrefix) - throws MALException, MalformedURLException, MALInteractionException { + final COMServicesConsumer comServices, final Blob authenticationId, + final String localNamePrefix) throws MALException, MalformedURLException, MALInteractionException { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -82,13 +82,13 @@ public AppsLauncherConsumerServiceImpl(final SingleConnectionDetails connectionD } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(AppsLauncherHelper.APPSLAUNCHER_SERVICE_NAME) == null) { AppsLauncherHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -100,7 +100,8 @@ public AppsLauncherConsumerServiceImpl(final SingleConnectionDetails connectionD try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(AppsLauncherConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(AppsLauncherConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/CommandExecutorConsumerServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/CommandExecutorConsumerServiceImpl.java index 0ac88f963..36ef98b48 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/CommandExecutorConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/CommandExecutorConsumerServiceImpl.java @@ -70,8 +70,9 @@ public CommandExecutorConsumerServiceImpl(final SingleConnectionDetails connecti } public CommandExecutorConsumerServiceImpl(final SingleConnectionDetails connectionDetails, - final COMServicesConsumer comServices, final Blob authenticationId, final String localNamePrefix) - throws MALException, MalformedURLException, MALInteractionException { + final COMServicesConsumer comServices, + final Blob authenticationId, + final String localNamePrefix) throws MALException, MalformedURLException, MALInteractionException { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -82,13 +83,13 @@ public CommandExecutorConsumerServiceImpl(final SingleConnectionDetails connecti } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME) == null) { CommandExecutorHelper.init(MALContextFactory.getElementFactoryRegistry()); } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/HeartbeatConsumerServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/HeartbeatConsumerServiceImpl.java index f0a0fd7bc..9d9657dae 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/HeartbeatConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/HeartbeatConsumerServiceImpl.java @@ -69,14 +69,14 @@ public Object generateServiceStub(MALConsumer tmConsumer) { return new HeartbeatStub(tmConsumer); } - public HeartbeatConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices) - throws MALException, MalformedURLException, MALInteractionException { + public HeartbeatConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { this(connectionDetails, comServices, null, null); } - public HeartbeatConsumerServiceImpl(SingleConnectionDetails connectionDetails, COMServicesConsumer comServices, - Blob authenticationId, String localNamePrefix) throws MALException, MalformedURLException, - MALInteractionException { + public HeartbeatConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, Blob authenticationId, + String localNamePrefix) throws MALException, MalformedURLException, MALInteractionException { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -86,14 +86,14 @@ public HeartbeatConsumerServiceImpl(SingleConnectionDetails connectionDetails, C COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - HeartbeatHelper.HEARTBEAT_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(HeartbeatHelper.HEARTBEAT_SERVICE_NAME) == null) { HeartbeatHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -105,7 +105,8 @@ public HeartbeatConsumerServiceImpl(SingleConnectionDetails connectionDetails, C try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(HeartbeatConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(HeartbeatConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } @@ -130,7 +131,8 @@ public void startListening(final HeartbeatAdapter adapter) { try { heartbeatService.beatRegister(heartbeatSubscription, adapter); } catch (MALInteractionException | MALException ex) { - Logger.getLogger(HeartbeatConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(HeartbeatConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } } @@ -149,7 +151,8 @@ public void stopListening() { ids.add(heartbeatSubscription.getSubscriptionId()); heartbeatService.beatDeregister(ids); } catch (MALInteractionException | MALException ex) { - Logger.getLogger(HeartbeatConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(HeartbeatConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/PackageManagementConsumerServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/PackageManagementConsumerServiceImpl.java index 09be7de09..6493a7526 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/PackageManagementConsumerServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/consumer/PackageManagementConsumerServiceImpl.java @@ -64,15 +64,14 @@ public Object generateServiceStub(MALConsumer tmConsumer) { return new PackageManagementStub(tmConsumer); } - public PackageManagementConsumerServiceImpl(SingleConnectionDetails connectionDetails, - COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { + public PackageManagementConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices) throws MALException, MalformedURLException, MALInteractionException { this(connectionDetails, comServices, null, null); } - public PackageManagementConsumerServiceImpl(SingleConnectionDetails connectionDetails, - COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) throws MALException, - MalformedURLException, MALInteractionException { - + public PackageManagementConsumerServiceImpl(SingleConnectionDetails connectionDetails, + COMServicesConsumer comServices, Blob authenticationId, String localNamePrefix) + throws MALException, MalformedURLException, MALInteractionException { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -81,14 +80,14 @@ public PackageManagementConsumerServiceImpl(SingleConnectionDetails connectionDe COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) == null) { SoftwareManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION).getServiceByName( - PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE_NAME) == null) { + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) + .getServiceByName(PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE_NAME) == null) { PackageManagementHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -100,7 +99,8 @@ public PackageManagementConsumerServiceImpl(SingleConnectionDetails connectionDe try { tmConsumer.close(); } catch (MALException ex) { - Logger.getLogger(PackageManagementConsumerServiceImpl.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(PackageManagementConsumerServiceImpl.class.getName()).log( + Level.SEVERE, null, ex); } } From 46e3222b7191b9aae81113f8d2650248fe79ab89 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 15:37:44 +0200 Subject: [PATCH 041/173] [nmfpack] Code cleanup --- .../mo/nmf/nmfpackage/NMFPackageManager.java | 27 +++---------------- .../nmf/nmfpackage/NMFPackagePMBackend.java | 24 +---------------- .../tests/SimpleDemoPackageCreation.java | 18 +++---------- 3 files changed, 8 insertions(+), 61 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index dc2f1ab62..94c2f050d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -221,11 +221,10 @@ public static void uninstall(final NMFPackageDescriptor descriptor, throw new IOException("The parsed descriptor is null."); } - // Verify integrity of the file: Are all the declared files matching their CRCs? - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Removing the files..."); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "Removing the files..."); removeFiles(descriptor); - String appName = descriptor.getDetails().getPackageName(); // This directory should be passed in the method signature: @@ -279,7 +278,6 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro ZipFile zipFile = new ZipFile(packageLocation); ZipEntry newReceipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); - // Verify integrity of the file: Are all the declared files matching their CRCs? Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Reading the receipt file that includes the list of files to be upgraded..."); @@ -372,7 +370,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro // chmod the installation directory with recursive LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); - + // --------------------------------------- // Store a copy of the newReceipt to know that it has been installed! //create the file otherwise we get FileNotFoundException @@ -582,25 +580,6 @@ private static void removeFiles(final NMFPackageDescriptor descriptor) throws IO final String path = generateFilePathForSystem(packageFile.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); NMFPackageManager.removeFile(file); - - /* - if (!file.exists()) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "The file no longer exists: " + file.getCanonicalPath()); - } else { - // The file exists... - - // Check the CRC - long crc = HelperNMFPackage.calculateCRCFromFile(file.getCanonicalPath()); - - if (packageFile.getCRC() != crc) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "The CRC does not match for file: " + file.getCanonicalPath()); - } - - NMFPackageManager.removeFile(file); - } - */ } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index 14549f8ff..ca42eddfc 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -31,17 +31,12 @@ import org.ccsds.moims.mo.mal.structures.StringList; /** + * The Package Management backend to handle the NMF Packages. * * @author Cesar Coelho */ public class NMFPackagePMBackend implements PMBackend { - @Deprecated - private static final String FOLDER_LOCATION_PROPERTY = "esa.mo.nmf.package.FolderLocation"; - - @Deprecated - private static final String PACKAGES_FOLDER = "packages"; // dir name - private final File packagesFolder; // Location of the folder /** @@ -54,22 +49,6 @@ public NMFPackagePMBackend(String folder) { packagesFolder = new File(folder); } - /** - * - * @deprecated The folder with the packages must be passed as argument - * instead of having the internal hidden properties for it! Please use: - * NMFPackagePMBackend(String folder) - */ - @Deprecated - public NMFPackagePMBackend() { - // If there is a property for that, then use it!! - if (System.getProperty(FOLDER_LOCATION_PROPERTY) != null) { - packagesFolder = new File(System.getProperty(FOLDER_LOCATION_PROPERTY)); - }else{ - packagesFolder = new File(PACKAGES_FOLDER); - } - } - @Override public StringList getListOfPackages() throws IOException { // Go to the folder that contains the Packages and return the list of files! @@ -170,7 +149,6 @@ public boolean isPackageInstalled(final String packageName) { @Override public boolean checkPackageIntegrity(final String packageName) throws UnsupportedOperationException { - // To do: Check the package integrity! return true; } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index e39f100f8..dd0cc0975 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -33,6 +33,7 @@ import org.ccsds.moims.mo.mal.structures.Time; /** + * A simple demo code to test the generation of NMF Packages. * * @author Cesar Coelho */ @@ -56,12 +57,6 @@ public static void createPackage() { files.add(myAppFilename); newLocations.add("apps" + File.separator + dummyFolder + File.separator + myAppFilename); - // Step 1: Fill in app details... - // App Name, Description, Category - // Step 2: Is it a NMF app? - // If Not: - // Select the binary files to be installed - // Additional libraries? final Time time = new Time(System.currentTimeMillis()); final String timestamp = HelperTime.time2readableString(time); @@ -89,20 +84,15 @@ public static void createPackage() { NMFPackageDetails details3 = new NMFPackageDetails("TestPackage", "3.0", timestamp, "noclass", "", "96m"); String location = NMFPackageCreator.nmfPackageCreator(details3, files, newLocations); - + try { // Test if the created file can be parsed ZipFile writtenFile = new ZipFile(location); NMFPackageDescriptor theDescriptor = NMFPackageDescriptor.parseZipFile(writtenFile); } catch (IOException ex) { - Logger.getLogger(SimpleDemoPackageCreation.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(SimpleDemoPackageCreation.class.getName()).log( + Level.SEVERE, "The file could not be processed!", ex); } - - // If Yes: - // Select the jar file (without dependencies) - // Select the provider.properties file - // - // Additional libraries? } } From ba1a630597ccae82dfecd1960f770a8d4cc7d2ec Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 17:06:24 +0200 Subject: [PATCH 042/173] Added transport default properties in case there is no file with them. This means that we can now run the demos directly from Netbeans without having to do complicated configurations --- .../mo/helpertools/helpers/HelperMisc.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java index 3b0ac7a00..05ff35de2 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java @@ -296,7 +296,8 @@ public static void loadPropertiesFile(Boolean useSharedBroker) { } else { Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, "The file transport.properties does not exist on the path: {0}\n" - + "Is the application working directory configured properly?", transport_file_path); + + "The App will fallback to the default TCP/IP Transport!", transport_file_path); + sysProps.putAll(getTransportDefaults()); } } @@ -321,8 +322,50 @@ public static void loadThisPropertiesFile(final String propertiesFileName) throw Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); } } + } - System.setProperties(sysProps); + System.setProperties(sysProps); + System.setProperty("PropertiesLoadedFlag", "true"); + + } catch (MalformedURLException ex) { + Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); + } + + } + + /** + * Loads in the properties of a file. + * + * @param propertiesFileName The name of the property file to load. + * @throws java.lang.IllegalArgumentException If propertiesFileName == null + */ + public static void loadThisPropertiesFile(final String propertiesFileName) + throws IllegalArgumentException { + if (propertiesFileName == null) { + throw new IllegalArgumentException("propertiesFileName must not be null."); + } + final java.util.Properties sysProps = System.getProperties(); + + File file = new File(propertiesFileName); + if (file.exists()) { + try { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), PROVIDER_PROPERTIES_FILE)); + } catch (MalformedURLException ex) { + Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); + } + } + + System.setProperties(sysProps); + } + + private static Properties getTransportDefaults(){ + Properties props = new Properties(); + props.setProperty("org.ccsds.moims.mo.mal.transport.default.protocol", "maltcp://"); + props.setProperty("org.ccsds.moims.mo.mal.transport.protocol.maltcp", "esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl"); + props.setProperty("org.ccsds.moims.mo.mal.encoding.protocol.maltcp", "esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory"); + props.setProperty("org.ccsds.moims.mo.mal.transport.tcpip.autohost", "true"); + return props; + } } From 2be42ba3df7e889a9d744e838256a97653b81d9a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 17:29:01 +0200 Subject: [PATCH 043/173] [com-archive] Code cleanup --- .../esa/mo/com/impl/archive/db/DatabaseBackend.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java index df9de33fb..30d1a8ff0 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java @@ -69,10 +69,10 @@ public class DatabaseBackend { private PreparedStatements preparedStatements; public DatabaseBackend() { - String url = System.getProperty("esa.nmf.archive.persistence.jdbc.url"); + String urlP = System.getProperty("esa.nmf.archive.persistence.jdbc.url"); - if (null != url && !"".equals(url)) { - this.url = url; + if (null != urlP && !"".equals(urlP)) { + this.url = urlP; } else { File dbFile = new File(DATABASE_LOCATION_NAME); boolean writableFs = true; @@ -99,10 +99,8 @@ public DatabaseBackend() { String driver = System.getProperty("esa.nmf.archive.persistence.jdbc.driver"); this.jdbcDriver = (null != driver && !"".equals(driver)) ? driver : DRIVER_CLASS_NAME; - - String user = System.getProperty("esa.nmf.archive.persistence.jdbc.user"); - this.user = (null != user && !"".equals(user)) ? user : null; - + String userP = System.getProperty("esa.nmf.archive.persistence.jdbc.user"); + this.user = (null != userP && !"".equals(userP)) ? userP : null; String pass = System.getProperty("esa.nmf.archive.persistence.jdbc.password"); this.password = (null != pass && !"".equals(pass)) ? pass : null; } From 0d20c18d1e195cbb6c19a1de3572dce0d61c1dc4 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 11 Apr 2022 17:30:00 +0200 Subject: [PATCH 044/173] Code cleanup --- .../mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 3ba9fad74..154a66dfb 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -48,7 +48,6 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.com.COMService; @@ -194,7 +193,7 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { try { // Convert provider to connectionDetails... final SingleConnectionDetails connectionDetails = AppsLauncherManager - .getSingleConnectionDetailsFromProviderSummaryList(supervisorEventServiceConnectionDetails); + .getSingleConnectionDetailsFromProviderSummaryList(supervisorEventServiceConnectionDetails); serviceCOMEvent = new EventConsumerServiceImpl(connectionDetails); } catch (IOException | MALException | MALInteractionException ex) { LOGGER.log(Level.SEVERE, @@ -464,7 +463,7 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter, final MissionPlann try { // Convert provider to connectionDetails... final SingleConnectionDetails connectionDetails = AppsLauncherManager - .getSingleConnectionDetailsFromProviderSummaryList(supervisorEventServiceConnectionDetails); + .getSingleConnectionDetailsFromProviderSummaryList(supervisorEventServiceConnectionDetails); serviceCOMEvent = new EventConsumerServiceImpl(connectionDetails); } catch (IOException | MALException | MALInteractionException ex) { LOGGER.log(Level.SEVERE, From 1029aa56bcea3a66385dda3922c6fbf04d85add0 Mon Sep 17 00:00:00 2001 From: CesarCoelho Date: Tue, 12 Apr 2022 15:43:18 +0200 Subject: [PATCH 045/173] Update README.md [README] Clear instructions on how to build --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 84a817a98..542a96c5f 100644 --- a/README.md +++ b/README.md @@ -21,20 +21,26 @@ The research was carried by Graz University of Technology in partnership with th ## Release The latest NMF SDK release tag can be downloaded in [Releases]. However, the currently recommended distribution channel is directly from Git repository. -## Getting Started - -### Building +## Building Prerequisites: - Java SDK 1.8 or higher - Apache Maven -Clone this repository, set the environment variable NMF\_HOME with the path to this repository's root directory and run `mvn install` in the root directory. +Instructions: + +1. Clone this repository + +2. Set the environment variable NMF\_HOME with the path to this repository's root directory + +3. Run in the root directory: `mvn install` Note that the errors about missing module descriptors during Javadoc generation are to be expected and non breaking. -In order to produce independently runnable Java executables (JAR artifacts with dependencies - equivalent of statically linked executables), use `mvn install -P assembly-with-dependencies`. +In order to produce independently runnable Java executables (JAR artifacts with dependencies - equivalent of statically linked executables), use `mvn install -P assembly-with-dependencies` + +## Getting Started ### SDK and examples From c4f005362bb95c2d04ba6861e4dce90e7a24d648 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 12 Apr 2022 17:44:29 +0200 Subject: [PATCH 046/173] [ai] Updates to the AI interface --- .../connections/ConnectionProvider.java | 1 - ...ficialIntelligenceProviderServiceImpl.java | 10 +++--- .../main/resources/xml/ServiceDefPLATFORM.xml | 34 +++++++++++++------ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java index f3bd6ff56..f47bc6421 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java @@ -23,7 +23,6 @@ import esa.mo.helpertools.helpers.HelperConnections; import esa.mo.helpertools.helpers.HelperMisc; import java.io.BufferedWriter; -import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index 6bd38167c..9bb1f6da9 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -33,7 +33,6 @@ import org.ccsds.moims.mo.platform.artificialintelligence.ArtificialIntelligenceHelper; import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; import esa.mo.helpertools.connections.ConnectionProvider; -import org.ccsds.moims.mo.mal.structures.File; public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelligenceInheritanceSkeleton { @@ -102,13 +101,12 @@ public void close() { } @Override - public void setModel(File location, MALInteraction interaction) throws MALInteractionException, MALException { - throw new UnsupportedOperationException("Not supported yet."); + public Long setModel(String modelPath, String weightsPath, MALInteraction interaction) throws MALInteractionException, MALException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override - public File doInference(File inputTiles, MALInteraction interaction) throws MALInteractionException, MALException { - throw new UnsupportedOperationException("Not supported yet."); + public String doInference(Long modelId, String inputTilesPath, MALInteraction interaction) throws MALInteractionException, MALException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } - } diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index 8150f945a..a1739a02e 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2155,18 +2155,28 @@ comment="The Artificial Intelligence service provides a generic mechanism to control a AI device including setting the models and control the inference of images." name="ArtificialIntelligence" number="9" xsi:type="com:ExtendedServiceType"> - - + + + + - + comment="The weightsPath field holds the path to the file of the model weights." name="weightsPath"> + - + + + + + + - + - + comment="The modelId field holds the id of the model to be used for inference." name="modelId"> + + + + - + comment="The outputTiles field holds the path to a folder with the infered tiles." name="outputTilesPath"> + From 3d5f4d493a87d20991b10fa9cd6d8ef17fc83175 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 19 Apr 2022 09:30:39 +0200 Subject: [PATCH 047/173] [ai] Updates to the AI service backend adapter interface --- ...rtificialIntelligenceAdapterInterface.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java index be05e7f42..2ae60743f 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java @@ -20,10 +20,25 @@ */ package esa.mo.platform.impl.provider.gen; -import org.ccsds.moims.mo.mal.structures.Time; +import java.io.IOException; public interface ArtificialIntelligenceAdapterInterface { - public Time setModel(); + /** + * Sets a model to the Artificial Intelligence device. + * + * @param modelPath The file path to the model. + * @param weightsPath The file path to the weights of the model. + * @throws IOException If the model was not set. + */ + public void setModel(String modelPath, String weightsPath) throws IOException; + + /** + * Executes the inference on the Artificial Intelligence device. + * + * @param path The file path to a folder with a set of files to be + * processed. + */ + public void executeInference(String path); } From 46aa2edee450b8149e9b47a61931db1f5bd7948e Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 19 Apr 2022 09:31:50 +0200 Subject: [PATCH 048/173] [nmp-package] Fixed the ZipSlip vulnerability --- .../esa/mo/nmf/nmfpackage/NMFPackageManager.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 94c2f050d..9ecde475a 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -521,10 +521,14 @@ private static File getInstallationFolder() { return folder; } - private static String generateFilePathForSystem(final String path) { - String out = path.replace("..", "\u0000"); - String out1 = out.replace('/', File.separatorChar); - return out1.replace('\\', File.separatorChar); + private static String generateFilePathForSystem(final String path) throws IOException { + // Sanitize the path to prevent a ZipSlip attack: + if (path.contains("..")) { + throw new IOException("Warning! A ZipSlip attack was detected!"); + } + + String out = path.replace('/', File.separatorChar); + return out.replace('\\', File.separatorChar); } private static void installFiles(final ZipFile zipFile, File to) throws IOException { From 4777d5a84f64f27f7ced3e16b9476f035f4f6b85 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 19 Apr 2022 17:33:32 +0200 Subject: [PATCH 049/173] Added javadocs comments --- .../esa/mo/sm/impl/util/ShellCommander.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java index 8374a21ef..48116d7f2 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java @@ -40,10 +40,24 @@ public class ShellCommander { public ShellCommander() { } + /** + * Runs a command on the OS shell. Note that the input is not being + * sanitized and therefore, this method should not have any user inputs! + * + * @param cmd The command to run + * @return The Process + */ public Process runCommand(String cmd) { return this.runCommand(cmd, null); } + /** + * Runs a command on the OS shell. Note that the input is not being + * sanitized and therefore, this method should not have any user inputs! + * + * @param cmd The command to run + * @return The output + */ public String runCommandAndGetOutputMessage(String cmd) { try { Process proc = this.runCommand(cmd, null); @@ -58,13 +72,20 @@ public String runCommandAndGetOutputMessage(String cmd) { return output.getMessage(); } catch (InterruptedException ex) { - Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, + Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, "The thread was interrupted!", ex); } return ""; } + /** + * Runs a command on the OS shell. Note that the input is not being + * sanitized and therefore, this method should not have any user inputs! + * + * @param cmd The command to run + * @return The output from the command + */ public String runCommandAndGetOutputMessageAndError(String cmd) { try { Process proc = this.runCommand(cmd, null); @@ -86,6 +107,14 @@ public String runCommandAndGetOutputMessageAndError(String cmd) { return ""; } + /** + * Runs a command on the OS shell. Note that the input is not being + * sanitized and therefore, this method should not have any user inputs! + * + * @param cmd The command to run + * @param dirPath The working directory of the process + * @return + */ public Process runCommand(String cmd, File dirPath) { try { Process proc; From 3a9fff2b4ff7591208efda5bde55dfcad3c7c26f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 19 Apr 2022 17:43:04 +0200 Subject: [PATCH 050/173] Improved the code for the Linux Users/Groups activities --- .../mo/nmf/nmfpackage/LinuxUsersGroups.java | 347 ++++++------------ 1 file changed, 112 insertions(+), 235 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java index cea75d133..4e8bf955d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java @@ -20,8 +20,10 @@ */ package esa.mo.nmf.nmfpackage; -import esa.mo.sm.impl.util.ShellCommander; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,8 +35,6 @@ */ public class LinuxUsersGroups { - private static final String NOT_FOUND = "command not found"; - private static final String PERMISSION_DENIED = "Permission denied"; private static final String MSG_NOT_FOUND = "The command was not found.\n"; @@ -58,43 +58,21 @@ public class LinuxUsersGroups { */ public static void useradd(String username, String password, boolean withGroup, String extraGroups) throws IOException { - ShellCommander shell = new ShellCommander(); - - // First, we need to check if the "useradd" exist - String cmd1 = "useradd -h"; - String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); - - if (out1.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; - throw new IOException(msg); - } - // Second, we need to check if we have permissions to run the commands - StringBuilder useradd = new StringBuilder(); - useradd.append("sudo "); - useradd.append("useradd ").append(username) - .append(" --create-home") - .append(" --shell ").append(DEFAULT_SHELL) - .append(withGroup ? " --user-group" : "") - .append(" --groups ").append(extraGroups); //String cmd = "useradd $user_nmf_admin -m -s /bin/bash --user-group"; //String cmd = "useradd $user_nmf_admin --create-home --shell /bin/bash --user-group"; - - String cmd3 = useradd.toString(); - String out3 = shell.runCommandAndGetOutputMessageAndError(cmd3); - - if (out3.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd3 + "\n" + out3; - throw new IOException(msg); - } + String group = withGroup ? "--user-group" : ""; + String[] cmd = {"sudo", "useradd", username, "--create-home", + "--shell", DEFAULT_SHELL, group, "--groups", extraGroups}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); // Does the user account have a respective password? if (password != null) { LinuxUsersGroups.chpasswd(username, password); } - // Change permissions on the home directories - LinuxUsersGroups.printCommandAndOutput(cmd3, out3); + LinuxUsersGroups.printCommandAndOutput(cmd, out); } /** @@ -105,33 +83,10 @@ public static void useradd(String username, String password, * @throws IOException if the group could not be created. */ public static void addgroup(String groupName, boolean isSystemGroup) throws IOException { - ShellCommander shell = new ShellCommander(); - - // First, we need to check if the "useradd" exist - String cmd1 = "sudo addgroup -h"; - String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); - - if (out1.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; - throw new IOException(msg); - } - - StringBuilder addgroup = new StringBuilder(); - addgroup.append("sudo "); - addgroup.append("addgroup ") - .append("-S ") - .append(groupName); - - String cmd2 = addgroup.toString(); - String out2 = shell.runCommandAndGetOutputMessageAndError(cmd2); - - if (out2.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd2 + "\n" + out2; - throw new IOException(msg); - } - - // Print the command output: - LinuxUsersGroups.printCommandAndOutput(cmd2, out2); + String[] cmd = {"sudo", "addgroup", "-S", groupName}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + LinuxUsersGroups.printCommandAndOutput(cmd, out); } /** @@ -148,113 +103,59 @@ public static void addgroup(String groupName, boolean isSystemGroup) throws IOEx */ public static void adduser(String username, String password, boolean withGroup) throws IOException { - ShellCommander shell = new ShellCommander(); - - // First, we need to check if the "useradd" exist - String cmd1 = "sudo adduser -h"; - String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); - - if (out1.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; - throw new IOException(msg); - } + // First, we need to check if the "useradd" is from BusyBox or not + String[] cmd1 = {"sudo", "adduser", "-h"}; + String out1 = runCommand(cmd1); // Different Linux Systems have different syntaxes for the same command // So we need to check if we are using the adduser from "BusyBox" or not boolean isBusyBox = out1.contains("BusyBox"); // Second, we need to check if we have permissions to run the commands - StringBuilder useradd = new StringBuilder(); - useradd.append("sudo "); + String[] cmd2; if (isBusyBox) { if (withGroup) { LinuxUsersGroups.addgroup(username, true); } - useradd.append("adduser ") - .append("-s ").append(DEFAULT_SHELL) - .append(withGroup ? " -G " : "") - .append(withGroup ? username : "") - .append(" -S ") - .append(username); + + cmd2 = new String[]{"sudo", "adduser", "-s", DEFAULT_SHELL, + withGroup ? " -G " : "", withGroup ? username : "", + "-S", username}; } else { - useradd.append("adduser --system ") - .append("--shell ").append(DEFAULT_SHELL) - .append(withGroup ? " --group " : " ") - .append(username); + cmd2 = new String[]{"sudo", "adduser", "--system", + "--shell", DEFAULT_SHELL, withGroup ? "--group" : "", + username}; } //String cmd = "useradd $user_nmf_admin -m -s /bin/bash --user-group"; //String cmd = "useradd $user_nmf_admin --create-home --shell /bin/bash --user-group"; - - String cmd3 = useradd.toString(); - String out3 = shell.runCommandAndGetOutputMessageAndError(cmd3); - - if (out3.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd3 + "\n" + out3; - throw new IOException(msg); - } + String out2 = runCommand(cmd2); + checkIfPermissionDenied(cmd2, out2); // Does the user account have a respective password? if (password != null) { LinuxUsersGroups.chpasswd(username, password); } - // Change permissions on the home directories - LinuxUsersGroups.printCommandAndOutput(cmd3, out3); + LinuxUsersGroups.printCommandAndOutput(cmd2, out2); } public static void addUserToGroup(String username, String extraGroup) throws IOException { - ShellCommander shell = new ShellCommander(); - - // First, we need to check if the "useradd" exist - String cmd1 = "sudo adduser -h"; - String out1 = shell.runCommandAndGetOutputMessageAndError(cmd1); - - if (out1.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd1 + "\n" + out1; - throw new IOException(msg); - } - - StringBuilder useradd = new StringBuilder(); - useradd.append("sudo "); - useradd.append("adduser ") - .append(username) - .append(" ") - .append(extraGroup); - - String cmd3 = useradd.toString(); - String out3 = shell.runCommandAndGetOutputMessageAndError(cmd3); - - if (out3.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd3 + "\n" + out3; - throw new IOException(msg); - } + String[] cmd = {"sudo", "adduser", username, extraGroup}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + LinuxUsersGroups.printCommandAndOutput(cmd, out); } public static void chpasswd(String username, String password) throws IOException { - ShellCommander shell = new ShellCommander(); - String cmd2 = "chpasswd -h"; - String out2 = shell.runCommandAndGetOutputMessageAndError(cmd2); + String[] cmd1 = {"chpasswd", "-h"}; + String out1 = runCommand(cmd1); - if (out2.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd2 + "\n" + out2; - throw new IOException(msg); - } - - StringBuilder chpasswd = new StringBuilder(); - chpasswd.append("echo ") - .append(username).append(":").append(password) - .append(" | ") - .append("chpasswd"); // echo $user_nmf_admin:$user_nmf_admin_password | chpasswd - - String cmd4 = chpasswd.toString(); - String out4 = shell.runCommandAndGetOutputMessageAndError(cmd4); - - if (out4.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd4 + "\n" + out4; - throw new IOException(msg); - } + String userWithPass = username + ":" + password; + String[] cmd2 = {"echo", userWithPass, "|", "chpasswd"}; + String out2 = runCommand(cmd2); + checkIfPermissionDenied(cmd2, out2); } /** @@ -265,26 +166,11 @@ public static void chpasswd(String username, String password) throws IOException * @throws IOException if the user could not be deleted. */ public static void userdel(String username, boolean removeHome) throws IOException { - StringBuilder cmd = new StringBuilder(); - cmd.append("sudo "); - cmd.append("userdel --force "); - cmd.append(removeHome ? "--remove " : ""); - cmd.append(username); - - ShellCommander shell = new ShellCommander(); - String out = shell.runCommandAndGetOutputMessageAndError(cmd.toString()); - - if (out.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } - - if (out.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } - - LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); + String strRemove = removeHome ? "--remove" : ""; + String[] cmd = {"sudo", "userdel", "--force", strRemove, username}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + LinuxUsersGroups.printCommandAndOutput(cmd, out); } /** @@ -295,26 +181,11 @@ public static void userdel(String username, boolean removeHome) throws IOExcepti * @throws IOException if the user could not be deleted. */ public static void deluser(String username, boolean removeHome) throws IOException { - StringBuilder cmd = new StringBuilder(); - cmd.append("sudo "); - cmd.append("deluser "); - cmd.append(removeHome ? "--remove-home " : ""); - cmd.append(username); - - ShellCommander shell = new ShellCommander(); - String out = shell.runCommandAndGetOutputMessageAndError(cmd.toString()); - - if (out.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } - - if (out.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } - - LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); + String strRemove = removeHome ? "--remove-home" : ""; + String[] cmd = {"sudo", "deluser", strRemove, username}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + LinuxUsersGroups.printCommandAndOutput(cmd, out); } /** @@ -328,81 +199,87 @@ public static void deluser(String username, boolean removeHome) throws IOExcepti * @throws IOException if the permissions could not be changed. */ public static void chmod(boolean sudo, boolean recursive, String mode, String path) throws IOException { - StringBuilder cmd = new StringBuilder(); - cmd.append(sudo ? "sudo " : ""); - cmd.append("chmod "); - cmd.append(recursive ? "--recursive " : ""); - cmd.append(mode); - cmd.append(" "); - cmd.append(path); - - ShellCommander shell = new ShellCommander(); - String out = shell.runCommandAndGetOutputMessageAndError(cmd.toString()); - - if (out.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } + String strRecursive = recursive ? "--recursive" : ""; + //String[] cmd = {sudo ? "sudo" : "", "chmod", strRecursive, mode, path}; + String[] cmd = sudo + ? new String[]{"sudo", "chmod", strRecursive, mode, path} + : new String[]{"chmod", strRecursive, mode, path}; + + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + LinuxUsersGroups.printCommandAndOutput(cmd, out); + } - if (out.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd + "\n" + out; - throw new IOException(msg); + public static void chgrp(boolean recursive, String newGroup, String path) throws IOException { + String[] cmd = {"sudo", "chgrp", recursive ? "--recursive" : "", newGroup, path}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + LinuxUsersGroups.printCommandAndOutput(cmd, out); + } + + public static String findHomeDir(String username) throws IOException { + // Get the list of users and respective folders + String[] cmd = {"cat", "/etc/passwd"}; + String out = runCommand(cmd); + checkIfPermissionDenied(cmd, out); + String[] lines = out.split("\\R"); + + for (String line : lines) { + if (line.contains(username)) { + return line.split(":")[5]; + } } - LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); + throw new IOException("The HomeDir was not found for user: " + username); } - public static void chgrp(boolean recursive, String newGroup, String path) throws IOException { - StringBuilder cmd = new StringBuilder(); - cmd.append("sudo "); - cmd.append("chgrp "); - cmd.append(recursive ? "--recursive " : ""); - cmd.append(newGroup); - cmd.append(" "); - cmd.append(path); - - ShellCommander shell = new ShellCommander(); - String out = shell.runCommandAndGetOutputMessageAndError(cmd.toString()); - - if (out.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } + public static void printCommandAndOutput(String[] cmd, String out) { + Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, + "Executed command: " + String.join(" ", cmd) + "\n" + out); + } + private static void checkIfPermissionDenied(String[] cmd, String out) throws IOException { if (out.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd + "\n" + out; + String msg = "Permission denied! For command:\n >> " + + String.join(" ", cmd) + "\n" + out; throw new IOException(msg); } - - LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); } - public static String findHomeDir(String username) throws IOException { - StringBuilder cmd = new StringBuilder(); - cmd.append("cat /etc/passwd | grep '"); - cmd.append(username); - cmd.append(":' | cut -d ':' -f6"); + private static String runCommand(String[] cmd) throws IOException { + try { + Process p = Runtime.getRuntime().exec(cmd, null, null); + boolean terminated = p.waitFor(10, TimeUnit.SECONDS); - ShellCommander shell = new ShellCommander(); - String out = shell.runCommandAndGetOutputMessageAndError(cmd.toString()); + if (!terminated) { + Logger.getLogger(LinuxUsersGroups.class.getName()).log( + Level.SEVERE, + "Timeout reached: The process is stuck... " + + "therefore the process was killed!"); - if (out.contains(NOT_FOUND)) { - String msg = MSG_NOT_FOUND + "\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } + p.destroyForcibly(); + } - if (out.contains(PERMISSION_DENIED)) { - String msg = "Permission denied! For command:\n >> " + cmd + "\n" + out; - throw new IOException(msg); - } + BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); + StringBuilder buffer = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + buffer.append(line); + buffer.append("\n"); + } - LinuxUsersGroups.printCommandAndOutput(cmd.toString(), out); - return out; - } + int exitValue = p.exitValue(); + String out = buffer.toString(); - public static void printCommandAndOutput(String cmd, String out) { - Logger.getLogger(LinuxUsersGroups.class.getName()).log(Level.INFO, - "Executed command: " + cmd + "\n" + out); + if (exitValue == 127) { // Command not found! + throw new IOException(MSG_NOT_FOUND + + "\n >> " + String.join(" ", cmd) + "\n" + out); + } + + return out; + } catch (InterruptedException ex) { + throw new IOException(ex); + } } } From bdb4e499dadc43162f6c7674eb8657de7e858623 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 19 Apr 2022 19:00:52 +0200 Subject: [PATCH 051/173] [nmf-package] Improved javadocs and added a few extra conditions when it installs in a Linux machine. --- .../mo/nmf/nmfpackage/NMFPackageManager.java | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 9ecde475a..c573e0580 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -63,6 +63,14 @@ public class NMFPackageManager { private static final String SEPARATOR = "--------------\n"; + /** + * Installs an NMF Package on the specified NMF root folder. + * + * @param packageLocation The NMF Package location + * @param nmfDir The NMF root directory + * @throws FileNotFoundException if the file was not found + * @throws IOException if there was a problem with the NMF Package + */ public static void install(final String packageLocation, final File nmfDir) throws FileNotFoundException, IOException { System.out.printf(SEPARATOR); @@ -174,13 +182,15 @@ public static void install(final String packageLocation, String transportContent = HelperNMFPackage.generateTransportProperties(); NMFPackageManager.writeFile(transportPath, transportContent); - // Change Group owner of the installationDir - if (username != null) { - LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); - } + if ((new OSValidator()).isUnix()) { + // Change Group owner of the installationDir + if (username != null) { + LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); + } - // chmod the installation directory with recursive - LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + // chmod the installation directory with recursive + LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + } // --------------------------------------- // Store a copy of the newReceipt to know that it has been installed! @@ -212,6 +222,13 @@ public static void install(final String packageLocation, System.out.printf(SEPARATOR); } + /** + * Uninstalls an NMF Package using the respective package descriptor. + * + * @param descriptor The desccriptor + * @param keepUserData A flag that sets if the user data is kept + * @throws IOException if there was a problem during the uninstallation + */ public static void uninstall(final NMFPackageDescriptor descriptor, final boolean keepUserData) throws IOException { System.out.printf(SEPARATOR); @@ -243,11 +260,13 @@ public static void uninstall(final NMFPackageDescriptor descriptor, } // --------------------------------------- - // We need to delete the respective user here!! - //LinuxUsersGroups.userdel(generateUsername(appName), true); - if (!keepUserData) { - String username = generateUsername(appName); - LinuxUsersGroups.deluser(username, true); + if ((new OSValidator()).isUnix()) { + // We need to delete the respective user here!! + //LinuxUsersGroups.userdel(generateUsername(appName), true); + if (!keepUserData) { + String username = generateUsername(appName); + LinuxUsersGroups.deluser(username, true); + } } Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, @@ -272,6 +291,13 @@ private static void removeAuxiliaryFiles(File installationDir, String appName) t NMFPackageManager.removeFile(new File(startPath)); } + /** + * Upgrades an NMF Package with a newer version. + * + * @param packageLocation The NMF Package location + * @param nmfDir The NMF root directory + * @throws IOException if the package could not be upgraded + */ public static void upgrade(final String packageLocation, final File nmfDir) throws IOException { System.out.printf(SEPARATOR); // Get the Package to be uninstalled @@ -363,13 +389,15 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro String transportContent = HelperNMFPackage.generateTransportProperties(); NMFPackageManager.writeFile(transportPath, transportContent); - // Change Group owner of the installationDir - if (username != null) { - LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); - } + if ((new OSValidator()).isUnix()) { + // Change Group owner of the installationDir + if (username != null) { + LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); + } - // chmod the installation directory with recursive - LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + // chmod the installation directory with recursive + LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + } // --------------------------------------- // Store a copy of the newReceipt to know that it has been installed! @@ -397,7 +425,8 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro } /** - * Based on the name, goes to the receipts folder and checks. + * Checks if a certain NMF package is installed. Based on the name, goes to + * the receipts folder and checks. * * @param packageLocation The package location. * @return If it is installed or not. From 33c455fa88ac61ea204a1fc4fc2da01526cedb86 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 21 Apr 2022 13:39:41 +0200 Subject: [PATCH 052/173] Added the Edge AI App to the SDK. This App will demonstrate how to use the NMF AI service. --- sdk/examples/space/edge-ai/.gitignore | 1 + sdk/examples/space/edge-ai/README.md | 54 ++++++ sdk/examples/space/edge-ai/pom.xml | 128 +++++++++++++ .../esa/mo/nmf/apps/edgeai/EdgeAIApp.java | 45 +++++ .../esa/mo/nmf/apps/edgeai/MCAdapter.java | 177 ++++++++++++++++++ .../src/main/resources/scripts/myScript.py | 8 + sdk/examples/space/pom.xml | 1 + 7 files changed, 414 insertions(+) create mode 100644 sdk/examples/space/edge-ai/.gitignore create mode 100644 sdk/examples/space/edge-ai/README.md create mode 100644 sdk/examples/space/edge-ai/pom.xml create mode 100644 sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java create mode 100644 sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java create mode 100644 sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py diff --git a/sdk/examples/space/edge-ai/.gitignore b/sdk/examples/space/edge-ai/.gitignore new file mode 100644 index 000000000..3475b2ff7 --- /dev/null +++ b/sdk/examples/space/edge-ai/.gitignore @@ -0,0 +1 @@ +toGround/ diff --git a/sdk/examples/space/edge-ai/README.md b/sdk/examples/space/edge-ai/README.md new file mode 100644 index 000000000..fae45c84e --- /dev/null +++ b/sdk/examples/space/edge-ai/README.md @@ -0,0 +1,54 @@ +# Edge AI NMF App + + + +NMF App that allows to: + + - Run AI for Earth Observation + - Takes advantage of the AI service part of the NanoSat MO Framework + - Stores the processed tiles in a folder + + + +## Prerequisites: + +The Edge AI App takes advantage of the AI service of the NanoSat MO Framework therefore the App needs to be running on a NMF system with an implementation of the AI service, in particular, to an edge computing hardware such as the Intel Movidius device which has been space-qualified with ESA's Phi-Sat-1 mission. + + + +## MO Actions: + +The App exposes two MO Actions: "*AI_Start*" and "*AI_Cancel*". + + + +### AI_Start + +When this action is triggered, the App will run inference using the AI service. + + +When the external process terminates the App will publish a MO Parameter whose name have the following format: "Process Request ID: \ exitCode: \". + + + +### AI_Cancel: + +When this action is triggered, the App will attempt to terminate the process having the provided "Action Request ID" + + +The "Action Request ID" is printed on the console of the "Apps Launcher Service" of the Supervisor whenever the "*AI_Start*" action is triggered. + +Example: + +``` +INFO: Process 1614083521462 is starting. It will last at least 0 seconds and at most 30000 ms +``` + + + +#### Arguments: + +1. Action Request ID: the action request ID of the "*AI_Start*" Action that triggered the external process. + + + diff --git a/sdk/examples/space/edge-ai/pom.xml b/sdk/examples/space/edge-ai/pom.xml new file mode 100644 index 000000000..e6af6afef --- /dev/null +++ b/sdk/examples/space/edge-ai/pom.xml @@ -0,0 +1,128 @@ + + + + + + 4.0.0 + + + int.esa.nmf + parent + 2.1.0-SNAPSHOT + ../../../../parent/pom.xml + + + int.esa.nmf.sdk.examples.space + edge-ai + jar + + ESA NMF SDK App Example - Edge AI + A demo that performs AI directly on-board. + http://www.esa.int + + + ESA + http://www.esa.int + + + + + European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + https://raw.github.com/esa/nanosat-mo-framework/master/LICENCE.md + repo + + + + + scm:git:git@github.com:esa/nanosat-mo-framework.git + scm:git:git@github.com:esa/nanosat-mo-framework.git + https://github.com/esa/nanosat-mo-framework + + + + GitHub + https://github.com/esa/nanosat-mo-framework/issues + + + + + CesarCoelho + César Coelho + https://github.com/CesarCoelho + + + + + esa.mo.nmf.apps.edgeai.EdgeAIApp + + + + + int.esa.nmf.core + nanosat-mo-connector + + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.codehaus.mojo + build-helper-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-resources-plugin + + + + + + + generate-nmf-package + + + + int.esa.nmf.core + nmf-package-maven-plugin + + + package + + generate-nmf-package + + + ${assembly.mainClass} + + + + + + + + + diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java new file mode 100644 index 000000000..4bd51061a --- /dev/null +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java @@ -0,0 +1,45 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.edgeai; + +import esa.mo.nmf.nanosatmoconnector.NanoSatMOConnectorImpl; + +/** + * An NMF App that runs an AI model directly on-board + */ +public class EdgeAIApp { + + public EdgeAIApp() { + NanoSatMOConnectorImpl connector = new NanoSatMOConnectorImpl(); + connector.init(new MCAdapter(connector)); + } + + /** + * Main command line entry point. + * + * @param args the command line arguments + * @throws java.lang.Exception If there is an error + */ + public static void main(final String[] args) throws Exception { + EdgeAIApp app = new EdgeAIApp(); + } + +} diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java new file mode 100644 index 000000000..43b16b21a --- /dev/null +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java @@ -0,0 +1,177 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.apps.edgeai; + +import static esa.mo.helpertools.helpers.HelperAttributes.attribute2JavaType; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.mal.provider.MALInteraction; +import org.ccsds.moims.mo.mal.structures.Attribute; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.UInteger; +import org.ccsds.moims.mo.mal.structures.UOctet; +import org.ccsds.moims.mo.mal.structures.UShort; +import org.ccsds.moims.mo.mc.action.structures.ActionDefinitionDetails; +import org.ccsds.moims.mo.mc.action.structures.ActionDefinitionDetailsList; +import org.ccsds.moims.mo.mc.structures.ArgumentDefinitionDetails; +import org.ccsds.moims.mo.mc.structures.ArgumentDefinitionDetailsList; +import org.ccsds.moims.mo.mc.structures.AttributeValue; +import org.ccsds.moims.mo.mc.structures.AttributeValueList; +import esa.mo.nmf.MCRegistration; +import esa.mo.nmf.MonitorAndControlNMFAdapter; +import esa.mo.nmf.NMFException; +import esa.mo.nmf.NMFInterface; +import esa.mo.nmf.NMFProvider; + +/** + * The adapter for the NMF App + */ +public class MCAdapter extends MonitorAndControlNMFAdapter { + + private static final Logger LOG = Logger.getLogger(MCAdapter.class.getName()); + + private static final String ACTION_START_AI = "AI_Start"; + private static final String ACTION_CANCEL_AI = "AI_Cancel"; + private static final int TOTAL_STAGES = 1; + + private final NMFInterface connector; + + public MCAdapter(NMFProvider connector) { + this.connector = connector; + } + + @Override + public void initialRegistrations(MCRegistration registration) { + registration.setMode(MCRegistration.RegistrationMode.DONT_UPDATE_IF_EXISTS); + + // ------------------ Actions ------------------ + ActionDefinitionDetailsList actionDefs = new ActionDefinitionDetailsList(); + IdentifierList actionNames = new IdentifierList(); + + registerActionAIStart(actionDefs, actionNames); + registerActionAICancel(actionDefs, actionNames); + // ---- + + registration.registerActions(actionNames, actionDefs); + } + + @Override + public UInteger actionArrived(Identifier name, AttributeValueList attributeValues, + Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { + + if (ACTION_START_AI.equals(name.getValue())) { + triggerAIInference(actionInstanceObjId, attributeValues); + return null; // Success! + } else if (ACTION_CANCEL_AI.equals(name.getValue())) { + destroyProcess(attributeValues); + return null; + } + + return new UInteger(0); // Action service not integrated + } + + public void onProcessCompleted(Long id, int exitCode) { + LOG.info("Process with Request Id: " + id + " exited with code: " + exitCode); + publishParameter(id.toString(), exitCode); + } + + private void registerActionAIStart(ActionDefinitionDetailsList actionDefs, IdentifierList actionNames) { + ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); + actionDefs.add(new ActionDefinitionDetails( + "Starts the AI inference using the AI service", + new UOctet((short) 0), + new UShort(TOTAL_STAGES), + arguments)); + actionNames.add(new Identifier(ACTION_START_AI)); + } + + private void registerActionAICancel(ActionDefinitionDetailsList actionDefs, IdentifierList actionNames) { + ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); + { + Byte rawType = Attribute._LONG_TYPE_SHORT_FORM; + arguments.add(new ArgumentDefinitionDetails( + new Identifier("process id"), + "process id", + rawType, "", null, null, null)); + } + + actionDefs.add(new ActionDefinitionDetails( + "Cancel the AI processing", + new UOctet((short) 0), + new UShort(1), + arguments)); + actionNames.add(new Identifier(ACTION_CANCEL_AI)); + } + + private void triggerAIInference(Long actionInstanceObjId, AttributeValueList attributeValues) { + /* + int minProcessingDurationSeconds = getAs(attributeValues.get(0)); + int maxProcessingDurationSeconds = getAs(attributeValues.get(1)); + + LOG.info("Requested to run the python script..."); + LOG.info("Process Min duration " + minProcessingDurationSeconds); + LOG.info("Process Max duration " + maxProcessingDurationSeconds); + LOG.info("Process Request Id " + actionInstanceObjId); + + PythonScriptExecutor exec = new PythonScriptExecutor(this, + actionInstanceObjId, minProcessingDurationSeconds, + maxProcessingDurationSeconds + ); + + exec.triggerAIInference(""); + + processMap.put(actionInstanceObjId, exec); + */ + } + + private void destroyProcess(AttributeValueList attributeValues) { + /* + Long processRequestId = getAs(attributeValues.get(0)); + LOG.info("Requested to destroy Process with Id: " + processRequestId); + + PythonScriptExecutor adapter = processMap.remove(processRequestId); + if (adapter != null) { + LOG.info("Killing process Process with Id: " + processRequestId); + adapter.destroyProcess(); + } else { + LOG.info("Process Request Id " + processRequestId + " not found"); + } + */ + } + + private void publishParameter(String id, int exitCode) { + try { + String str = "Process Request ID: " + id + " exitCode: " + exitCode; + connector.pushParameterValue(str, exitCode); + } catch (NMFException e) { + LOG.log(Level.SEVERE, "Failed to publish parameter", e); + } + } + + private static T getAs(AttributeValue attributeValue) { + if (attributeValue == null) { + return null; + } + return (T) attribute2JavaType(attributeValue.getValue()); + } + +} diff --git a/sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py b/sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py new file mode 100644 index 000000000..981251b7b --- /dev/null +++ b/sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py @@ -0,0 +1,8 @@ +import time + +def start_demo(): + for x in range(1, 6): + print ("Hello, World! Counter:",x) + time.sleep(1) + +start_demo() diff --git a/sdk/examples/space/pom.xml b/sdk/examples/space/pom.xml index 52ad1258b..1a2061439 100644 --- a/sdk/examples/space/pom.xml +++ b/sdk/examples/space/pom.xml @@ -72,6 +72,7 @@ camera camera-acquisitor-system echo + edge-ai gps hello-world-full hello-world-simple From 8e70bd0a61b6a2075875223541f5188c801b322f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 21 Apr 2022 13:52:05 +0200 Subject: [PATCH 053/173] [space2space] Code cleanup --- .../java/esa/mo/nmf/apps/DemoSpace2Space.java | 27 ++++++++++--------- .../esa/mo/nmf/apps/Space2SpaceAdapter.java | 4 +-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/DemoSpace2Space.java b/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/DemoSpace2Space.java index af7c4f6cd..2a677e1b0 100644 --- a/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/DemoSpace2Space.java +++ b/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/DemoSpace2Space.java @@ -22,33 +22,36 @@ import esa.mo.nmf.nanosatmoconnector.NanoSatMOConnectorImpl; import esa.mo.nmf.spacemoadapter.SpaceMOApdapterImpl; +import org.ccsds.moims.mo.mal.structures.URI; /** - * App connects to a GPS space app and logs the GPS parameter values that it receives. + * App connects to a GPS space app and logs the GPS parameter values that it + * receives. */ public class DemoSpace2Space { + /** + * Main command line entry point. + * + * @param args the command line arguments + * @throws java.lang.Exception If there is an error + */ + public static void main(final String[] args) throws Exception { + DemoSpace2Space demo = new DemoSpace2Space(); + } + public DemoSpace2Space() { Space2SpaceAdapter adapter = new Space2SpaceAdapter(); NanoSatMOConnectorImpl connector = new NanoSatMOConnectorImpl(); connector.init(adapter); // Initialize application's NMF consumer (consuming the supervisor) - SpaceMOApdapterImpl spaceAppSMA = SpaceMOApdapterImpl.forNMFApp(connector.readCentralDirectoryServiceURI(), - "gps"); + URI uri = connector.readCentralDirectoryServiceURI(); + SpaceMOApdapterImpl spaceAppSMA = SpaceMOApdapterImpl.forNMFApp(uri, "gps"); adapter.setConnector(connector); adapter.setSpaceAppSMA(spaceAppSMA); adapter.fetchGPSParameters(); } - /** - * Main command line entry point. - * - * @param args the command line arguments - * @throws java.lang.Exception If there is an error - */ - public static void main(final String[] args) throws Exception { - DemoSpace2Space demo = new DemoSpace2Space(); - } } diff --git a/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/Space2SpaceAdapter.java b/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/Space2SpaceAdapter.java index 2f44084d6..a7e9d2489 100644 --- a/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/Space2SpaceAdapter.java +++ b/sdk/examples/space/space-to-space/src/main/java/esa/mo/nmf/apps/Space2SpaceAdapter.java @@ -53,7 +53,7 @@ public void setConnector(NanoSatMOConnectorImpl connector) { this.connector.setCloseAppListener(new CloseAppListener() { @Override public Boolean onClose() { - return Space2SpaceAdapter.this.onClose(); + return closeApp(); } }); } @@ -94,7 +94,7 @@ public void onDataReceived(String parameterName, Serializable data) { LOGGER.log(Level.INFO, "Started fetching parameters"); } - public Boolean onClose() { + public Boolean closeApp() { boolean success = true; // Stop fetching data in supervisor try { From 48994ddc6ba29dde7b3f86577363267d87acba70 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 27 Apr 2022 18:06:03 +0200 Subject: [PATCH 054/173] [action service] Fixed submitAction bug... the action can now be passed to the backend with the correct name --- .../mo/mc/impl/provider/ActionManager.java | 7 +++---- .../esa/mo/mc/impl/provider/MCManager.java | 20 +++++++++++++++---- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionManager.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionManager.java index 3f92bdf3b..492a8786a 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionManager.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionManager.java @@ -370,7 +370,7 @@ public boolean checkActionInstanceDetails(ActionInstanceDetails actionInstance, protected void forward(final Long actionInstId, final ActionInstanceDetails actionDetails, final MALInteraction interaction, final SingleConnectionDetails connectionDetails) { //TODO: after issue I expect to get the identity-id here -> issue #179 - final Identifier name = getName(actionDetails.getDefInstId()); + final Identifier name = this.getNameFromObjId(actionDetails.getDefInstId()); actionsExecutor.execute(() -> { try { @@ -410,10 +410,9 @@ protected void forward(final Long actionInstId, final ActionInstanceDetails acti } protected void execute(final Long actionInstId, final ActionInstanceDetails actionDetails, - final MALInteraction interaction, final SingleConnectionDetails connectionDetails) { - + final MALInteraction interaction, final SingleConnectionDetails connectionDetails) { actionInstances.put(actionInstId, actionDetails); - final Identifier name = this.getName(actionDetails.getDefInstId()); + final Identifier name = this.getNameFromObjId(actionDetails.getDefInstId()); actionsExecutor.execute(() -> { final ActionDefinitionDetails actionDefinition = getActionDefinitionFromDefId(actionDetails.getDefInstId()); diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/MCManager.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/MCManager.java index 1daaf1c5f..6117c1ed5 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/MCManager.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/MCManager.java @@ -64,6 +64,7 @@ public abstract class MCManager { // Maps all existing Identity objects names that exists in the archive to their ID // Identity objects type for which names are stored depends on the implementation class (ParameterIdentity, ActionIdentity...) private HashMap storedNamesToIdMap; + private HashMap objIdToNameMap; private final EventProviderServiceImpl eventService; private final ArchiveProviderServiceImpl archiveService; @@ -72,10 +73,11 @@ public abstract class MCManager { private final GroupServiceImpl groupService = new GroupServiceImpl(); protected MCManager(COMServicesProvider comServices) { - this.identitiesToNamesMap = new HashMap<>(); this.namesToPairsMap = new HashMap<>(); this.objIdToDefMap = new HashMap<>(); + this.objIdToNameMap = new HashMap<>(); + this.storedNamesToIdMap = null; if (comServices != null) { @@ -160,6 +162,19 @@ public synchronized ObjectInstancePair getIdentityDefinition(Identifier name) { return this.namesToPairsMap.get(name); } + public synchronized Identifier getNameFromObjId(Long objId) { + Identifier out = objIdToNameMap.get(objId); + + if (out == null) { // Refresh if could not be found + for (Identifier name : namesToPairsMap.keySet()) { + objIdToNameMap.put(namesToPairsMap.get(name).getObjDefInstanceId(), name); + } + return objIdToNameMap.get(objId); + } + + return out; + } + /** * Gets the details of the definition with the given id. * @@ -167,9 +182,6 @@ public synchronized ObjectInstancePair getIdentityDefinition(Identifier name) { * @return the definition-details. Or Null if not found. */ public synchronized Element getDefinition(Long identityId) { - // This must be fast! - - // Needs further optimization... final Identifier name = this.identitiesToNamesMap.get(identityId); if (name == null) { From 38d2fbd945c35ecd6c5495f1f1b8d3964e88dc00 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 28 Apr 2022 11:42:46 +0200 Subject: [PATCH 055/173] [ai-service] Removed the weights path as the convention is to have the weights file, if exists, with the same name as the model with the difference that the file ending is .bin --- .../gen/ArtificialIntelligenceProviderServiceImpl.java | 2 +- .../src/main/resources/xml/ServiceDefPLATFORM.xml | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index 9bb1f6da9..b81a9c5e9 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -101,7 +101,7 @@ public void close() { } @Override - public Long setModel(String modelPath, String weightsPath, MALInteraction interaction) throws MALInteractionException, MALException { + public Long setModel(String modelPath, MALInteraction interaction) throws MALInteractionException, MALException { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index a1739a02e..c869f5a51 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2161,11 +2161,7 @@ - - - + comment="The modelPath field holds the absolute path to the file of the model." name="modelPath"> @@ -2189,13 +2185,13 @@ + comment="The inputTiles field holds the absolute path to a folder with the tiles to be processed." name="inputTilesPath"> + comment="The outputTiles field holds the absolute path to a folder with the infered tiles." name="outputTilesPath"> From 2bba257d4bed96902a6d695b9acf050a9ebd3034 Mon Sep 17 00:00:00 2001 From: CesarCoelho Date: Thu, 28 Apr 2022 13:27:53 +0200 Subject: [PATCH 056/173] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 542a96c5f..36220c785 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,10 @@ The latest NMF SDK release tag can be downloaded in [Releases]. However, the cur Prerequisites: -- Java SDK 1.8 or higher -- Apache Maven +1. Java SDK 1.8 (will work with higher JDKs but 1.8 is the recommended) + > In Linux: `sudo apt-get install openjdk-8-jdk` +2. Apache Maven + > In Linux: `sudo apt-get install maven` Instructions: From fce8f19ee335b0763423fd3717e22e4b3076244c Mon Sep 17 00:00:00 2001 From: CesarCoelho Date: Thu, 28 Apr 2022 18:26:55 +0200 Subject: [PATCH 057/173] Update README.md --- README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 36220c785..f3c5a3967 100644 --- a/README.md +++ b/README.md @@ -25,18 +25,28 @@ The latest NMF SDK release tag can be downloaded in [Releases]. However, the cur Prerequisites: -1. Java SDK 1.8 (will work with higher JDKs but 1.8 is the recommended) - > In Linux: `sudo apt-get install openjdk-8-jdk` +1. Java SDK 1.8 (will work with higher SDKs but 1.8 is the recommended) +```bash +sudo apt-get install openjdk-8-jdk +``` 2. Apache Maven - > In Linux: `sudo apt-get install maven` +```bash +sudo apt-get install maven +``` Instructions: 1. Clone this repository 2. Set the environment variable NMF\_HOME with the path to this repository's root directory - -3. Run in the root directory: `mvn install` +```bash +export NMF_HOME=path_to_repository +``` + +3. Run in the root directory: +```bash +mvn install +``` Note that the errors about missing module descriptors during Javadoc generation are to be expected and non breaking. From 8faf0df29389e2c8ad590c237ce45ec09d732e7c Mon Sep 17 00:00:00 2001 From: CesarCoelho Date: Fri, 29 Apr 2022 16:13:24 +0200 Subject: [PATCH 058/173] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f3c5a3967..7d60acbca 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,9 @@ Or directly in the respective source code repository. ## License -The NanoSat MO Framework is **licensed** under the **[European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4]**. +The NanoSat MO Framework is **licensed** under: + +**[European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4]**. [![][ESAImage]][website] From 5c0096c73e6be8b871797b8d4a2a1e38fa85e3b3 Mon Sep 17 00:00:00 2001 From: CesarCoelho Date: Tue, 17 May 2022 10:24:00 +0200 Subject: [PATCH 059/173] [xml] Added better description for doInference --- .../src/main/resources/xml/ServiceDefPLATFORM.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index c869f5a51..f3084bbc2 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2161,7 +2161,7 @@ + comment="The modelPath field holds the absolute path to the file of the model. If there is also an associated weights file, then its path and filename shall be the same as the model with the only difference being the file extension (from .xml to .bin)." name="modelPath"> From 200af5b93f85b095d92b66d69e859f82a5f4ef8a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 29 Apr 2022 21:22:36 +0200 Subject: [PATCH 060/173] [nmf package] Added default maxHeap to 128m --- .../java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java | 2 +- .../main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 9546c0e88..290daab7a 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -96,7 +96,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I if (line.startsWith(line)) { maxHeap = line.substring(MAXHEAP.length()); } else { - throw new IOException("Could not read the package mainJar!"); + throw new IOException("Could not read the package maxHeap!"); } final NMFPackageDetails details = new NMFPackageDetails(name, diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 06d61249b..f247198ad 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -68,7 +68,7 @@ public class GenerateNMFPackageMojo extends AbstractMojo { @Parameter(property = "generate-nmf-package.nmfVersion", defaultValue = "${esa.nmf.version-qualifier}") private String nmfVersion; - @Parameter(property = "generate-nmf-package.maxHeap") + @Parameter(property = "generate-nmf-package.maxHeap", defaultValue = "128m") private String maxHeap; /** From a94a21f54797608fd59cd5d7d58d64bef453bc3b Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 17 May 2022 10:34:14 +0200 Subject: [PATCH 061/173] [edge-ai] Added method call to AI service --- .../java/esa/mo/nmf/apps/edgeai/MCAdapter.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java index 43b16b21a..bbc134f15 100644 --- a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java @@ -41,6 +41,10 @@ import esa.mo.nmf.NMFException; import esa.mo.nmf.NMFInterface; import esa.mo.nmf.NMFProvider; +import java.io.IOException; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.platform.artificialintelligence.consumer.ArtificialIntelligenceStub; /** * The adapter for the NMF App @@ -77,7 +81,6 @@ public void initialRegistrations(MCRegistration registration) { @Override public UInteger actionArrived(Identifier name, AttributeValueList attributeValues, Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { - if (ACTION_START_AI.equals(name.getValue())) { triggerAIInference(actionInstanceObjId, attributeValues); return null; // Success! @@ -141,6 +144,17 @@ private void triggerAIInference(Long actionInstanceObjId, AttributeValueList att processMap.put(actionInstanceObjId, exec); */ + + try { + String modelPath = ""; + String inputTilesPath = ""; + + ArtificialIntelligenceStub aiService = connector.getPlatformServices().getAIService(); + Long id = aiService.setModel(modelPath); + aiService.doInference(id, inputTilesPath); + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + LOG.log(Level.SEVERE, "AI was not performed...", ex); + } } private void destroyProcess(AttributeValueList attributeValues) { From 5a901e24aa2514abdd430c403fcc10b49aedaaa7 Mon Sep 17 00:00:00 2001 From: CesarCoelho Date: Thu, 26 May 2022 10:04:00 +0200 Subject: [PATCH 062/173] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d60acbca..c48e6c535 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Instructions: export NMF_HOME=path_to_repository ``` -3. Run in the root directory: +3. Compile the NMF using: ```bash mvn install ``` From fc6ba0dc78aba86415e70afa1ea4efd1ad4ddb3c Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 27 May 2022 12:04:28 +0200 Subject: [PATCH 063/173] Refactoring & AI service WIP code --- .../esa/mo/helpertools/misc}/OSValidator.java | 3 +- .../mo/helpertools/misc}/ShellCommander.java | 2 +- ...icialIntelligenceIntelMovidiusAdapter.java | 155 +++ ...rtificialIntelligenceAdapterInterface.java | 5 +- ...ficialIntelligenceProviderServiceImpl.java | 50 +- .../impl/provider/gen/GPSNMEAonlyAdapter.java | 1 + .../sm/impl/provider/AppsLauncherManager.java | 2 +- .../CommandExecutorProviderServiceImpl.java | 2 +- .../java/esa/nmf/test/RegressionTest0.java | 1037 ++++++++--------- .../MCSupervisorBasicAdapter.java | 4 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 2 +- .../util/PlatformServicesProviderSoftSim.java | 100 +- 12 files changed, 769 insertions(+), 594 deletions(-) rename core/{mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util => helper-tools/src/main/java/esa/mo/helpertools/misc}/OSValidator.java (95%) rename core/{mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util => helper-tools/src/main/java/esa/mo/helpertools/misc}/ShellCommander.java (99%) create mode 100644 core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java similarity index 95% rename from core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java rename to core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java index 6161394b2..a2c5d6e62 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/OSValidator.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java @@ -18,9 +18,10 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.sm.impl.util; +package esa.mo.helpertools.misc; /** + * The OSValidator allows easy determination of the current OS. * * @author Cesar Coelho */ diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java similarity index 99% rename from core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java rename to core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java index 48116d7f2..63004da0f 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ShellCommander.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java @@ -18,7 +18,7 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.sm.impl.util; +package esa.mo.helpertools.misc; import java.io.BufferedReader; import java.io.File; diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java new file mode 100644 index 000000000..ead1ffe5d --- /dev/null +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021 Cesar Coelho + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +package esa.mo.platform.impl.provider.adapters; + +import esa.mo.helpertools.misc.OSValidator; +import esa.mo.helpertools.misc.ShellCommander; +import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceAdapterInterface; +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * The Artificial Intelligence adapter for the Intel Movidius Neural Compute + * Stick via a python script. + * + * @author Cesar Coelho + */ +public class ArtificialIntelligenceIntelMovidiusAdapter implements ArtificialIntelligenceAdapterInterface { + + private static final Logger LOGGER = Logger.getLogger(ArtificialIntelligenceIntelMovidiusAdapter.class.getName()); + private final File setupVarsPath; + + public ArtificialIntelligenceIntelMovidiusAdapter() throws IOException { + // Check if Python3 is installed! + ShellCommander shellCommander = new ShellCommander(); + String cmdPython = "python3 --version"; + String out = shellCommander.runCommandAndGetOutputMessage(cmdPython); + String[] splits = out.split("Python "); + + if (splits.length == 0) { + throw new IOException("The Python version could not be determined!" + + " The command returned: " + out); + } + + LOGGER.log(Level.INFO, "The Python3 version is: " + splits[1]); + String[] subVersions = splits[1].split("\\."); + + if (Integer.valueOf(subVersions[1]) < 6) { + throw new IOException("The installed python3 version is < 3.6.0!" + + "\n>>>> Please update your Python version!"); + } + + OSValidator os = new OSValidator(); + + // Is it Linux or Windows? + if (os.isUnix()) { + // Find the folder where the Intel Movidius software is installed + String[] options = { + "/opt/intel" + }; + + setupVarsPath = this.crawlOptions(options, "setupvars.sh"); + return; + } + + if (os.isWindows()) { + // Find the folder where the Intel Movidius software is installed + String[] options = { + "C:\\Program Files (x86)\\Intel", + "C:\\Program Files (x86)\\IntelSWTools", + "C:\\Program Files\\Intel", + "C:\\Program Files\\IntelSWTools" + }; + + setupVarsPath = this.crawlOptions(options, "setupvars.bat"); + + // Please install version: 2020.3 + return; + } + + throw new IOException("The current OS is not supported: " + os.getOS()); + } + + private File crawlOptions(String[] options, String filename) throws IOException { + for (String option : options) { + File folder = new File(option); + File path = this.findPathToFile(folder, filename); + + if (path != null) { // Found! + LOGGER.log(Level.INFO, "The file was found on path:\n" + + " >> " + path.getAbsolutePath()); + return path; + } + } + + throw new IOException("The file " + filename + " was not found!"); + } + + private File findPathToFile(File path, String toBeMatched) { + if (path.isFile()) { + return toBeMatched.equals(path.getName()) ? path : null; + } + + // It is a directory... crawl through it + for (File entry : path.listFiles()) { + File file = findPathToFile(entry, toBeMatched); + if (file != null) { + return file; + } + } + + return null; + } + + @Override + public void setModel(String modelPath, String weightsPath) throws IOException { + + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void executeInference(String inputPath, String outputPath) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + public String generateScriptSH(String pathIntelVar, String pythonFile) { + StringBuilder str = new StringBuilder(); + str.append("#!/bin/bash \n\n"); + str.append("source ").append(pathIntelVar); + str.append("\n\n"); + str.append("python3 ").append(pythonFile); + return str.toString(); + } + + public String generateScriptBAT(String pathIntelVar, String pythonFile) { + StringBuilder str = new StringBuilder(); + str.append(pathIntelVar); + str.append("\n\n"); + str.append(pythonFile); + return str.toString(); + } + +} diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java index 2ae60743f..4937b2252 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java @@ -36,9 +36,10 @@ public interface ArtificialIntelligenceAdapterInterface { /** * Executes the inference on the Artificial Intelligence device. * - * @param path The file path to a folder with a set of files to be + * @param inputPath The path to a folder with a set of files to be * processed. + * @param outputPath The path to a folder to store the processed files. */ - public void executeInference(String path); + public void executeInference(String inputPath, String outputPath); } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index b81a9c5e9..cf1c99404 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -33,6 +33,8 @@ import org.ccsds.moims.mo.platform.artificialintelligence.ArtificialIntelligenceHelper; import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; import esa.mo.helpertools.connections.ConnectionProvider; +import java.io.IOException; +import java.util.ArrayList; public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelligenceInheritanceSkeleton { @@ -41,6 +43,8 @@ public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelli private boolean initialiased = false; private final ConnectionProvider connection = new ConnectionProvider(); private ArtificialIntelligenceAdapterInterface adapter; + private final static Long TIMESTAMP = System.currentTimeMillis(); + private final ArrayList modelPaths = new ArrayList(); /** * creates the MAL objects, the publisher used to create updates and starts @@ -102,11 +106,51 @@ public void close() { @Override public Long setModel(String modelPath, MALInteraction interaction) throws MALInteractionException, MALException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + if (modelPath == null) { + throw new MALException("The modelPath is null!"); + } + + for (String path : modelPaths) { + if (path.equals(modelPath)) { + throw new MALException("The model already exists!"); + } + } + + modelPaths.add(modelPath); + return TIMESTAMP + modelPaths.indexOf(modelPath); } @Override - public String doInference(Long modelId, String inputTilesPath, MALInteraction interaction) throws MALInteractionException, MALException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public String doInference(Long modelId, String inputTilesPath, + MALInteraction interaction) throws MALInteractionException, MALException { + if (modelId == null) { + throw new MALException("The modelId is null!"); + } + + if (inputTilesPath == null) { + throw new MALException("The inputTilesPath is null!"); + } + + String modelPath = modelPaths.get((int) (modelId - TIMESTAMP)); + + if (!modelPath.endsWith(".xml")) { + throw new MALException("The model does not end with the file extension: .xml"); + } + + String weightsPath = modelPath.substring(0, modelPath.length() - 4) + ".bin"; + Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( + Level.INFO, "The weights file path is:\n >> " + weightsPath); + + try { + adapter.setModel(modelPath, weightsPath); + String outputTilesPath = ""; + adapter.executeInference(inputTilesPath, outputTilesPath); + return outputTilesPath; + } catch (IOException ex) { + Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( + Level.SEVERE, "The inference could not be performed!", ex); + } + + throw new MALException("The inference could not be performed!"); } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java index 2a8a7e268..bdff893bb 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java @@ -21,6 +21,7 @@ package esa.mo.platform.impl.provider.gen; import esa.mo.helpertools.misc.Const; +import esa.mo.platform.impl.provider.gen.GPSAdapterInterface; import esa.mo.platform.impl.util.HelperGPS; import java.io.IOException; import java.util.logging.Level; diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index afaca5cda..cf9c8ba23 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -31,7 +31,7 @@ import esa.mo.helpertools.connections.SingleConnectionDetails; import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.misc.Const; -import esa.mo.sm.impl.util.OSValidator; +import esa.mo.helpertools.misc.OSValidator; import java.io.File; import java.io.FileInputStream; import java.io.IOException; diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java index 7fbc097f6..9906f34fe 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java @@ -26,7 +26,7 @@ import esa.mo.com.impl.util.HelperArchive; import esa.mo.helpertools.connections.ConfigurationProviderSingleton; import esa.mo.helpertools.connections.ConnectionProvider; -import esa.mo.sm.impl.util.OSValidator; +import esa.mo.helpertools.misc.OSValidator; import java.io.File; import java.io.IOException; import java.nio.file.Paths; diff --git a/core/mo-services-impl/nmf-software-management-impl/src/test/java/esa/nmf/test/RegressionTest0.java b/core/mo-services-impl/nmf-software-management-impl/src/test/java/esa/nmf/test/RegressionTest0.java index 9ba841b40..5bed91c6f 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/test/java/esa/nmf/test/RegressionTest0.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/test/java/esa/nmf/test/RegressionTest0.java @@ -99,7 +99,7 @@ public void test007() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -136,7 +136,7 @@ public void test008() throws Throwable { public void test009() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test009"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isSolaris(); @@ -167,7 +167,7 @@ public void test010() throws Throwable { public void test011() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test011"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isMac(); @@ -182,7 +182,7 @@ public void test011() throws Throwable { public void test012() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test012"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("[]"); @@ -210,7 +210,7 @@ public void test013() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); int int22 = floatList4.size(); @@ -256,7 +256,7 @@ public void test014() throws Throwable { public void test015() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test015"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -307,7 +307,7 @@ public void test017() throws Throwable { public void test018() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test018"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage(""); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("281474993487887"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("[10, -1, -1, 10, 1]"); @@ -528,7 +528,7 @@ public void test021() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); org.ccsds.moims.mo.mal.structures.UShort uShort21 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -581,7 +581,7 @@ public void test022() throws Throwable { java.util.Spliterator uShortSpliterator23 = uShortList20 .spliterator(); int int24 = shortList14.lastIndexOf((java.lang.Object) uShortList20); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("hi!"); boolean boolean28 = uShortList20.contains((java.lang.Object) str27); org.ccsds.moims.mo.mal.structures.UShort uShort30 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -620,7 +620,7 @@ public void test023() throws Throwable { (java.lang.Float) 100.0f); org.ccsds.moims.mo.mal.structures.UOctet uOctet2 = union1.getAreaVersion(); java.lang.Long long3 = union1.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator4 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator4 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str5 = oSValidator4.getOS(); boolean boolean6 = oSValidator4.isMac(); boolean boolean7 = oSValidator4.isMac(); @@ -642,7 +642,7 @@ public void test024() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -670,7 +670,7 @@ public void test025() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -713,7 +713,7 @@ public void test026() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); java.util.Spliterator uShortSpliterator20 = uShortList11 @@ -762,7 +762,7 @@ public void test027() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -811,7 +811,7 @@ public void test028() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -845,14 +845,13 @@ public void test029() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test029"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); java.lang.Long long8 = processExecutionHandler2.getObjId(); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str11 = shellCommander9.runCommandAndGetOutputMessage("[true]"); java.lang.String str13 = shellCommander9.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process15 = shellCommander9.runCommand(""); @@ -986,7 +985,7 @@ public void test030() throws Throwable { public void test031() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test031"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -1001,7 +1000,7 @@ public void test031() throws Throwable { public void test032() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test032"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isSolaris(); boolean boolean2 = oSValidator0.isUnix(); org.junit.Assert.assertTrue("'" + boolean1 + "' != '" + false + "'", !boolean1); @@ -1027,7 +1026,7 @@ public void test033() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("[true]"); @@ -1179,7 +1178,7 @@ public void test036() throws Throwable { floatList73.ensureCapacity((-11)); int int90 = booleanList26.indexOf((java.lang.Object) floatList73); boolean boolean91 = uRIList15.remove((java.lang.Object) int90); - esa.mo.sm.impl.util.OSValidator oSValidator92 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator92 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean93 = oSValidator92.isMac(); boolean boolean94 = oSValidator92.isWindows(); java.lang.String str95 = oSValidator92.getOS(); @@ -1257,7 +1256,7 @@ public void test036() throws Throwable { public void test037() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test037"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -1397,7 +1396,7 @@ public void test040() throws Throwable { java.lang.Long long61 = octetList59.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element62 = octetList59.createElement(); octetList59.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator64 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator64 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean65 = oSValidator64.isMac(); boolean boolean66 = oSValidator64.isMac(); int int67 = octetList59.lastIndexOf((java.lang.Object) oSValidator64); @@ -1492,7 +1491,7 @@ public void test042() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -1570,7 +1569,7 @@ public void test043() throws Throwable { public void test044() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test044"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -1647,7 +1646,7 @@ public void test045() throws Throwable { public void test046() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test046"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); java.lang.String str3 = oSValidator0.getOS(); @@ -1686,7 +1685,7 @@ public void test047() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -1718,7 +1717,7 @@ public void test047() throws Throwable { public void test048() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test048"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -1752,7 +1751,7 @@ public void test049() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); org.ccsds.moims.mo.mal.structures.UShort uShort21 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -1813,7 +1812,7 @@ public void test050() throws Throwable { java.util.stream.Stream uRIStream23 = uRIList20.stream(); boolean boolean24 = uRIList20.isEmpty(); int int25 = intList11.indexOf((java.lang.Object) boolean24); - esa.mo.sm.impl.util.ShellCommander shellCommander26 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander26 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process28 = shellCommander26.runCommand("[]"); boolean boolean29 = intList11.equals((java.lang.Object) shellCommander26); java.lang.String str31 = shellCommander26.runCommandAndGetOutputMessage("[10, -1, -1, 10]"); @@ -1984,7 +1983,7 @@ public void test052() throws Throwable { public void test053() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test053"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("7.0"); org.junit.Assert.assertTrue("'" + str2 + "' != '" + "" + "'", str2.equals("")); @@ -2049,7 +2048,7 @@ public void test055() throws Throwable { java.util.ListIterator doubleItor13 = doubleList5.listIterator((int) (short) 1); doubleList5.ensureCapacity((int) (byte) 1); doubleList5.trimToSize(); - esa.mo.sm.impl.util.ShellCommander shellCommander17 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander17 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str19 = shellCommander17.runCommandAndGetOutputMessage("hi!"); boolean boolean20 = doubleList5.contains((java.lang.Object) "hi!"); java.util.Iterator doubleItor21 = doubleList5.iterator(); @@ -2069,14 +2068,13 @@ public void test056() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test056"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); processExecutionHandler2.close(); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str11 = shellCommander9.runCommandAndGetOutputMessage(""); java.lang.Process process13 = shellCommander9.runCommand("281474993487879"); processExecutionHandler2.monitorProcess(process13); @@ -2251,7 +2249,7 @@ public void test058() throws Throwable { java.lang.Long long37 = octetList35.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element38 = octetList35.createElement(); octetList35.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator40 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator40 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean41 = oSValidator40.isMac(); boolean boolean42 = oSValidator40.isMac(); int int43 = octetList35.lastIndexOf((java.lang.Object) oSValidator40); @@ -2404,16 +2402,14 @@ public void test060() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test060"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks8 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler10 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks8, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander11 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler10 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks8, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander11 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process13 = shellCommander11.runCommand("[281475010265083]"); processExecutionHandler10.monitorProcess(process13); java.lang.Process process15 = processExecutionHandler10.getProcess(); @@ -2626,18 +2622,16 @@ public void test063() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test063"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); java.lang.Long long8 = processExecutionHandler2.getObjId(); java.lang.Process process9 = processExecutionHandler2.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks10 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks10, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks10, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process15 = shellCommander13.runCommand("[281475010265083]"); processExecutionHandler12.monitorProcess(process15); java.lang.Process process17 = processExecutionHandler12.getProcess(); @@ -2768,7 +2762,7 @@ public void test064() throws Throwable { public void test065() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test065"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isMac(); @@ -2868,7 +2862,7 @@ public void test067() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -2896,7 +2890,7 @@ public void test067() throws Throwable { public void test068() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test068"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isSolaris(); @@ -2915,7 +2909,7 @@ public void test069() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -2946,24 +2940,22 @@ public void test070() throws Throwable { org.ccsds.moims.mo.mal.structures.UShortList uShortList0 = new org.ccsds.moims.mo.mal.structures.UShortList(); org.ccsds.moims.mo.mal.structures.UShort uShort1 = uShortList0.getAreaNumber(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks2 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks2, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander5 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks2, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander5 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process7 = shellCommander5.runCommand("[281475010265083]"); processExecutionHandler4.monitorProcess(process7); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process11 = shellCommander9.runCommand("[]"); processExecutionHandler4.monitorProcess(process11); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks13 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks13, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks13, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[281475010265083]"); processExecutionHandler15.monitorProcess(process18); - esa.mo.sm.impl.util.ShellCommander shellCommander20 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander20 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str22 = shellCommander20.runCommandAndGetOutputMessage("[true]"); java.lang.Process process24 = shellCommander20.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("[true]"); java.lang.Process process29 = shellCommander25.runCommand("[10, -1, -1, 10]"); java.lang.Process[] processArray30 = new java.lang.Process[]{process11, process18, process24, process29}; @@ -3055,7 +3047,7 @@ public void test071() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -3119,24 +3111,22 @@ public void test072() throws Throwable { org.ccsds.moims.mo.mal.structures.UShortList uShortList0 = new org.ccsds.moims.mo.mal.structures.UShortList(); org.ccsds.moims.mo.mal.structures.UShort uShort1 = uShortList0.getAreaNumber(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks2 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks2, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander5 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks2, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander5 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process7 = shellCommander5.runCommand("[281475010265083]"); processExecutionHandler4.monitorProcess(process7); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process11 = shellCommander9.runCommand("[]"); processExecutionHandler4.monitorProcess(process11); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks13 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks13, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks13, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[281475010265083]"); processExecutionHandler15.monitorProcess(process18); - esa.mo.sm.impl.util.ShellCommander shellCommander20 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander20 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str22 = shellCommander20.runCommandAndGetOutputMessage("[true]"); java.lang.Process process24 = shellCommander20.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("[true]"); java.lang.Process process29 = shellCommander25.runCommand("[10, -1, -1, 10]"); java.lang.Process[] processArray30 = new java.lang.Process[]{process11, process18, process24, process29}; @@ -3191,7 +3181,7 @@ public void test073() throws Throwable { java.lang.Long long30 = octetList28.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element31 = octetList28.createElement(); octetList28.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator33 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator33 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean34 = oSValidator33.isMac(); boolean boolean35 = oSValidator33.isMac(); int int36 = octetList28.lastIndexOf((java.lang.Object) oSValidator33); @@ -3393,7 +3383,7 @@ public void test079() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -3444,24 +3434,22 @@ public void test081() throws Throwable { org.ccsds.moims.mo.mal.structures.UShortList uShortList0 = new org.ccsds.moims.mo.mal.structures.UShortList(); org.ccsds.moims.mo.mal.structures.UShort uShort1 = uShortList0.getAreaNumber(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks2 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks2, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander5 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks2, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander5 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process7 = shellCommander5.runCommand("[281475010265083]"); processExecutionHandler4.monitorProcess(process7); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process11 = shellCommander9.runCommand("[]"); processExecutionHandler4.monitorProcess(process11); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks13 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks13, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks13, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[281475010265083]"); processExecutionHandler15.monitorProcess(process18); - esa.mo.sm.impl.util.ShellCommander shellCommander20 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander20 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str22 = shellCommander20.runCommandAndGetOutputMessage("[true]"); java.lang.Process process24 = shellCommander20.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("[true]"); java.lang.Process process29 = shellCommander25.runCommand("[10, -1, -1, 10]"); java.lang.Process[] processArray30 = new java.lang.Process[]{process11, process18, process24, process29}; @@ -3557,7 +3545,7 @@ public void test082() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -3621,9 +3609,8 @@ public void test083() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test083"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -3707,13 +3694,13 @@ public void test084() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); boolean boolean66 = shortList6.remove((java.lang.Object) oSValidator62); boolean boolean68 = shortList6.add((java.lang.Short) (short) 0); - esa.mo.sm.impl.util.OSValidator oSValidator69 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator69 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str70 = oSValidator69.getOS(); int int71 = shortList6.indexOf((java.lang.Object) str70); org.junit.Assert.assertNotNull(shortArray5); @@ -3908,7 +3895,7 @@ public void test087() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -3955,7 +3942,7 @@ public void test088() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -4051,7 +4038,7 @@ public void test089() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -4133,7 +4120,7 @@ public void test090() throws Throwable { public void test091() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test091"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); java.lang.String str3 = oSValidator0.getOS(); @@ -4199,7 +4186,7 @@ public void test093() throws Throwable { public void test094() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test094"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage(""); java.lang.Process process4 = shellCommander0.runCommand("281474993487879"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage(""); @@ -4214,7 +4201,7 @@ public void test094() throws Throwable { public void test095() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test095"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.Process process4 = shellCommander0.runCommand("[false]"); org.junit.Assert.assertTrue("'" + str2 + "' != '" + "" + "'", str2.equals("")); @@ -4292,7 +4279,7 @@ public void test096() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -4374,7 +4361,7 @@ public void test097() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); int int22 = floatList4.size(); @@ -4449,24 +4436,22 @@ public void test098() throws Throwable { org.ccsds.moims.mo.mal.structures.UShortList uShortList48 = new org.ccsds.moims.mo.mal.structures.UShortList(); org.ccsds.moims.mo.mal.structures.UShort uShort49 = uShortList48.getAreaNumber(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks50 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler52 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks50, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander53 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler52 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks50, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander53 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process55 = shellCommander53.runCommand("[281475010265083]"); processExecutionHandler52.monitorProcess(process55); - esa.mo.sm.impl.util.ShellCommander shellCommander57 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander57 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process59 = shellCommander57.runCommand("[]"); processExecutionHandler52.monitorProcess(process59); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks61 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler63 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks61, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander64 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler63 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks61, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander64 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process66 = shellCommander64.runCommand("[281475010265083]"); processExecutionHandler63.monitorProcess(process66); - esa.mo.sm.impl.util.ShellCommander shellCommander68 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander68 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str70 = shellCommander68.runCommandAndGetOutputMessage("[true]"); java.lang.Process process72 = shellCommander68.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander73 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander73 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str75 = shellCommander73.runCommandAndGetOutputMessage("[true]"); java.lang.Process process77 = shellCommander73.runCommand("[10, -1, -1, 10]"); java.lang.Process[] processArray78 = new java.lang.Process[]{process59, process66, process72, process77}; @@ -4552,7 +4537,7 @@ public void test100() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -4598,7 +4583,7 @@ public void test101() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); int int22 = floatList4.size(); @@ -4694,7 +4679,7 @@ public void test101() throws Throwable { public void test102() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test102"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -4787,7 +4772,7 @@ public void test103() throws Throwable { java.util.stream.Stream uRIStream76 = uRIList73.stream(); boolean boolean77 = uRIList73.isEmpty(); int int78 = intList64.indexOf((java.lang.Object) boolean77); - esa.mo.sm.impl.util.ShellCommander shellCommander79 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander79 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process81 = shellCommander79.runCommand("[]"); boolean boolean82 = intList64.equals((java.lang.Object) shellCommander79); intList64.add((int) (byte) 10, (java.lang.Integer) 0); @@ -4930,7 +4915,7 @@ public void test105() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -5176,7 +5161,7 @@ public void test107() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("-1"); @@ -5401,9 +5386,8 @@ public void test110() throws Throwable { java.lang.Process process20 = processExecutionHandler19.getProcess(); java.lang.Long long21 = processExecutionHandler19.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks22 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler24 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks22, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler24 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks22, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process27 = shellCommander25.runCommand("[281475010265083]"); processExecutionHandler24.monitorProcess(process27); processExecutionHandler19.monitorProcess(process27); @@ -5450,7 +5434,7 @@ public void test111() throws Throwable { public void test112() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test112"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isMac(); @@ -5465,7 +5449,7 @@ public void test112() throws Throwable { public void test113() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test113"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -5504,9 +5488,8 @@ public void test114() throws Throwable { java.lang.Double double21 = doubleList11.remove(3); doubleList11.ensureCapacity((int) '4'); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks24 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler26 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks24, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander27 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler26 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks24, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander27 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process29 = shellCommander27.runCommand("[281475010265083]"); processExecutionHandler26.monitorProcess(process29); java.lang.Process process31 = processExecutionHandler26.getProcess(); @@ -5565,7 +5548,7 @@ public void test116() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -5734,7 +5717,7 @@ public void test118() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -5956,7 +5939,7 @@ public void test120() throws Throwable { public void test121() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test121"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -6007,7 +5990,7 @@ public void test122() throws Throwable { java.lang.Long long30 = octetList28.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element31 = octetList28.createElement(); octetList28.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator33 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator33 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean34 = oSValidator33.isMac(); boolean boolean35 = oSValidator33.isMac(); int int36 = octetList28.lastIndexOf((java.lang.Object) oSValidator33); @@ -6040,7 +6023,7 @@ public void test122() throws Throwable { public void test123() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test123"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isMac(); @@ -6180,7 +6163,7 @@ public void test126() throws Throwable { java.util.stream.Stream uRIStream23 = uRIList20.stream(); boolean boolean24 = uRIList20.isEmpty(); int int25 = intList11.indexOf((java.lang.Object) boolean24); - esa.mo.sm.impl.util.ShellCommander shellCommander26 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander26 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process28 = shellCommander26.runCommand("[]"); boolean boolean29 = intList11.equals((java.lang.Object) shellCommander26); java.lang.String str31 = shellCommander26.runCommandAndGetOutputMessage("[-1, -1, 10]"); @@ -6207,7 +6190,7 @@ public void test126() throws Throwable { public void test127() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test127"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process6 = shellCommander0.runCommand(""); @@ -6225,24 +6208,22 @@ public void test128() throws Throwable { org.ccsds.moims.mo.mal.structures.UShortList uShortList0 = new org.ccsds.moims.mo.mal.structures.UShortList(); org.ccsds.moims.mo.mal.structures.UShort uShort1 = uShortList0.getAreaNumber(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks2 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks2, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander5 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks2, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander5 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process7 = shellCommander5.runCommand("[281475010265083]"); processExecutionHandler4.monitorProcess(process7); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process11 = shellCommander9.runCommand("[]"); processExecutionHandler4.monitorProcess(process11); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks13 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks13, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks13, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[281475010265083]"); processExecutionHandler15.monitorProcess(process18); - esa.mo.sm.impl.util.ShellCommander shellCommander20 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander20 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str22 = shellCommander20.runCommandAndGetOutputMessage("[true]"); java.lang.Process process24 = shellCommander20.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("[true]"); java.lang.Process process29 = shellCommander25.runCommand("[10, -1, -1, 10]"); java.lang.Process[] processArray30 = new java.lang.Process[]{process11, process18, process24, process29}; @@ -6286,7 +6267,7 @@ public void test129() throws Throwable { public void test130() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test130"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isUnix(); @@ -6478,7 +6459,7 @@ public void test133() throws Throwable { java.util.stream.Stream uRIStream66 = uRIList63.stream(); boolean boolean67 = uRIList63.isEmpty(); int int68 = intList54.indexOf((java.lang.Object) boolean67); - esa.mo.sm.impl.util.ShellCommander shellCommander69 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander69 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process71 = shellCommander69.runCommand("[]"); boolean boolean72 = intList54.equals((java.lang.Object) shellCommander69); int int73 = doubleList42.indexOf((java.lang.Object) intList54); @@ -6566,7 +6547,7 @@ public void test134() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -6610,17 +6591,15 @@ public void test135() throws Throwable { java.lang.Process process8 = processExecutionHandler7.getProcess(); java.lang.Long long9 = processExecutionHandler7.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks10 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks10, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks10, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process15 = shellCommander13.runCommand("[281475010265083]"); processExecutionHandler12.monitorProcess(process15); processExecutionHandler7.monitorProcess(process15); processExecutionHandler2.monitorProcess(process15); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks19 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler21 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks19, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander22 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler21 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks19, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander22 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process24 = shellCommander22.runCommand("[281475010265083]"); processExecutionHandler21.monitorProcess(process24); java.lang.Process process26 = processExecutionHandler21.getProcess(); @@ -6747,7 +6726,7 @@ public void test139() throws Throwable { public void test140() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test140"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isMac(); @@ -6975,7 +6954,7 @@ public void test142() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -7033,9 +7012,8 @@ public void test143() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test143"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -7181,10 +7159,10 @@ public void test146() throws Throwable { boolean boolean10 = uInteger3.equals((java.lang.Object) uShortList4); boolean boolean11 = uShortList4.isEmpty(); java.util.ListIterator uShortItor12 = uShortList4.listIterator(); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str15 = shellCommander13.runCommandAndGetOutputMessage("[true]"); java.lang.Process process17 = shellCommander13.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str20 = shellCommander18.runCommandAndGetOutputMessage("[true]"); java.lang.Process process22 = shellCommander18.runCommand("[10, -1, -1, 10]"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks23 = null; @@ -7193,9 +7171,8 @@ public void test146() throws Throwable { java.lang.Process process26 = processExecutionHandler25.getProcess(); java.lang.Long long27 = processExecutionHandler25.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks28 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler30 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks28, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander31 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler30 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks28, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander31 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process33 = shellCommander31.runCommand("[281475010265083]"); processExecutionHandler30.monitorProcess(process33); processExecutionHandler25.monitorProcess(process33); @@ -7205,9 +7182,8 @@ public void test146() throws Throwable { java.lang.Process process39 = processExecutionHandler38.getProcess(); java.lang.Long long40 = processExecutionHandler38.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks41 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler43 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks41, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander44 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler43 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks41, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander44 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process46 = shellCommander44.runCommand("[281475010265083]"); processExecutionHandler43.monitorProcess(process46); processExecutionHandler38.monitorProcess(process46); @@ -7263,7 +7239,7 @@ public void test147() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -7299,12 +7275,11 @@ public void test148() throws Throwable { booleanList2.trimToSize(); boolean boolean9 = booleanList2.add((java.lang.Boolean) true); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks10 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks10, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks10, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process15 = shellCommander13.runCommand("[281475010265083]"); processExecutionHandler12.monitorProcess(process15); - esa.mo.sm.impl.util.ShellCommander shellCommander17 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander17 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process19 = shellCommander17.runCommand("[]"); processExecutionHandler12.monitorProcess(process19); java.lang.Process process21 = processExecutionHandler12.getProcess(); @@ -7702,7 +7677,7 @@ public void test153() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -7771,7 +7746,7 @@ public void test154() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -7810,7 +7785,7 @@ public void test155() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -7842,7 +7817,7 @@ public void test155() throws Throwable { public void test156() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test156"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -7899,9 +7874,8 @@ public void test158() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test158"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -7910,7 +7884,7 @@ public void test158() throws Throwable { callbacks8, (java.lang.Long) 281474993487875L); java.lang.Long long11 = processExecutionHandler10.getObjId(); java.lang.Process process12 = processExecutionHandler10.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str15 = shellCommander13.runCommandAndGetOutputMessage("hi!"); java.lang.Process process17 = shellCommander13.runCommand("17"); processExecutionHandler10.monitorProcess(process17); @@ -7947,7 +7921,7 @@ public void test159() throws Throwable { public void test160() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test160"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process2 = shellCommander0.runCommand("[]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("[true]"); org.junit.Assert.assertNotNull(process2); @@ -8015,7 +7989,7 @@ public void test162() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); uShortList11.ensureCapacity((-11)); @@ -8228,10 +8202,10 @@ public void test164() throws Throwable { boolean boolean10 = uInteger3.equals((java.lang.Object) uShortList4); boolean boolean11 = uShortList4.isEmpty(); java.util.ListIterator uShortItor12 = uShortList4.listIterator(); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str15 = shellCommander13.runCommandAndGetOutputMessage("[true]"); java.lang.Process process17 = shellCommander13.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str20 = shellCommander18.runCommandAndGetOutputMessage("[true]"); java.lang.Process process22 = shellCommander18.runCommand("[10, -1, -1, 10]"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks23 = null; @@ -8240,9 +8214,8 @@ public void test164() throws Throwable { java.lang.Process process26 = processExecutionHandler25.getProcess(); java.lang.Long long27 = processExecutionHandler25.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks28 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler30 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks28, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander31 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler30 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks28, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander31 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process33 = shellCommander31.runCommand("[281475010265083]"); processExecutionHandler30.monitorProcess(process33); processExecutionHandler25.monitorProcess(process33); @@ -8252,9 +8225,8 @@ public void test164() throws Throwable { java.lang.Process process39 = processExecutionHandler38.getProcess(); java.lang.Long long40 = processExecutionHandler38.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks41 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler43 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks41, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander44 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler43 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks41, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander44 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process46 = shellCommander44.runCommand("[281475010265083]"); processExecutionHandler43.monitorProcess(process46); processExecutionHandler38.monitorProcess(process46); @@ -8320,7 +8292,7 @@ public void test166() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("-1"); @@ -8565,12 +8537,11 @@ public void test168() throws Throwable { boolean boolean43 = octetList0.containsAll( (java.util.Collection) uRIList17); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks44 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler46 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks44, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander47 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler46 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks44, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander47 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process49 = shellCommander47.runCommand("[281475010265083]"); processExecutionHandler46.monitorProcess(process49); - esa.mo.sm.impl.util.ShellCommander shellCommander51 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander51 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process53 = shellCommander51.runCommand("[]"); processExecutionHandler46.monitorProcess(process53); java.lang.Process process55 = processExecutionHandler46.getProcess(); @@ -8624,7 +8595,7 @@ public void test169() throws Throwable { public void test170() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test170"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.Process process4 = shellCommander0.runCommand("17"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("-1"); @@ -8659,7 +8630,7 @@ public void test171() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -8862,7 +8833,7 @@ public void test172() throws Throwable { public void test173() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test173"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process2 = shellCommander0.runCommand("[281475010265083]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("281474993487879"); org.junit.Assert.assertNotNull(process2); @@ -8897,18 +8868,17 @@ public void test174() throws Throwable { int int21 = strList2.size(); java.util.ListIterator strItor22 = strList2.listIterator(); boolean boolean24 = strList2.add("[1, 1, 10, 1, -1, 0]"); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("[true]"); java.lang.String str29 = shellCommander25.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process31 = shellCommander25.runCommand(""); - esa.mo.sm.impl.util.ShellCommander shellCommander32 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander32 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str34 = shellCommander32.runCommandAndGetOutputMessage(""); java.lang.Process process36 = shellCommander32.runCommand("2.81475010265083E14"); java.lang.String str38 = shellCommander32.runCommandAndGetOutputMessage("2.81475010265083E14"); - esa.mo.sm.impl.util.ShellCommander[] shellCommanderArray39 = new esa.mo.sm.impl.util.ShellCommander[]{shellCommander25, - shellCommander32}; + esa.mo.helpertools.misc.ShellCommander[] shellCommanderArray39 = new esa.mo.helpertools.misc.ShellCommander[] { shellCommander25, shellCommander32 }; try { - esa.mo.sm.impl.util.ShellCommander[] shellCommanderArray40 = strList2.toArray(shellCommanderArray39); + esa.mo.helpertools.misc.ShellCommander[] shellCommanderArray40 = strList2.toArray(shellCommanderArray39); org.junit.Assert.fail("Expected exception of type java.lang.ArrayStoreException; message: null"); } catch (java.lang.ArrayStoreException e) { } @@ -8975,7 +8945,7 @@ public void test175() throws Throwable { java.util.stream.Stream uRIStream38 = uRIList35.stream(); boolean boolean39 = uRIList35.isEmpty(); int int40 = intList26.indexOf((java.lang.Object) boolean39); - esa.mo.sm.impl.util.ShellCommander shellCommander41 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander41 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process43 = shellCommander41.runCommand("[]"); boolean boolean44 = intList26.equals((java.lang.Object) shellCommander41); org.ccsds.moims.mo.mal.structures.OctetList octetList46 = new org.ccsds.moims.mo.mal.structures.OctetList(0); @@ -9026,7 +8996,7 @@ public void test176() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -9093,7 +9063,7 @@ public void test177() throws Throwable { public void test178() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test178"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.Process process4 = shellCommander0.runCommand("17"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("-1"); @@ -9212,7 +9182,7 @@ public void test180() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); uShortList11.ensureCapacity((-11)); @@ -9385,9 +9355,8 @@ public void test181() throws Throwable { java.lang.String str78 = identifier73.getValue(); org.ccsds.moims.mo.mal.structures.Element element79 = identifier73.createElement(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks80 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler82 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks80, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander83 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler82 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks80, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander83 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process85 = shellCommander83.runCommand("[281475010265083]"); processExecutionHandler82.monitorProcess(process85); boolean boolean87 = identifier73.equals((java.lang.Object) process85); @@ -9555,7 +9524,7 @@ public void test183() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test183"); org.ccsds.moims.mo.mal.structures.URIList uRIList1 = new org.ccsds.moims.mo.mal.structures.URIList(13); - esa.mo.sm.impl.util.ShellCommander shellCommander2 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander2 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str4 = shellCommander2.runCommandAndGetOutputMessage("hi!"); java.lang.Process process6 = shellCommander2.runCommand("17"); java.lang.String str8 = shellCommander2.runCommandAndGetOutputMessage("-1"); @@ -9578,7 +9547,7 @@ public void test183() throws Throwable { public void test184() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test184"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -9599,7 +9568,7 @@ public void test184() throws Throwable { public void test185() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test185"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -9622,7 +9591,7 @@ public void test186() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -9656,7 +9625,7 @@ public void test186() throws Throwable { public void test187() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test187"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); java.lang.String str3 = oSValidator0.getOS(); @@ -9752,7 +9721,7 @@ public void test188() throws Throwable { boolean boolean73 = booleanList1.removeAll( (java.util.Collection) uRIList63); uRIList63.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator75 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator75 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean76 = oSValidator75.isMac(); java.lang.String str77 = oSValidator75.getOS(); boolean boolean78 = uRIList63.equals((java.lang.Object) str77); @@ -9850,9 +9819,8 @@ public void test189() throws Throwable { boolean boolean42 = intList24.removeAll( (java.util.Collection) uRIList39); boolean boolean43 = booleanList12.equals((java.lang.Object) uRIList39); - boolean boolean44 = booleanList1.retainAll( - (java.util.Collection) uRIList39); - esa.mo.sm.impl.util.OSValidator oSValidator45 = new esa.mo.sm.impl.util.OSValidator(); + boolean boolean44 = booleanList1.retainAll((java.util.Collection) uRIList39); + esa.mo.helpertools.misc.OSValidator oSValidator45 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean46 = oSValidator45.isMac(); boolean boolean47 = oSValidator45.isWindows(); java.lang.String str48 = oSValidator45.getOS(); @@ -9910,7 +9878,7 @@ public void test190() throws Throwable { public void test191() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test191"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.Process process4 = shellCommander0.runCommand("17"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("-1"); @@ -9928,12 +9896,11 @@ public void test192() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test192"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[]"); processExecutionHandler2.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler2.getProcess(); @@ -10006,9 +9973,8 @@ public void test192() throws Throwable { (java.util.Collection) uRIList63); java.util.Spliterator uRISpliterator69 = uRIList63.spliterator(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks70 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler72 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks70, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander73 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler72 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks70, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander73 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process75 = shellCommander73.runCommand("[281475010265083]"); processExecutionHandler72.monitorProcess(process75); java.lang.Process process77 = processExecutionHandler72.getProcess(); @@ -10100,7 +10066,7 @@ public void test194() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("[10, -1, -1, 10, 1, 1]"); @@ -10153,7 +10119,7 @@ public void test195() throws Throwable { java.lang.Long long30 = octetList28.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element31 = octetList28.createElement(); octetList28.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator33 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator33 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean34 = oSValidator33.isMac(); boolean boolean35 = oSValidator33.isMac(); int int36 = octetList28.lastIndexOf((java.lang.Object) oSValidator33); @@ -10292,7 +10258,7 @@ public void test196() throws Throwable { public void test197() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test197"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process6 = shellCommander0.runCommand(""); @@ -10377,7 +10343,7 @@ public void test198() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -10583,7 +10549,7 @@ public void test200() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); int int22 = floatList4.size(); @@ -10686,7 +10652,7 @@ public void test201() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -10754,13 +10720,13 @@ public void test202() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); boolean boolean41 = uShortList30.add(uShort40); int int42 = uShortList11.lastIndexOf((java.lang.Object) boolean41); - esa.mo.sm.impl.util.ShellCommander shellCommander43 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander43 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str45 = shellCommander43.runCommandAndGetOutputMessage(""); java.lang.Process process47 = shellCommander43.runCommand("2.81475010265083E14"); java.lang.String str49 = shellCommander43.runCommandAndGetOutputMessage("2.81475010265083E14"); @@ -10871,7 +10837,7 @@ public void test203() throws Throwable { public void test204() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test204"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); java.lang.String str3 = oSValidator0.getOS(); @@ -10979,21 +10945,20 @@ public void test205() throws Throwable { java.util.Iterator floatItor76 = floatList61.iterator(); java.util.ListIterator floatItor77 = floatList61.listIterator(); boolean boolean78 = octetList0.contains((java.lang.Object) floatList61); - esa.mo.sm.impl.util.OSValidator oSValidator79 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator79 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean80 = oSValidator79.isMac(); java.lang.String str81 = oSValidator79.getOS(); boolean boolean82 = oSValidator79.isWindows(); boolean boolean83 = oSValidator79.isMac(); boolean boolean84 = oSValidator79.isSolaris(); boolean boolean85 = oSValidator79.isUnix(); - esa.mo.sm.impl.util.OSValidator oSValidator86 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator86 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean87 = oSValidator86.isMac(); java.lang.String str88 = oSValidator86.getOS(); boolean boolean89 = oSValidator86.isWindows(); boolean boolean90 = oSValidator86.isMac(); - esa.mo.sm.impl.util.OSValidator[] oSValidatorArray91 = new esa.mo.sm.impl.util.OSValidator[]{oSValidator79, - oSValidator86}; - esa.mo.sm.impl.util.OSValidator[] oSValidatorArray92 = octetList0.toArray(oSValidatorArray91); + esa.mo.helpertools.misc.OSValidator[] oSValidatorArray91 = new esa.mo.helpertools.misc.OSValidator[] { oSValidator79, oSValidator86 }; + esa.mo.helpertools.misc.OSValidator[] oSValidatorArray92 = octetList0.toArray(oSValidatorArray91); java.lang.Long long93 = octetList0.getShortForm(); org.junit.Assert.assertNotNull(uOctet1); org.junit.Assert.assertNotNull(uOctet2); @@ -11087,7 +11052,7 @@ public void test206() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("-1"); @@ -11186,7 +11151,7 @@ public void test208() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -11232,7 +11197,7 @@ public void test209() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); uShortList11.ensureCapacity((-11)); @@ -11331,7 +11296,7 @@ public void test210() throws Throwable { java.util.ListIterator doubleItor37 = doubleList29.listIterator((int) (short) 1); doubleList29.ensureCapacity((int) (byte) 1); doubleList29.trimToSize(); - esa.mo.sm.impl.util.ShellCommander shellCommander41 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander41 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str43 = shellCommander41.runCommandAndGetOutputMessage("hi!"); boolean boolean44 = doubleList29.contains((java.lang.Object) "hi!"); java.util.Iterator doubleItor45 = doubleList29.iterator(); @@ -11569,7 +11534,7 @@ public void test213() throws Throwable { public void test214() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test214"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -11622,13 +11587,13 @@ public void test215() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); boolean boolean41 = uShortList30.add(uShort40); int int42 = uShortList11.lastIndexOf((java.lang.Object) boolean41); - esa.mo.sm.impl.util.ShellCommander shellCommander43 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander43 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str45 = shellCommander43.runCommandAndGetOutputMessage(""); java.lang.Process process47 = shellCommander43.runCommand("2.81475010265083E14"); java.lang.String str49 = shellCommander43.runCommandAndGetOutputMessage("2.81475010265083E14"); @@ -11688,7 +11653,7 @@ public void test216() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); int int22 = floatList4.size(); @@ -11810,9 +11775,8 @@ public void test217() throws Throwable { boolean boolean49 = intList31.removeAll( (java.util.Collection) uRIList46); boolean boolean50 = booleanList19.equals((java.lang.Object) uRIList46); - boolean boolean51 = booleanList8.retainAll( - (java.util.Collection) uRIList46); - esa.mo.sm.impl.util.OSValidator oSValidator52 = new esa.mo.sm.impl.util.OSValidator(); + boolean boolean51 = booleanList8.retainAll((java.util.Collection) uRIList46); + esa.mo.helpertools.misc.OSValidator oSValidator52 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean53 = oSValidator52.isMac(); boolean boolean54 = oSValidator52.isWindows(); java.lang.String str55 = oSValidator52.getOS(); @@ -11860,7 +11824,7 @@ public void test217() throws Throwable { public void test218() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test218"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); java.lang.String str3 = oSValidator0.getOS(); @@ -11889,7 +11853,7 @@ public void test219() throws Throwable { java.util.Spliterator intSpliterator15 = integerList13.spliterator(); boolean boolean16 = doubleList6.equals((java.lang.Object) integerList13); org.ccsds.moims.mo.mal.structures.Element element17 = integerList13.createElement(); - esa.mo.sm.impl.util.OSValidator oSValidator18 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator18 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean19 = oSValidator18.isMac(); java.lang.String str20 = oSValidator18.getOS(); boolean boolean21 = oSValidator18.isWindows(); @@ -11930,9 +11894,8 @@ public void test220() throws Throwable { java.lang.Process process8 = processExecutionHandler7.getProcess(); java.lang.Long long9 = processExecutionHandler7.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks10 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks10, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks10, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process15 = shellCommander13.runCommand("[281475010265083]"); processExecutionHandler12.monitorProcess(process15); processExecutionHandler7.monitorProcess(process15); @@ -11968,17 +11931,15 @@ public void test222() throws Throwable { java.lang.Process process8 = processExecutionHandler7.getProcess(); java.lang.Long long9 = processExecutionHandler7.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks10 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks10, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks10, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process15 = shellCommander13.runCommand("[281475010265083]"); processExecutionHandler12.monitorProcess(process15); processExecutionHandler7.monitorProcess(process15); processExecutionHandler2.monitorProcess(process15); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks19 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler21 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks19, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander22 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler21 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks19, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander22 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process24 = shellCommander22.runCommand("[281475010265083]"); processExecutionHandler21.monitorProcess(process24); java.lang.Process process26 = processExecutionHandler21.getProcess(); @@ -12228,7 +12189,7 @@ public void test226() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -12303,7 +12264,7 @@ public void test227() throws Throwable { callbacks33, (java.lang.Long) 281474993487875L); java.lang.Long long36 = processExecutionHandler35.getObjId(); java.lang.Process process37 = processExecutionHandler35.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander38 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander38 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str40 = shellCommander38.runCommandAndGetOutputMessage("hi!"); java.lang.Process process42 = shellCommander38.runCommand("17"); processExecutionHandler35.monitorProcess(process42); @@ -12407,7 +12368,7 @@ public void test229() throws Throwable { java.lang.Object[] objArray2 = octetList1.toArray(); java.util.Iterator byteItor3 = octetList1.iterator(); java.util.stream.Stream byteStream4 = octetList1.stream(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str6 = oSValidator5.getOS(); boolean boolean7 = octetList1.contains((java.lang.Object) str6); org.junit.Assert.assertNotNull(objArray2); @@ -12421,7 +12382,7 @@ public void test229() throws Throwable { public void test230() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test230"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process6 = shellCommander0.runCommand("1"); @@ -12519,7 +12480,7 @@ public void test232() throws Throwable { (java.util.Collection) uRIList61); boolean boolean68 = uShortList2.remove((java.lang.Object) uRIList61); java.lang.Object obj69 = uShortList2.clone(); - esa.mo.sm.impl.util.OSValidator oSValidator70 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator70 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str71 = oSValidator70.getOS(); boolean boolean72 = oSValidator70.isUnix(); java.lang.String str73 = oSValidator70.getOS(); @@ -12582,7 +12543,7 @@ public void test232() throws Throwable { public void test233() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test233"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -12748,16 +12709,14 @@ public void test235() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test235"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks8 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler10 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks8, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander11 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler10 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks8, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander11 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process13 = shellCommander11.runCommand("[281475010265083]"); processExecutionHandler10.monitorProcess(process13); java.lang.Process process15 = processExecutionHandler10.getProcess(); @@ -12767,9 +12726,8 @@ public void test235() throws Throwable { esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler20 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( callbacks18, (java.lang.Long) 0L); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks21 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler23 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks21, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander24 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler23 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks21, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander24 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process26 = shellCommander24.runCommand("[281475010265083]"); processExecutionHandler23.monitorProcess(process26); java.lang.Process process28 = processExecutionHandler23.getProcess(); @@ -12828,7 +12786,7 @@ public void test236() throws Throwable { public void test237() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test237"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.Process process4 = shellCommander0.runCommand("17"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("-1"); @@ -12913,7 +12871,7 @@ public void test239() throws Throwable { java.util.stream.Stream uRIStream23 = uRIList20.stream(); boolean boolean24 = uRIList20.isEmpty(); int int25 = intList11.indexOf((java.lang.Object) boolean24); - esa.mo.sm.impl.util.ShellCommander shellCommander26 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander26 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process28 = shellCommander26.runCommand("[]"); boolean boolean29 = intList11.equals((java.lang.Object) shellCommander26); intList11.add((int) (byte) 10, (java.lang.Integer) 0); @@ -12992,7 +12950,7 @@ public void test240() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -13088,7 +13046,7 @@ public void test242() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -13154,7 +13112,7 @@ public void test243() throws Throwable { public void test244() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test244"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -13175,7 +13133,7 @@ public void test245() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -13359,7 +13317,7 @@ public void test246() throws Throwable { boolean boolean19 = floatList16.contains((java.lang.Object) uShort18); floatList16.clear(); boolean boolean21 = uShort12.equals((java.lang.Object) floatList16); - esa.mo.sm.impl.util.OSValidator oSValidator22 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator22 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str23 = oSValidator22.getOS(); boolean boolean24 = oSValidator22.isMac(); int int25 = floatList16.indexOf((java.lang.Object) oSValidator22); @@ -13526,7 +13484,7 @@ public void test250() throws Throwable { boolean boolean29 = floatList18.remove((java.lang.Object) boolean28); java.lang.String str30 = floatList18.toString(); java.lang.Object obj31 = floatList18.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander32 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander32 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process34 = shellCommander32.runCommand("[]"); boolean boolean35 = floatList18.equals((java.lang.Object) shellCommander32); int int36 = floatList18.size(); @@ -13558,7 +13516,7 @@ public void test250() throws Throwable { public void test251() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test251"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); java.lang.String str3 = oSValidator0.getOS(); @@ -13720,9 +13678,8 @@ public void test253() throws Throwable { java.lang.Process process3 = processExecutionHandler2.getProcess(); java.lang.Long long4 = processExecutionHandler2.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks5 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler7 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks5, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander8 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler7 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks5, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander8 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process10 = shellCommander8.runCommand("[281475010265083]"); processExecutionHandler7.monitorProcess(process10); processExecutionHandler2.monitorProcess(process10); @@ -13743,7 +13700,7 @@ public void test254() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -13799,7 +13756,7 @@ public void test255() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -14043,7 +14000,7 @@ public void test257() throws Throwable { java.util.stream.Stream uRIStream68 = uRIList65.stream(); boolean boolean69 = uRIList65.isEmpty(); int int70 = intList56.indexOf((java.lang.Object) boolean69); - esa.mo.sm.impl.util.ShellCommander shellCommander71 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander71 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process73 = shellCommander71.runCommand("[]"); boolean boolean74 = intList56.equals((java.lang.Object) shellCommander71); int int75 = doubleList44.indexOf((java.lang.Object) intList56); @@ -14116,7 +14073,7 @@ public void test258() throws Throwable { java.util.stream.Stream uRIStream23 = uRIList20.stream(); boolean boolean24 = uRIList20.isEmpty(); int int25 = intList11.indexOf((java.lang.Object) boolean24); - esa.mo.sm.impl.util.ShellCommander shellCommander26 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander26 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process28 = shellCommander26.runCommand("[]"); boolean boolean29 = intList11.equals((java.lang.Object) shellCommander26); java.lang.Process process31 = shellCommander26.runCommand("-4"); @@ -14281,7 +14238,7 @@ public void test260() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -14517,7 +14474,7 @@ public void test262() throws Throwable { java.util.ListIterator doubleItor13 = doubleList5.listIterator((int) (short) 1); doubleList5.ensureCapacity((int) (byte) 1); doubleList5.trimToSize(); - esa.mo.sm.impl.util.ShellCommander shellCommander17 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander17 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str19 = shellCommander17.runCommandAndGetOutputMessage("hi!"); boolean boolean20 = doubleList5.contains((java.lang.Object) "hi!"); java.util.ListIterator doubleItor21 = doubleList5.listIterator(); @@ -14548,7 +14505,7 @@ public void test263() throws Throwable { public void test264() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test264"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -14577,7 +14534,7 @@ public void test265() throws Throwable { java.util.ListIterator doubleItor13 = doubleList5.listIterator((int) (short) 1); doubleList5.ensureCapacity((int) (byte) 1); doubleList5.trimToSize(); - esa.mo.sm.impl.util.ShellCommander shellCommander17 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander17 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str19 = shellCommander17.runCommandAndGetOutputMessage("hi!"); boolean boolean20 = doubleList5.contains((java.lang.Object) "hi!"); java.util.Iterator doubleItor21 = doubleList5.iterator(); @@ -14700,7 +14657,7 @@ public void test266() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -14733,7 +14690,7 @@ public void test266() throws Throwable { public void test267() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test267"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process6 = shellCommander0.runCommand(""); @@ -14748,7 +14705,7 @@ public void test267() throws Throwable { public void test268() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test268"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process2 = shellCommander0.runCommand(""); java.lang.Process process4 = shellCommander0.runCommand("97"); org.junit.Assert.assertNotNull(process2); @@ -14762,7 +14719,7 @@ public void test269() throws Throwable { org.ccsds.moims.mo.mal.structures.IntegerList integerList1 = new org.ccsds.moims.mo.mal.structures.IntegerList( 7); org.ccsds.moims.mo.mal.structures.UShort uShort2 = integerList1.getAreaNumber(); - esa.mo.sm.impl.util.OSValidator oSValidator3 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator3 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str4 = oSValidator3.getOS(); boolean boolean5 = oSValidator3.isUnix(); java.lang.String str6 = oSValidator3.getOS(); @@ -14914,7 +14871,7 @@ public void test269() throws Throwable { public void test270() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test270"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process6 = shellCommander0.runCommand(""); @@ -14977,7 +14934,7 @@ public void test271() throws Throwable { public void test272() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test272"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -15074,11 +15031,9 @@ public void test273() throws Throwable { org.ccsds.moims.mo.mal.structures.URI uRI72 = new org.ccsds.moims.mo.mal.structures.URI(); org.ccsds.moims.mo.mal.structures.UShort uShort73 = uRI72.getServiceNumber(); boolean boolean74 = uRIList51.add(uRI72); - boolean boolean75 = booleanList24.containsAll( - (java.util.Collection) uRIList51); - boolean boolean76 = octetList0.retainAll( - (java.util.Collection) uRIList51); - esa.mo.sm.impl.util.OSValidator oSValidator77 = new esa.mo.sm.impl.util.OSValidator(); + boolean boolean75 = booleanList24.containsAll((java.util.Collection) uRIList51); + boolean boolean76 = octetList0.retainAll((java.util.Collection) uRIList51); + esa.mo.helpertools.misc.OSValidator oSValidator77 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean78 = oSValidator77.isMac(); boolean boolean79 = oSValidator77.isSolaris(); java.lang.String str80 = oSValidator77.getOS(); @@ -15168,7 +15123,7 @@ public void test274() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -15245,7 +15200,7 @@ public void test275() throws Throwable { boolean boolean60 = uShortList0.equals((java.lang.Object) doubleList39); java.lang.Long long61 = uShortList0.getShortForm(); org.ccsds.moims.mo.mal.structures.URIList uRIList63 = new org.ccsds.moims.mo.mal.structures.URIList(13); - esa.mo.sm.impl.util.ShellCommander shellCommander64 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander64 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str66 = shellCommander64.runCommandAndGetOutputMessage("hi!"); java.lang.Process process68 = shellCommander64.runCommand("17"); java.lang.String str70 = shellCommander64.runCommandAndGetOutputMessage("-1"); @@ -15307,12 +15262,11 @@ public void test276() throws Throwable { (java.lang.Boolean) true); org.ccsds.moims.mo.mal.structures.UOctet uOctet2 = union1.getAreaVersion(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks3 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler5 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks3, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander6 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler5 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks3, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander6 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process8 = shellCommander6.runCommand("[281475010265083]"); processExecutionHandler5.monitorProcess(process8); - esa.mo.sm.impl.util.ShellCommander shellCommander10 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander10 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process12 = shellCommander10.runCommand("[]"); processExecutionHandler5.monitorProcess(process12); java.lang.Process process14 = processExecutionHandler5.getProcess(); @@ -15333,9 +15287,8 @@ public void test277() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test277"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -15356,7 +15309,7 @@ public void test277() throws Throwable { public void test278() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test278"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isMac(); @@ -15378,9 +15331,8 @@ public void test279() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test279"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -15421,9 +15373,8 @@ public void test281() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test281"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -15480,10 +15431,10 @@ public void test283() throws Throwable { boolean boolean10 = uInteger3.equals((java.lang.Object) uShortList4); boolean boolean11 = uShortList4.isEmpty(); java.util.ListIterator uShortItor12 = uShortList4.listIterator(); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str15 = shellCommander13.runCommandAndGetOutputMessage("[true]"); java.lang.Process process17 = shellCommander13.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str20 = shellCommander18.runCommandAndGetOutputMessage("[true]"); java.lang.Process process22 = shellCommander18.runCommand("[10, -1, -1, 10]"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks23 = null; @@ -15492,9 +15443,8 @@ public void test283() throws Throwable { java.lang.Process process26 = processExecutionHandler25.getProcess(); java.lang.Long long27 = processExecutionHandler25.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks28 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler30 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks28, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander31 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler30 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks28, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander31 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process33 = shellCommander31.runCommand("[281475010265083]"); processExecutionHandler30.monitorProcess(process33); processExecutionHandler25.monitorProcess(process33); @@ -15504,9 +15454,8 @@ public void test283() throws Throwable { java.lang.Process process39 = processExecutionHandler38.getProcess(); java.lang.Long long40 = processExecutionHandler38.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks41 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler43 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks41, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander44 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler43 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks41, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander44 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process46 = shellCommander44.runCommand("[281475010265083]"); processExecutionHandler43.monitorProcess(process46); processExecutionHandler38.monitorProcess(process46); @@ -15557,7 +15506,7 @@ public void test284() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); org.ccsds.moims.mo.mal.structures.UShort uShort21 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -15613,7 +15562,7 @@ public void test284() throws Throwable { public void test285() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test285"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isMac(); @@ -15636,7 +15585,7 @@ public void test285() throws Throwable { public void test286() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test286"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -15666,7 +15615,7 @@ public void test287() throws Throwable { public void test288() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test288"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage(""); java.lang.Process process4 = shellCommander0.runCommand("281474993487879"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("[281475010265083]"); @@ -15688,15 +15637,13 @@ public void test289() throws Throwable { java.lang.Process process4 = processExecutionHandler2.getProcess(); java.lang.Process process5 = processExecutionHandler2.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks6 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler8 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks6, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler8 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks6, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process11 = shellCommander9.runCommand("[281475010265083]"); processExecutionHandler8.monitorProcess(process11); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks13 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks13, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks13, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[281475010265083]"); processExecutionHandler15.monitorProcess(process18); java.lang.Process process20 = processExecutionHandler15.getProcess(); @@ -15751,9 +15698,8 @@ public void test291() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test291"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -15765,9 +15711,8 @@ public void test291() throws Throwable { java.lang.Long long13 = processExecutionHandler12.getObjId(); java.lang.Process process14 = processExecutionHandler12.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks15 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler17 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks15, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler17 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks15, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[281475010265083]"); processExecutionHandler17.monitorProcess(process20); java.lang.Process process22 = processExecutionHandler17.getProcess(); @@ -15794,9 +15739,8 @@ public void test292() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test292"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -15942,7 +15886,7 @@ public void test293() throws Throwable { public void test294() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test294"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -16158,10 +16102,10 @@ public void test296() throws Throwable { boolean boolean47 = uInteger40.equals((java.lang.Object) uShortList41); boolean boolean48 = uShortList41.isEmpty(); java.util.ListIterator uShortItor49 = uShortList41.listIterator(); - esa.mo.sm.impl.util.ShellCommander shellCommander50 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander50 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str52 = shellCommander50.runCommandAndGetOutputMessage("[true]"); java.lang.Process process54 = shellCommander50.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander55 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander55 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str57 = shellCommander55.runCommandAndGetOutputMessage("[true]"); java.lang.Process process59 = shellCommander55.runCommand("[10, -1, -1, 10]"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks60 = null; @@ -16170,9 +16114,8 @@ public void test296() throws Throwable { java.lang.Process process63 = processExecutionHandler62.getProcess(); java.lang.Long long64 = processExecutionHandler62.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks65 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler67 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks65, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander68 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler67 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks65, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander68 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process70 = shellCommander68.runCommand("[281475010265083]"); processExecutionHandler67.monitorProcess(process70); processExecutionHandler62.monitorProcess(process70); @@ -16182,9 +16125,8 @@ public void test296() throws Throwable { java.lang.Process process76 = processExecutionHandler75.getProcess(); java.lang.Long long77 = processExecutionHandler75.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks78 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler80 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks78, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander81 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler80 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks78, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander81 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process83 = shellCommander81.runCommand("[281475010265083]"); processExecutionHandler80.monitorProcess(process83); processExecutionHandler75.monitorProcess(process83); @@ -16250,7 +16192,7 @@ public void test297() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -16380,9 +16322,8 @@ public void test298() throws Throwable { java.lang.Process process30 = processExecutionHandler29.getProcess(); java.lang.Long long31 = processExecutionHandler29.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks32 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler34 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks32, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler34 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks32, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process37 = shellCommander35.runCommand("[281475010265083]"); processExecutionHandler34.monitorProcess(process37); processExecutionHandler29.monitorProcess(process37); @@ -16563,7 +16504,7 @@ public void test300() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -16641,7 +16582,7 @@ public void test300() throws Throwable { public void test301() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test301"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.Process process4 = shellCommander0.runCommand("[10, -1, -1, 10]"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("281474993487877"); @@ -16660,7 +16601,7 @@ public void test302() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -16690,20 +16631,18 @@ public void test303() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test303"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); java.lang.Long long8 = processExecutionHandler2.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks9 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler11 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks9, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander12 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler11 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks9, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander12 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process14 = shellCommander12.runCommand("[281475010265083]"); processExecutionHandler11.monitorProcess(process14); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[]"); processExecutionHandler11.monitorProcess(process18); java.lang.Process process20 = processExecutionHandler11.getProcess(); @@ -16714,7 +16653,7 @@ public void test303() throws Throwable { callbacks23, (java.lang.Long) 281474993487875L); java.lang.Long long26 = processExecutionHandler25.getObjId(); java.lang.Process process27 = processExecutionHandler25.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str30 = shellCommander28.runCommandAndGetOutputMessage("hi!"); java.lang.Process process32 = shellCommander28.runCommand("17"); processExecutionHandler25.monitorProcess(process32); @@ -16814,12 +16753,11 @@ public void test305() throws Throwable { boolean boolean43 = octetList0.containsAll( (java.util.Collection) uRIList17); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks44 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler46 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks44, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander47 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler46 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks44, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander47 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process49 = shellCommander47.runCommand("[281475010265083]"); processExecutionHandler46.monitorProcess(process49); - esa.mo.sm.impl.util.ShellCommander shellCommander51 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander51 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process53 = shellCommander51.runCommand("[]"); processExecutionHandler46.monitorProcess(process53); java.lang.Process process55 = processExecutionHandler46.getProcess(); @@ -16978,7 +16916,7 @@ public void test308() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -17023,7 +16961,7 @@ public void test309() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -17120,7 +17058,7 @@ public void test310() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -17182,15 +17120,14 @@ public void test311() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test311"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); java.lang.Process process8 = processExecutionHandler2.getProcess(); java.lang.Process process9 = processExecutionHandler2.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander10 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander10 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str12 = shellCommander10.runCommandAndGetOutputMessage(""); java.lang.Process process14 = shellCommander10.runCommand("281474993487879"); java.lang.String str16 = shellCommander10.runCommandAndGetOutputMessage("[1, 1, 10, 1, -1, 0]"); @@ -17387,7 +17324,7 @@ public void test315() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -17421,7 +17358,7 @@ public void test315() throws Throwable { public void test316() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test316"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isSolaris(); boolean boolean2 = oSValidator0.isSolaris(); org.junit.Assert.assertTrue("'" + boolean1 + "' != '" + false + "'", !boolean1); @@ -17527,13 +17464,13 @@ public void test320() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); boolean boolean41 = uShortList30.add(uShort40); int int42 = uShortList11.lastIndexOf((java.lang.Object) boolean41); - esa.mo.sm.impl.util.ShellCommander shellCommander43 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander43 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str45 = shellCommander43.runCommandAndGetOutputMessage(""); java.lang.Process process47 = shellCommander43.runCommand("2.81475010265083E14"); java.lang.String str49 = shellCommander43.runCommandAndGetOutputMessage("2.81475010265083E14"); @@ -17577,7 +17514,7 @@ public void test320() throws Throwable { public void test321() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test321"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("[1]"); @@ -17749,7 +17686,7 @@ public void test323() throws Throwable { public void test324() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test324"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -17918,13 +17855,13 @@ public void test326() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); boolean boolean41 = uShortList30.add(uShort40); int int42 = uShortList11.lastIndexOf((java.lang.Object) boolean41); - esa.mo.sm.impl.util.ShellCommander shellCommander43 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander43 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str45 = shellCommander43.runCommandAndGetOutputMessage(""); java.lang.Process process47 = shellCommander43.runCommand("2.81475010265083E14"); java.lang.String str49 = shellCommander43.runCommandAndGetOutputMessage("2.81475010265083E14"); @@ -18196,7 +18133,7 @@ public void test329() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); floatList4.trimToSize(); @@ -18239,7 +18176,7 @@ public void test330() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("-1"); @@ -18292,7 +18229,7 @@ public void test331() throws Throwable { public void test332() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test332"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); java.lang.String str3 = oSValidator0.getOS(); @@ -18311,7 +18248,7 @@ public void test332() throws Throwable { public void test333() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test333"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -18333,9 +18270,8 @@ public void test334() throws Throwable { java.lang.Object[] objArray2 = octetList1.toArray(); java.util.Iterator byteItor3 = octetList1.iterator(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks4 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler6 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks4, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler6 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks4, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[281475010265083]"); processExecutionHandler6.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler6.getProcess(); @@ -18377,7 +18313,7 @@ public void test335() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -18409,9 +18345,8 @@ public void test336() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort2 = floatList0.getAreaNumber(); java.lang.Long long3 = floatList0.getShortForm(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks4 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler6 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks4, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler6 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks4, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[281475010265083]"); processExecutionHandler6.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler6.getProcess(); @@ -18423,9 +18358,8 @@ public void test336() throws Throwable { java.lang.Long long17 = processExecutionHandler16.getObjId(); java.lang.Process process18 = processExecutionHandler16.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks19 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler21 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks19, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander22 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler21 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks19, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander22 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process24 = shellCommander22.runCommand("[281475010265083]"); processExecutionHandler21.monitorProcess(process24); java.lang.Process process26 = processExecutionHandler21.getProcess(); @@ -18650,7 +18584,7 @@ public void test338() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -18783,7 +18717,7 @@ public void test339() throws Throwable { java.util.Spliterator uShortSpliterator66 = uShortList63 .spliterator(); int int67 = shortList57.lastIndexOf((java.lang.Object) uShortList63); - esa.mo.sm.impl.util.ShellCommander shellCommander68 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander68 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str70 = shellCommander68.runCommandAndGetOutputMessage("hi!"); boolean boolean71 = uShortList63.contains((java.lang.Object) str70); boolean boolean72 = floatList44.contains((java.lang.Object) uShortList63); @@ -18844,7 +18778,7 @@ public void test340() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -18911,13 +18845,13 @@ public void test341() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); boolean boolean41 = uShortList30.add(uShort40); int int42 = uShortList11.lastIndexOf((java.lang.Object) boolean41); - esa.mo.sm.impl.util.ShellCommander shellCommander43 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander43 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str45 = shellCommander43.runCommandAndGetOutputMessage(""); java.lang.Process process47 = shellCommander43.runCommand("2.81475010265083E14"); java.lang.String str49 = shellCommander43.runCommandAndGetOutputMessage("2.81475010265083E14"); @@ -18963,7 +18897,7 @@ public void test342() throws Throwable { callbacks0, (java.lang.Long) 281474993487875L); java.lang.Long long3 = processExecutionHandler2.getObjId(); java.lang.Process process4 = processExecutionHandler2.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander5 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander5 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str7 = shellCommander5.runCommandAndGetOutputMessage("hi!"); java.lang.Process process9 = shellCommander5.runCommand("17"); processExecutionHandler2.monitorProcess(process9); @@ -18976,12 +18910,11 @@ public void test342() throws Throwable { booleanList13.trimToSize(); boolean boolean20 = booleanList13.add((java.lang.Boolean) true); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks21 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler23 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks21, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander24 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler23 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks21, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander24 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process26 = shellCommander24.runCommand("[281475010265083]"); processExecutionHandler23.monitorProcess(process26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); processExecutionHandler23.monitorProcess(process30); java.lang.Process process32 = processExecutionHandler23.getProcess(); @@ -19012,24 +18945,22 @@ public void test343() throws Throwable { org.ccsds.moims.mo.mal.structures.UShortList uShortList0 = new org.ccsds.moims.mo.mal.structures.UShortList(); org.ccsds.moims.mo.mal.structures.UShort uShort1 = uShortList0.getAreaNumber(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks2 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks2, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander5 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler4 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks2, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander5 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process7 = shellCommander5.runCommand("[281475010265083]"); processExecutionHandler4.monitorProcess(process7); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process11 = shellCommander9.runCommand("[]"); processExecutionHandler4.monitorProcess(process11); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks13 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks13, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler15 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks13, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process18 = shellCommander16.runCommand("[281475010265083]"); processExecutionHandler15.monitorProcess(process18); - esa.mo.sm.impl.util.ShellCommander shellCommander20 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander20 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str22 = shellCommander20.runCommandAndGetOutputMessage("[true]"); java.lang.Process process24 = shellCommander20.runCommand("[10, -1, -1, 10]"); - esa.mo.sm.impl.util.ShellCommander shellCommander25 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander25 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str27 = shellCommander25.runCommandAndGetOutputMessage("[true]"); java.lang.Process process29 = shellCommander25.runCommand("[10, -1, -1, 10]"); java.lang.Process[] processArray30 = new java.lang.Process[]{process11, process18, process24, process29}; @@ -19052,7 +18983,7 @@ public void test343() throws Throwable { public void test344() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test344"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isWindows(); java.lang.String str3 = oSValidator0.getOS(); @@ -19136,7 +19067,7 @@ public void test345() throws Throwable { boolean boolean60 = uShortList0.equals((java.lang.Object) doubleList39); java.lang.Long long61 = uShortList0.getShortForm(); org.ccsds.moims.mo.mal.structures.URIList uRIList63 = new org.ccsds.moims.mo.mal.structures.URIList(13); - esa.mo.sm.impl.util.ShellCommander shellCommander64 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander64 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str66 = shellCommander64.runCommandAndGetOutputMessage("hi!"); java.lang.Process process68 = shellCommander64.runCommand("17"); java.lang.String str70 = shellCommander64.runCommandAndGetOutputMessage("-1"); @@ -19222,9 +19153,8 @@ public void test346() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test346"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 0L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 0L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str5 = shellCommander3.runCommandAndGetOutputMessage("[true]"); java.lang.String str7 = shellCommander3.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process9 = shellCommander3.runCommand(""); @@ -19370,7 +19300,7 @@ public void test348() throws Throwable { java.lang.Long long55 = octetList53.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element56 = octetList53.createElement(); octetList53.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator58 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator58 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean59 = oSValidator58.isMac(); boolean boolean60 = oSValidator58.isMac(); int int61 = octetList53.lastIndexOf((java.lang.Object) oSValidator58); @@ -19426,16 +19356,15 @@ public void test349() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test349"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[]"); processExecutionHandler2.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler2.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander12 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander12 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str14 = shellCommander12.runCommandAndGetOutputMessage("[true]"); java.lang.String str16 = shellCommander12.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process18 = shellCommander12.runCommand(""); @@ -19454,7 +19383,7 @@ public void test349() throws Throwable { public void test350() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test350"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isMac(); @@ -19485,7 +19414,7 @@ public void test351() throws Throwable { public void test352() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test352"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.Process process4 = shellCommander0.runCommand("[10, -1, -1, 10]"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("2"); @@ -19520,7 +19449,7 @@ public void test353() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -19573,7 +19502,7 @@ public void test353() throws Throwable { public void test354() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test354"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process2 = shellCommander0.runCommand("[281475010265083]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("281474993487882"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("10"); @@ -19606,7 +19535,7 @@ public void test355() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -19746,7 +19675,7 @@ public void test357() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -19795,7 +19724,7 @@ public void test358() throws Throwable { java.util.stream.Stream uRIStream23 = uRIList20.stream(); boolean boolean24 = uRIList20.isEmpty(); int int25 = intList11.indexOf((java.lang.Object) boolean24); - esa.mo.sm.impl.util.ShellCommander shellCommander26 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander26 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process28 = shellCommander26.runCommand("[]"); boolean boolean29 = intList11.equals((java.lang.Object) shellCommander26); java.lang.String str31 = shellCommander26.runCommandAndGetOutputMessage("[10, -1, -1, 10]"); @@ -19896,9 +19825,8 @@ public void test359() throws Throwable { java.lang.String str78 = identifier73.getValue(); org.ccsds.moims.mo.mal.structures.Element element79 = identifier73.createElement(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks80 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler82 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks80, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander83 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler82 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks80, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander83 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process85 = shellCommander83.runCommand("[281475010265083]"); processExecutionHandler82.monitorProcess(process85); boolean boolean87 = identifier73.equals((java.lang.Object) process85); @@ -20169,7 +20097,7 @@ public void test362() throws Throwable { java.lang.Long long8 = uShortList5.getShortForm(); boolean boolean9 = uShortList5.isEmpty(); boolean boolean10 = uShort4.equals((java.lang.Object) uShortList5); - esa.mo.sm.impl.util.OSValidator oSValidator11 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator11 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean12 = oSValidator11.isMac(); boolean boolean13 = oSValidator11.isWindows(); java.lang.String str14 = oSValidator11.getOS(); @@ -20350,7 +20278,7 @@ public void test364() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -20638,7 +20566,7 @@ public void test367() throws Throwable { public void test368() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test368"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -20718,7 +20646,7 @@ public void test369() throws Throwable { boolean boolean60 = uShortList0.equals((java.lang.Object) doubleList39); java.lang.Long long61 = uShortList0.getShortForm(); org.ccsds.moims.mo.mal.structures.URIList uRIList63 = new org.ccsds.moims.mo.mal.structures.URIList(13); - esa.mo.sm.impl.util.ShellCommander shellCommander64 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander64 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str66 = shellCommander64.runCommandAndGetOutputMessage("hi!"); java.lang.Process process68 = shellCommander64.runCommand("17"); java.lang.String str70 = shellCommander64.runCommandAndGetOutputMessage("-1"); @@ -20840,12 +20768,11 @@ public void test370() throws Throwable { boolean boolean43 = octetList0.containsAll( (java.util.Collection) uRIList17); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks44 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler46 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks44, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander47 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler46 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks44, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander47 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process49 = shellCommander47.runCommand("[281475010265083]"); processExecutionHandler46.monitorProcess(process49); - esa.mo.sm.impl.util.ShellCommander shellCommander51 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander51 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process53 = shellCommander51.runCommand("[]"); processExecutionHandler46.monitorProcess(process53); java.lang.Process process55 = processExecutionHandler46.getProcess(); @@ -20974,7 +20901,7 @@ public void test372() throws Throwable { org.ccsds.moims.mo.mal.structures.UShort uShort3 = floatList0.getAreaNumber(); java.util.stream.Stream floatStream4 = floatList0.parallelStream(); java.lang.Long long5 = floatList0.getShortForm(); - esa.mo.sm.impl.util.OSValidator oSValidator6 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator6 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str7 = oSValidator6.getOS(); boolean boolean8 = oSValidator6.isUnix(); java.lang.String str9 = oSValidator6.getOS(); @@ -21037,9 +20964,8 @@ public void test373() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test373"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -21048,7 +20974,7 @@ public void test373() throws Throwable { callbacks8, (java.lang.Long) 281474993487875L); java.lang.Long long11 = processExecutionHandler10.getObjId(); java.lang.Process process12 = processExecutionHandler10.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str15 = shellCommander13.runCommandAndGetOutputMessage("hi!"); java.lang.Process process17 = shellCommander13.runCommand("17"); processExecutionHandler10.monitorProcess(process17); @@ -21111,7 +21037,7 @@ public void test374() throws Throwable { public void test375() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test375"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); java.lang.String str3 = oSValidator0.getOS(); @@ -21131,7 +21057,7 @@ public void test376() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -21433,7 +21359,7 @@ public void test379() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); org.ccsds.moims.mo.mal.structures.UShort uShort21 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -21462,7 +21388,7 @@ public void test379() throws Throwable { public void test380() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test380"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("281474993487886"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("-15"); @@ -21500,9 +21426,8 @@ public void test381() throws Throwable { boolean boolean23 = longList6.containsAll( (java.util.Collection) uRIList20); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks24 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler26 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks24, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander27 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler26 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks24, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander27 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process29 = shellCommander27.runCommand("[281475010265083]"); processExecutionHandler26.monitorProcess(process29); java.lang.Process process31 = processExecutionHandler26.getProcess(); @@ -21662,7 +21587,7 @@ public void test383() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -21796,9 +21721,8 @@ public void test384() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test384"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -21941,7 +21865,7 @@ public void test386() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.util.stream.Stream floatStream22 = floatList4.stream(); @@ -22051,7 +21975,7 @@ public void test387() throws Throwable { boolean boolean71 = shortList1.containsAll( (java.util.Collection) uRIList65); org.ccsds.moims.mo.mal.structures.Element element72 = shortList1.createElement(); - esa.mo.sm.impl.util.OSValidator oSValidator73 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator73 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean74 = oSValidator73.isMac(); java.lang.String str75 = oSValidator73.getOS(); boolean boolean76 = oSValidator73.isWindows(); @@ -22247,7 +22171,7 @@ public void test389() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -22311,7 +22235,7 @@ public void test390() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -22333,7 +22257,7 @@ public void test390() throws Throwable { public void test391() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test391"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process2 = shellCommander0.runCommand("[281475010265083]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("281474993487882"); java.lang.Process process6 = shellCommander0.runCommand("[100.0, -1.0, 10.0]"); @@ -22347,9 +22271,8 @@ public void test392() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test392"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -22358,7 +22281,7 @@ public void test392() throws Throwable { callbacks8, (java.lang.Long) 281474993487875L); java.lang.Long long11 = processExecutionHandler10.getObjId(); java.lang.Process process12 = processExecutionHandler10.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str15 = shellCommander13.runCommandAndGetOutputMessage("hi!"); java.lang.Process process17 = shellCommander13.runCommand("17"); processExecutionHandler10.monitorProcess(process17); @@ -22479,7 +22402,7 @@ public void test393() throws Throwable { public void test394() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test394"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); boolean boolean3 = oSValidator0.isUnix(); @@ -22507,7 +22430,7 @@ public void test395() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); int int22 = floatList4.size(); @@ -22738,9 +22661,8 @@ public void test399() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test399"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -22752,9 +22674,8 @@ public void test399() throws Throwable { java.lang.Long long13 = processExecutionHandler12.getObjId(); java.lang.Process process14 = processExecutionHandler12.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks15 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler17 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks15, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler17 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks15, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[281475010265083]"); processExecutionHandler17.monitorProcess(process20); java.lang.Process process22 = processExecutionHandler17.getProcess(); @@ -22952,9 +22873,8 @@ public void test402() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test402"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -23122,7 +23042,7 @@ public void test404() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); uShortList11.ensureCapacity((-11)); @@ -23148,7 +23068,7 @@ public void test404() throws Throwable { public void test405() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test405"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); java.lang.String str1 = oSValidator0.getOS(); boolean boolean2 = oSValidator0.isUnix(); java.lang.String str3 = oSValidator0.getOS(); @@ -23166,9 +23086,8 @@ public void test406() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test406"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); @@ -23185,7 +23104,7 @@ public void test406() throws Throwable { public void test407() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test407"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("[1, 1, 10, 1, -1, 0]"); @@ -23218,7 +23137,7 @@ public void test408() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -23251,7 +23170,7 @@ public void test408() throws Throwable { public void test409() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test409"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("[true]"); java.lang.String str4 = shellCommander0.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("4294967295"); @@ -23269,7 +23188,7 @@ public void test410() throws Throwable { org.ccsds.moims.mo.mal.structures.OctetList octetList0 = new org.ccsds.moims.mo.mal.structures.OctetList(); org.ccsds.moims.mo.mal.structures.UShort uShort1 = octetList0.getAreaNumber(); java.lang.Long long2 = octetList0.getShortForm(); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[]"); java.lang.Process process7 = shellCommander3.runCommand("100"); boolean boolean8 = octetList0.contains((java.lang.Object) shellCommander3); @@ -23351,7 +23270,7 @@ public void test411() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -23419,7 +23338,7 @@ public void test411() throws Throwable { public void test412() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test412"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isUnix(); boolean boolean2 = oSValidator0.isMac(); org.junit.Assert.assertTrue("'" + boolean1 + "' != '" + true + "'", boolean1); @@ -23499,7 +23418,7 @@ public void test413() throws Throwable { boolean boolean61 = strList24.equals((java.lang.Object) uRIList56); boolean boolean62 = shortList8.contains((java.lang.Object) strList24); java.lang.String str63 = shortList8.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator64 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator64 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean65 = oSValidator64.isMac(); java.lang.String str66 = oSValidator64.getOS(); boolean boolean67 = oSValidator64.isWindows(); @@ -23580,7 +23499,7 @@ public void test413() throws Throwable { public void test414() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test414"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage("hi!"); java.lang.Process process4 = shellCommander0.runCommand("17"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage("-1"); @@ -23625,12 +23544,11 @@ public void test416() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test416"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[]"); processExecutionHandler2.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler2.getProcess(); @@ -23746,7 +23664,7 @@ public void test418() throws Throwable { boolean boolean79 = strList42.equals((java.lang.Object) uRIList74); boolean boolean80 = shortList26.contains((java.lang.Object) strList42); java.lang.String str81 = shortList26.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator82 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator82 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean83 = oSValidator82.isMac(); java.lang.String str84 = oSValidator82.getOS(); boolean boolean85 = oSValidator82.isWindows(); @@ -23823,7 +23741,7 @@ public void test419() throws Throwable { java.lang.Long long2 = octetList0.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element3 = octetList0.createElement(); octetList0.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator5 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator5 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean6 = oSValidator5.isMac(); boolean boolean7 = oSValidator5.isMac(); int int8 = octetList0.lastIndexOf((java.lang.Object) oSValidator5); @@ -23845,7 +23763,7 @@ public void test419() throws Throwable { public void test420() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test420"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); java.lang.String str3 = oSValidator0.getOS(); @@ -23868,9 +23786,8 @@ public void test421() throws Throwable { esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( callbacks0, (java.lang.Long) 281474993487879L); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks3 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler5 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks3, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander6 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler5 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks3, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander6 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process8 = shellCommander6.runCommand("[281475010265083]"); processExecutionHandler5.monitorProcess(process8); java.lang.Process process10 = processExecutionHandler5.getProcess(); @@ -23890,7 +23807,7 @@ public void test421() throws Throwable { public void test422() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test422"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); boolean boolean3 = oSValidator0.isWindows(); @@ -23925,7 +23842,7 @@ public void test423() throws Throwable { java.util.ListIterator doubleItor13 = doubleList5.listIterator((int) (short) 1); doubleList5.ensureCapacity((int) (byte) 1); doubleList5.trimToSize(); - esa.mo.sm.impl.util.ShellCommander shellCommander17 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander17 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str19 = shellCommander17.runCommandAndGetOutputMessage("hi!"); boolean boolean20 = doubleList5.contains((java.lang.Object) "hi!"); try { @@ -24006,7 +23923,7 @@ public void test424() throws Throwable { boolean boolean60 = uShortList0.equals((java.lang.Object) doubleList39); java.lang.Long long61 = uShortList0.getShortForm(); org.ccsds.moims.mo.mal.structures.URIList uRIList63 = new org.ccsds.moims.mo.mal.structures.URIList(13); - esa.mo.sm.impl.util.ShellCommander shellCommander64 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander64 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str66 = shellCommander64.runCommandAndGetOutputMessage("hi!"); java.lang.Process process68 = shellCommander64.runCommand("17"); java.lang.String str70 = shellCommander64.runCommandAndGetOutputMessage("-1"); @@ -24079,7 +23996,7 @@ public void test425() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); uShortList11.ensureCapacity((-11)); @@ -24211,7 +24128,7 @@ public void test427() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); floatList4.trimToSize(); @@ -24250,7 +24167,7 @@ public void test428() throws Throwable { boolean boolean15 = floatList4.remove((java.lang.Object) boolean14); java.lang.String str16 = floatList4.toString(); java.lang.Object obj17 = floatList4.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander18 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander18 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process20 = shellCommander18.runCommand("[]"); boolean boolean21 = floatList4.equals((java.lang.Object) shellCommander18); java.lang.String str23 = shellCommander18.runCommandAndGetOutputMessage("-1"); @@ -24309,7 +24226,7 @@ public void test429() throws Throwable { java.lang.Long long30 = octetList28.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element31 = octetList28.createElement(); octetList28.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator33 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator33 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean34 = oSValidator33.isMac(); boolean boolean35 = oSValidator33.isMac(); int int36 = octetList28.lastIndexOf((java.lang.Object) oSValidator33); @@ -24345,16 +24262,15 @@ public void test430() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test430"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); java.lang.Long long8 = processExecutionHandler2.getObjId(); java.lang.Process process9 = processExecutionHandler2.getProcess(); java.lang.Process process10 = processExecutionHandler2.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander11 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander11 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str13 = shellCommander11.runCommandAndGetOutputMessage("[true]"); java.lang.String str15 = shellCommander11.runCommandAndGetOutputMessage("2.81475010265083E14"); java.lang.Process process17 = shellCommander11.runCommand(""); @@ -24485,7 +24401,7 @@ public void test431() throws Throwable { public void test432() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test432"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -24504,7 +24420,7 @@ public void test432() throws Throwable { public void test433() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test433"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isMac(); boolean boolean3 = oSValidator0.isWindows(); @@ -24592,7 +24508,7 @@ public void test434() throws Throwable { boolean boolean59 = strList22.equals((java.lang.Object) uRIList54); boolean boolean60 = shortList6.contains((java.lang.Object) strList22); java.lang.String str61 = shortList6.toString(); - esa.mo.sm.impl.util.OSValidator oSValidator62 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator62 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean63 = oSValidator62.isMac(); java.lang.String str64 = oSValidator62.getOS(); boolean boolean65 = oSValidator62.isWindows(); @@ -24725,7 +24641,7 @@ public void test436() throws Throwable { java.lang.Long long30 = octetList28.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element31 = octetList28.createElement(); octetList28.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator33 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator33 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean34 = oSValidator33.isMac(); boolean boolean35 = oSValidator33.isMac(); int int36 = octetList28.lastIndexOf((java.lang.Object) oSValidator33); @@ -24812,7 +24728,7 @@ public void test439() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); uShortList11.ensureCapacity((-11)); @@ -24904,9 +24820,8 @@ public void test440() throws Throwable { java.lang.Process process8 = processExecutionHandler7.getProcess(); java.lang.Long long9 = processExecutionHandler7.getObjId(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks10 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks10, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander13 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler12 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks10, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander13 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process15 = shellCommander13.runCommand("[281475010265083]"); processExecutionHandler12.monitorProcess(process15); processExecutionHandler7.monitorProcess(process15); @@ -24942,7 +24857,7 @@ public void test441() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); java.util.ListIterator uShortItor20 = uShortList11.listIterator(); @@ -24969,7 +24884,7 @@ public void test441() throws Throwable { public void test442() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test442"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); boolean boolean2 = oSValidator0.isSolaris(); java.lang.String str3 = oSValidator0.getOS(); @@ -25008,7 +24923,7 @@ public void test443() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -25070,7 +24985,7 @@ public void test444() throws Throwable { java.util.Spliterator uShortSpliterator33 = uShortList30 .spliterator(); int int34 = shortList24.lastIndexOf((java.lang.Object) uShortList30); - esa.mo.sm.impl.util.ShellCommander shellCommander35 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander35 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str37 = shellCommander35.runCommandAndGetOutputMessage("hi!"); boolean boolean38 = uShortList30.contains((java.lang.Object) str37); org.ccsds.moims.mo.mal.structures.UShort uShort40 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -25149,7 +25064,7 @@ public void test445() throws Throwable { java.util.stream.Stream uRIStream25 = uRIList22.stream(); boolean boolean26 = uRIList22.isEmpty(); int int27 = intList13.indexOf((java.lang.Object) boolean26); - esa.mo.sm.impl.util.ShellCommander shellCommander28 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander28 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process30 = shellCommander28.runCommand("[]"); boolean boolean31 = intList13.equals((java.lang.Object) shellCommander28); int int32 = doubleList1.indexOf((java.lang.Object) intList13); @@ -25171,7 +25086,7 @@ public void test445() throws Throwable { boolean boolean51 = floatList40.remove((java.lang.Object) boolean50); java.lang.String str52 = floatList40.toString(); java.lang.Object obj53 = floatList40.clone(); - esa.mo.sm.impl.util.ShellCommander shellCommander54 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander54 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process56 = shellCommander54.runCommand("[]"); boolean boolean57 = floatList40.equals((java.lang.Object) shellCommander54); int int58 = doubleList1.lastIndexOf((java.lang.Object) floatList40); @@ -25307,11 +25222,9 @@ public void test446() throws Throwable { org.ccsds.moims.mo.mal.structures.URI uRI87 = new org.ccsds.moims.mo.mal.structures.URI(); org.ccsds.moims.mo.mal.structures.UShort uShort88 = uRI87.getServiceNumber(); boolean boolean89 = uRIList66.add(uRI87); - boolean boolean90 = booleanList39.containsAll( - (java.util.Collection) uRIList66); - boolean boolean91 = octetList15.retainAll( - (java.util.Collection) uRIList66); - esa.mo.sm.impl.util.OSValidator oSValidator92 = new esa.mo.sm.impl.util.OSValidator(); + boolean boolean90 = booleanList39.containsAll((java.util.Collection) uRIList66); + boolean boolean91 = octetList15.retainAll((java.util.Collection) uRIList66); + esa.mo.helpertools.misc.OSValidator oSValidator92 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean93 = oSValidator92.isMac(); boolean boolean94 = oSValidator92.isSolaris(); java.lang.String str95 = oSValidator92.getOS(); @@ -25422,7 +25335,7 @@ public void test447() throws Throwable { java.lang.Long long30 = octetList28.getShortForm(); org.ccsds.moims.mo.mal.structures.Element element31 = octetList28.createElement(); octetList28.trimToSize(); - esa.mo.sm.impl.util.OSValidator oSValidator33 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator33 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean34 = oSValidator33.isMac(); boolean boolean35 = oSValidator33.isMac(); int int36 = octetList28.lastIndexOf((java.lang.Object) oSValidator33); @@ -25484,7 +25397,7 @@ public void test448() throws Throwable { java.util.Spliterator uShortSpliterator20 = uShortList17 .spliterator(); int int21 = shortList11.lastIndexOf((java.lang.Object) uShortList17); - esa.mo.sm.impl.util.ShellCommander shellCommander22 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander22 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str24 = shellCommander22.runCommandAndGetOutputMessage("hi!"); boolean boolean25 = uShortList17.contains((java.lang.Object) str24); org.ccsds.moims.mo.mal.structures.UShort uShort27 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -25517,19 +25430,17 @@ public void test449() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test449"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[]"); processExecutionHandler2.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler2.getProcess(); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks12 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler14 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks12, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander15 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler14 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks12, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander15 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process17 = shellCommander15.runCommand("[281475010265083]"); processExecutionHandler14.monitorProcess(process17); java.lang.Process process19 = processExecutionHandler14.getProcess(); @@ -25540,7 +25451,7 @@ public void test449() throws Throwable { callbacks22, (java.lang.Long) 281474993487875L); java.lang.Long long25 = processExecutionHandler24.getObjId(); java.lang.Process process26 = processExecutionHandler24.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander27 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander27 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str29 = shellCommander27.runCommandAndGetOutputMessage("hi!"); java.lang.Process process31 = shellCommander27.runCommand("17"); processExecutionHandler24.monitorProcess(process31); @@ -25583,12 +25494,11 @@ public void test451() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test451"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); - esa.mo.sm.impl.util.ShellCommander shellCommander7 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander7 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process9 = shellCommander7.runCommand("[]"); processExecutionHandler2.monitorProcess(process9); java.lang.Process process11 = processExecutionHandler2.getProcess(); @@ -25599,7 +25509,7 @@ public void test451() throws Throwable { callbacks14, (java.lang.Long) 281474993487875L); java.lang.Long long17 = processExecutionHandler16.getObjId(); java.lang.Process process18 = processExecutionHandler16.getProcess(); - esa.mo.sm.impl.util.ShellCommander shellCommander19 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander19 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str21 = shellCommander19.runCommandAndGetOutputMessage("hi!"); java.lang.Process process23 = shellCommander19.runCommand("17"); processExecutionHandler16.monitorProcess(process23); @@ -25622,14 +25532,13 @@ public void test452() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test452"); esa.mo.sm.impl.provider.ProcessExecutionHandler.Callbacks callbacks0 = null; - esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler( - callbacks0, (java.lang.Long) 281474993487875L); - esa.mo.sm.impl.util.ShellCommander shellCommander3 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.sm.impl.provider.ProcessExecutionHandler processExecutionHandler2 = new esa.mo.sm.impl.provider.ProcessExecutionHandler(callbacks0, (java.lang.Long) 281474993487875L); + esa.mo.helpertools.misc.ShellCommander shellCommander3 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process5 = shellCommander3.runCommand("[281475010265083]"); processExecutionHandler2.monitorProcess(process5); java.lang.Process process7 = processExecutionHandler2.getProcess(); java.lang.Long long8 = processExecutionHandler2.getObjId(); - esa.mo.sm.impl.util.ShellCommander shellCommander9 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander9 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str11 = shellCommander9.runCommandAndGetOutputMessage("hi!"); java.lang.Process process13 = shellCommander9.runCommand("17"); java.lang.Process process15 = shellCommander9.runCommand("uni"); @@ -25653,7 +25562,7 @@ public void test452() throws Throwable { java.util.stream.Stream uRIStream40 = uRIList37.stream(); boolean boolean41 = uRIList37.isEmpty(); int int42 = intList28.indexOf((java.lang.Object) boolean41); - esa.mo.sm.impl.util.ShellCommander shellCommander43 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander43 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.Process process45 = shellCommander43.runCommand("[]"); boolean boolean46 = intList28.equals((java.lang.Object) shellCommander43); java.lang.String str48 = shellCommander43.runCommandAndGetOutputMessage("[10, -1, -1, 10]"); @@ -25788,7 +25697,7 @@ public void test453() throws Throwable { public void test454() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test454"); - esa.mo.sm.impl.util.OSValidator oSValidator0 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator0 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean1 = oSValidator0.isMac(); java.lang.String str2 = oSValidator0.getOS(); java.lang.String str3 = oSValidator0.getOS(); @@ -25958,7 +25867,7 @@ public void test456() throws Throwable { java.lang.Long long8 = uShortList5.getShortForm(); boolean boolean9 = uShortList5.isEmpty(); boolean boolean10 = uShort4.equals((java.lang.Object) uShortList5); - esa.mo.sm.impl.util.OSValidator oSValidator11 = new esa.mo.sm.impl.util.OSValidator(); + esa.mo.helpertools.misc.OSValidator oSValidator11 = new esa.mo.helpertools.misc.OSValidator(); boolean boolean12 = oSValidator11.isMac(); boolean boolean13 = oSValidator11.isWindows(); java.lang.String str14 = oSValidator11.getOS(); @@ -26004,7 +25913,7 @@ public void test457() throws Throwable { java.util.Spliterator uShortSpliterator14 = uShortList11 .spliterator(); int int15 = shortList5.lastIndexOf((java.lang.Object) uShortList11); - esa.mo.sm.impl.util.ShellCommander shellCommander16 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander16 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str18 = shellCommander16.runCommandAndGetOutputMessage("hi!"); boolean boolean19 = uShortList11.contains((java.lang.Object) str18); org.ccsds.moims.mo.mal.structures.UShort uShort21 = new org.ccsds.moims.mo.mal.structures.UShort(2); @@ -26060,7 +25969,7 @@ public void test457() throws Throwable { public void test458() throws Throwable { if (debug) System.out.format("%n%s%n", "RegressionTest0.test458"); - esa.mo.sm.impl.util.ShellCommander shellCommander0 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander0 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str2 = shellCommander0.runCommandAndGetOutputMessage(""); java.lang.Process process4 = shellCommander0.runCommand("281474993487879"); java.lang.String str6 = shellCommander0.runCommandAndGetOutputMessage(""); @@ -26142,7 +26051,7 @@ public void test459() throws Throwable { java.util.Spliterator uShortSpliterator63 = uShortList60 .spliterator(); int int64 = shortList54.lastIndexOf((java.lang.Object) uShortList60); - esa.mo.sm.impl.util.ShellCommander shellCommander65 = new esa.mo.sm.impl.util.ShellCommander(); + esa.mo.helpertools.misc.ShellCommander shellCommander65 = new esa.mo.helpertools.misc.ShellCommander(); java.lang.String str67 = shellCommander65.runCommandAndGetOutputMessage("hi!"); boolean boolean68 = uShortList60.contains((java.lang.Object) str67); uShortList60.ensureCapacity((-11)); diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java index 1742b6357..8cf8b3e19 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java @@ -46,8 +46,8 @@ import esa.mo.nmf.annotations.ActionParameter; import esa.mo.nmf.annotations.Parameter; import esa.mo.nmf.nanosatmosupervisor.parameter.OBSWParameterManager; -import esa.mo.sm.impl.util.OSValidator; -import esa.mo.sm.impl.util.ShellCommander; +import esa.mo.helpertools.misc.OSValidator; +import esa.mo.helpertools.misc.ShellCommander; import org.ccsds.moims.mo.mal.structures.Attribute; import org.ccsds.moims.mo.mal.structures.Duration; import org.ccsds.moims.mo.mal.structures.Identifier; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index c573e0580..be0099b33 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -24,7 +24,7 @@ import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; -import esa.mo.sm.impl.util.OSValidator; +import esa.mo.helpertools.misc.OSValidator; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index 46b70f03e..696507479 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -36,6 +36,9 @@ import org.ccsds.moims.mo.platform.softwaredefinedradio.provider.SoftwareDefinedRadioInheritanceSkeleton; import esa.mo.com.impl.util.COMServicesProvider; +import esa.mo.platform.impl.provider.adapters.ArtificialIntelligenceIntelMovidiusAdapter; +import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceAdapterInterface; +import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceProviderServiceImpl; import esa.mo.platform.impl.provider.gen.AutonomousADCSAdapterInterface; import esa.mo.platform.impl.provider.gen.AutonomousADCSProviderServiceImpl; import esa.mo.platform.impl.provider.gen.CameraAdapterInterface; @@ -59,18 +62,45 @@ */ public class PlatformServicesProviderSoftSim implements PlatformServicesProviderInterface { - // Simulator - private final ESASimulator instrumentsSimulator = new ESASimulator("127.0.0.1"); + // Simulator + private final ESASimulator instrumentsSimulator = new ESASimulator("127.0.0.1"); - // Services - private final AutonomousADCSProviderServiceImpl autonomousADCSService = new AutonomousADCSProviderServiceImpl(); - private final CameraProviderServiceImpl cameraService = new CameraProviderServiceImpl(); - private final GPSProviderServiceImpl gpsService = new GPSProviderServiceImpl(); - private final OpticalDataReceiverProviderServiceImpl opticalDataReceiverService = new OpticalDataReceiverProviderServiceImpl(); - private final SoftwareDefinedRadioProviderServiceImpl sdrService = new SoftwareDefinedRadioProviderServiceImpl(); - private final PowerControlProviderServiceImpl powerService = new PowerControlProviderServiceImpl(); - private PowerControlAdapterInterface pcAdapter; - private final ClockProviderServiceImpl clockService = new ClockProviderServiceImpl(); + // Services + private final ArtificialIntelligenceProviderServiceImpl aiService = new ArtificialIntelligenceProviderServiceImpl(); + private final AutonomousADCSProviderServiceImpl autonomousADCSService = new AutonomousADCSProviderServiceImpl(); + private final CameraProviderServiceImpl cameraService = new CameraProviderServiceImpl(); + private final GPSProviderServiceImpl gpsService = new GPSProviderServiceImpl(); + private final OpticalDataReceiverProviderServiceImpl opticalDataReceiverService = new OpticalDataReceiverProviderServiceImpl(); + private final SoftwareDefinedRadioProviderServiceImpl sdrService = new SoftwareDefinedRadioProviderServiceImpl(); + private final PowerControlProviderServiceImpl powerService = new PowerControlProviderServiceImpl(); + private PowerControlAdapterInterface pcAdapter; + private final ClockProviderServiceImpl clockService = new ClockProviderServiceImpl(); + + public void init(COMServicesProvider comServices) throws MALException { + // Check if hybrid setup is used + CameraAdapterInterface camAdapter; + ArtificialIntelligenceIntelMovidiusAdapter aiAdapter; + AutonomousADCSAdapterInterface adcsAdapter; + GPSAdapterInterface gpsAdapter; + OpticalDataReceiverAdapterInterface optRxAdapter; + SoftwareDefinedRadioAdapterInterface sdrAdapter; + ClockAdapterInterface clockAdapter; + + Properties platformProperties = new Properties(); + try { + platformProperties.load(new FileInputStream("platformsim.properties")); + if (platformProperties.getProperty("platform.mode").equals("hybrid")) { + String pcAdapterName = platformProperties.getProperty("pc.adapter"); + String camAdapterName = platformProperties.getProperty("camera.adapter"); + String adcsAdapterName = platformProperties.getProperty("adcs.adapter"); + String gpsAdapterName = platformProperties.getProperty("gps.adapter"); + String optRxAdapterName = platformProperties.getProperty("optrx.adapter"); + String sdrAdapterName = platformProperties.getProperty("sdr.adapter"); + String clockAdapterName = platformProperties.getProperty("clock.adapter"); + + // PowerControl adapter + try { + pcAdapter = (PowerControlAdapterInterface) Class.forName(pcAdapterName).newInstance(); public void init(COMServicesProvider comServices) throws MALException { // Check if hybrid setup is used @@ -238,15 +268,49 @@ public void init(COMServicesProvider comServices) throws MALException { sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); } + aiAdapter = null; + } else { + pcAdapter = new PowerControlSoftSimAdapter(); + camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); + aiAdapter = new ArtificialIntelligenceIntelMovidiusAdapter(); + adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); + gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); + optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); + sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); + clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); + } + } catch (IOException e) { + // Assume simulated environment by default + Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, + "Platform config file not found. Using simulated environment."); + pcAdapter = new PowerControlSoftSimAdapter(); + camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); + try { + aiAdapter = new ArtificialIntelligenceIntelMovidiusAdapter(); + } catch (IOException ex) { + Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log( + Level.SEVERE, "The AI adapter could not be started!", ex); + + aiAdapter = null; + } + adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); + gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); + optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); + sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); + clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); + } - autonomousADCSService.init(comServices, adcsAdapter); - cameraService.init(comServices, camAdapter); - gpsService.init(comServices, gpsAdapter); - opticalDataReceiverService.init(optRxAdapter); - sdrService.init(sdrAdapter); - powerService.init(pcAdapter); - clockService.init(clockAdapter); + autonomousADCSService.init(comServices, adcsAdapter); + if(aiAdapter != null) { + aiService.init(aiAdapter); } + cameraService.init(comServices, camAdapter); + gpsService.init(comServices, gpsAdapter); + opticalDataReceiverService.init(optRxAdapter); + sdrService.init(sdrAdapter); + powerService.init(pcAdapter); + clockService.init(clockAdapter); + } public void startStatusTracking(ConnectionConsumer connection) { pcAdapter.startStatusTracking(connection); From ba13fc43cba07aca354d43ca93c97158555de042 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 27 May 2022 21:07:42 +0200 Subject: [PATCH 064/173] [com-archive] Faster overall startup with the delegation of the database backend to a seperate thread --- .../mo/com/impl/provider/ArchiveManager.java | 28 +++++++++---------- .../NanoSatMOConnectorImpl.java | 1 + 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java index 7717e7117..a579d5cba 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java @@ -129,21 +129,21 @@ public ArchiveManager(EventProviderServiceImpl eventService) { } public synchronized void init() { - this.dbBackend.startBackendDatabase(this.dbProcessor); - - Future f = this.dbProcessor.submitExternalTransactionExecutorTask(() -> { - LOGGER.log(Level.FINE, "Initializing Fast classes!"); - fastDomain.init(); - fastObjectType.init(); - fastNetwork.init(); - fastProviderURI.init(); - LOGGER.log(Level.FINE, "The Fast classes are initialized!"); + final ArchiveManager manager = this; + + this.dbProcessor.submitExternalTransactionExecutorTask(() -> { + synchronized (manager) { + this.dbBackend.startBackendDatabase(this.dbProcessor); + Logger.getLogger(ArchiveManager.class.getName()).log(Level.FINE, + "Initializing Fast classes!"); + fastDomain.init(); + fastObjectType.init(); + fastNetwork.init(); + fastProviderURI.init(); + Logger.getLogger(ArchiveManager.class.getName()).log(Level.FINE, + "The Fast classes are initialized!"); + } }); - try { - f.get(); - } catch (InterruptedException | ExecutionException e) { - LOGGER.log(Level.SEVERE, "Failed to init the archive", e); - } } /** diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 154a66dfb..50a02e799 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -48,6 +48,7 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.com.COMService; From 626a4a0f11188596fcf2a6c0c472046556d4ed42 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 27 May 2022 22:39:38 +0200 Subject: [PATCH 065/173] [com-archive] Optimization for faster stores in the database. --- .../archive/db/TransactionsProcessor.java | 17 +++++------ .../mo/com/impl/provider/ArchiveManager.java | 8 ++--- .../provider/EventProviderServiceImpl.java | 29 ++++++------------- 3 files changed, 21 insertions(+), 33 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java index d9266d511..dcbec11fc 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java @@ -54,8 +54,9 @@ * consolidated and executed in one single transaction. */ public class TransactionsProcessor { - public static final Logger LOGGER = Logger.getLogger(TransactionsProcessor.class.getName()); - final DatabaseBackend dbBackend; + + public static Logger LOGGER = Logger.getLogger(TransactionsProcessor.class.getName()); + public final DatabaseBackend dbBackend; // This executor is responsible for the interactions with the db // Guarantees sequential order @@ -76,16 +77,14 @@ public TransactionsProcessor(DatabaseBackend dbBackend) { this.sequencialStoring = new AtomicBoolean(false); } - public Future submitExternalGeneralExecutorTask(final Runnable task) { + public void submitExternalTaskGeneral(final Runnable task) { this.sequencialStoring.set(false); // Sequential stores can no longer happen otherwise we break order - - return generalExecutor.submit(task); + generalExecutor.execute(task); } - public Future submitExternalTransactionExecutorTask(final Runnable task) { + public void submitExternalTaskDBTransactions(final Runnable task) { this.sequencialStoring.set(false); // Sequential stores can no longer happen otherwise we break order - - return dbTransactionsExecutor.submit(task); + dbTransactionsExecutor.execute(task); } public Future submitExternalTransactionExecutorTask(final Callable task) { @@ -195,7 +194,7 @@ public void insert(final ArrayList perObjs, final Runnable publ } catch (InterruptedException ex) { Logger.getLogger(ArchiveManager.class.getName()).log(Level.SEVERE, "Something went wrong...", ex); } - + dbTransactionsExecutor.execute(new RunnableInsert(this, publishEvents)); } diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java index a579d5cba..3aece9dde 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java @@ -38,8 +38,6 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -79,6 +77,7 @@ * @author Cesar Coelho */ public class ArchiveManager { + public static final Logger LOGGER = Logger.getLogger(ArchiveManager.class.getName()); private final DatabaseBackend dbBackend; @@ -110,7 +109,8 @@ public ArchiveManager(EventProviderServiceImpl eventService) { ArchiveHelper.ARCHIVE_SERVICE_NAME) == null) { try { ArchiveHelper.init(MALContextFactory.getElementFactoryRegistry()); - } catch (MALException ex) { + } + catch (MALException ex) { LOGGER.log(Level.SEVERE, "Unexpectedly ArchiveHelper already initialized!?", ex); } } @@ -131,7 +131,7 @@ public ArchiveManager(EventProviderServiceImpl eventService) { public synchronized void init() { final ArchiveManager manager = this; - this.dbProcessor.submitExternalTransactionExecutorTask(() -> { + this.dbProcessor.submitExternalTaskDBTransactions(() -> { synchronized (manager) { this.dbBackend.startBackendDatabase(this.dbProcessor); Logger.getLogger(ArchiveManager.class.getName()).log(Level.FINE, diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java index 44cf66b19..05a9698be 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java @@ -396,20 +396,20 @@ public LongList generateAndStoreEvents(final ObjectType objType, final Identifie ObjectDetailsList objectDetailsList = new ObjectDetailsList(sourceList.size()); for (int i = 0; i < sourceList.size(); i++) { - if (relateds != null) { - objectDetailsList.add(new ObjectDetails(relateds.get(i), sourceList.get(i))); - } else { - objectDetailsList.add(new ObjectDetails(null, sourceList.get(i))); - } + Long related = (relateds != null) ? relateds.get(i) : null; + objectDetailsList.add(new ObjectDetails(related, sourceList.get(i))); } ElementList events = null; - Identifier network = null; - URI uri = null; + Identifier network; + URI uri; if (interaction != null) { network = interaction.getMessageHeader().getNetworkZone(); uri = interaction.getMessageHeader().getURIFrom(); + }else{ + network = ConfigurationProviderSingleton.getNetwork(); + uri = connection.getConnectionDetails().getProviderURI(); } if (this.archiveService == null) { @@ -423,19 +423,8 @@ public LongList generateAndStoreEvents(final ObjectType objType, final Identifie archiveDetails.setDetails(objectDetailsList.get(i)); archiveDetails.setInstId(0L); // no need to worry about objIds archiveDetails.setTimestamp(HelperTime.getTimestamp()); - - if (network != null) { - archiveDetails.setNetwork(network); - } else { - archiveDetails.setNetwork(ConfigurationProviderSingleton.getNetwork()); - } - - if (uri != null) { - archiveDetails.setProvider(uri); - } else { - archiveDetails.setProvider(connection.getConnectionDetails().getProviderURI()); - } - + archiveDetails.setNetwork(network); + archiveDetails.setProvider(uri); archiveDetailsList.add(archiveDetails); } From 3b3b3ae4db0a3a866f2b009f75ec9e3855ad8cc0 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 21 Jun 2022 14:01:45 +0200 Subject: [PATCH 066/173] [ai-service] Small fixes to support better handling. --- .../ArtificialIntelligenceIntelMovidiusAdapter.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java index ead1ffe5d..1b533fe6d 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java @@ -49,7 +49,7 @@ public ArtificialIntelligenceIntelMovidiusAdapter() throws IOException { String out = shellCommander.runCommandAndGetOutputMessage(cmdPython); String[] splits = out.split("Python "); - if (splits.length == 0) { + if (splits.length <= 1) { throw new IOException("The Python version could not be determined!" + " The command returned: " + out); } @@ -112,9 +112,15 @@ private File findPathToFile(File path, String toBeMatched) { if (path.isFile()) { return toBeMatched.equals(path.getName()) ? path : null; } + + File[] list = path.listFiles(); + + if(list == null) { + return null; + } // It is a directory... crawl through it - for (File entry : path.listFiles()) { + for (File entry : list) { File file = findPathToFile(entry, toBeMatched); if (file != null) { return file; From 5f6bf9335d4cd6d89fe38a5f9eb269f9b0efc080 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 14 Aug 2022 14:48:26 +0200 Subject: [PATCH 067/173] Updates the README with clear instructions to get started --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c48e6c535..e21280442 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # NanoSat MO Framework -The [NanoSat MO Framework] is a software framework for nanosatellites based on CCSDS Mission Operations services. +The [NanoSat MO Framework] is a software framework for small satellites based on CCSDS Mission Operations services. It introduces the concept of apps in space that can be started and stopped from ground. Apps can retrieve data from the platform through a set of well-defined MO services. Many possibilities for extensions are available due to its modular and flexible design approach which is not limited to the space segment but extends down to ground by providing all the building blocks for a complete and free end-to-end solution. @@ -21,34 +21,35 @@ The research was carried by Graz University of Technology in partnership with th ## Release The latest NMF SDK release tag can be downloaded in [Releases]. However, the currently recommended distribution channel is directly from Git repository. -## Building +## Building Prerequisites -Prerequisites: - -1. Java SDK 1.8 (will work with higher SDKs but 1.8 is the recommended) +1. Install Java SDK 1.8 (will work with higher SDKs but 1.8 is the recommended) ```bash sudo apt-get install openjdk-8-jdk ``` -2. Apache Maven +2. Install Apache Maven ```bash sudo apt-get install maven ``` -Instructions: +## Building Instructions -1. Clone this repository +3. Clone this repository +```bash +git clone https://github.com/esa/nanosat-mo-framework.git +``` -2. Set the environment variable NMF\_HOME with the path to this repository's root directory +4. Set the environment variable NMF\_HOME with the path to this repository's root directory ```bash export NMF_HOME=path_to_repository ``` -3. Compile the NMF using: +5. Build the cloned NanoSat MO Framework project: ```bash -mvn install +mvn clean install ``` -Note that the errors about missing module descriptors during Javadoc generation are to be expected and non breaking. +Note that the errors about missing module descriptors during Javadoc generation are to be expected and non-breaking. In order to produce independently runnable Java executables (JAR artifacts with dependencies - equivalent of statically linked executables), use `mvn install -P assembly-with-dependencies` From 39eb17d42a35d6062ef823bdb0f45bd2a69c6e43 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 14 Aug 2022 14:52:26 +0200 Subject: [PATCH 068/173] Updates the Banner code to be printed via the LOGGER instead of the System.out.println --- .../NanoSatMOConnectorImpl.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 50a02e799..030654049 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -96,25 +96,7 @@ public class NanoSatMOConnectorImpl extends NMFProvider { @Override public void init(final MonitorAndControlNMFAdapter mcAdapter) { super.startTime = System.currentTimeMillis(); - - Properties p = System.getProperties(); - StringBuilder java = new StringBuilder(); - java.append(p.getProperty("java.runtime.name", "?")); - java.append(" (version: "); - java.append(p.getProperty("java.runtime.version", "?")); - java.append(")"); - - StringBuilder os = new StringBuilder(); - os.append(p.getProperty("os.name", "?")); - os.append(" (version: "); - os.append(p.getProperty("os.version", "?")); - os.append(")"); - - System.out.println(SEPARATOR); - System.out.println("NanoSat MO Framework"); - System.out.println("OS: " + os.toString()); - System.out.println("Java: " + java.toString()); - System.out.println(SEPARATOR); + LOGGER.log(Level.INFO, this.generateStartBanner()); HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties ConnectionProvider.resetURILinks(); // Resets the providerURIs.properties file From f95aa0b0494cb3a2e95c8a8adf341be7b9499a8a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 14 Aug 2022 15:13:07 +0200 Subject: [PATCH 069/173] Fixes data type problems with nulls --- .../ParameterProviderServiceImpl.java | 29 +-- .../commonmoadapter/CommonMOAdapterImpl.java | 185 +++++++++++++++++- 2 files changed, 195 insertions(+), 19 deletions(-) diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java index e2d71df8b..6b1e8dc81 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java @@ -30,7 +30,6 @@ import esa.mo.mc.impl.util.MCServicesHelper; import esa.mo.reconfigurable.service.ConfigurationChangeListener; import esa.mo.reconfigurable.service.ReconfigurableService; - import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; @@ -138,8 +137,8 @@ public synchronized void init(ParameterManager parameterManager) throws MALExcep MCHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(MCHelper.MC_AREA_NAME, MCHelper.MC_AREA_VERSION).getServiceByName( - ParameterHelper.PARAMETER_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(MCHelper.MC_AREA_NAME, MCHelper.MC_AREA_VERSION) + .getServiceByName(ParameterHelper.PARAMETER_SERVICE_NAME) == null) { ParameterHelper.init(MALContextFactory.getElementFactoryRegistry()); } @@ -361,7 +360,8 @@ public void setValue(final ParameterRawValueList rawValueList, final MALInteract } // requirement: 3.3.9.2.f the new rawValues type and its definitions rawType must be the same - if (!newValue.getRawValue().getTypeShortForm().equals(Integer.valueOf(pDef.getRawType()))) { + if (newValue.getRawValue() != null + && !newValue.getRawValue().getTypeShortForm().equals(new Integer(pDef.getRawType()))) { invIndexList.add(new UInteger(index)); continue; } @@ -517,8 +517,10 @@ public ObjectInstancePairList addParameter(final ParameterCreationRequestList pa details.add(tempParameterCreationRequest.getParamDefDetails()); } - ObjectInstancePairList objectInstancePairs = manager.addMultiple(names, details, source, connection - .getConnectionDetails()); + ObjectInstancePairList objectInstancePairs = manager.addMultiple(names, + details, + source, + connection.getConnectionDetails()); //store the objects outPairLst.addAll(objectInstancePairs); // requirement: 3.3.12.2.g // Refresh the Periodic Reporting Manager for the added Definitions @@ -715,7 +717,8 @@ public Boolean reloadConfiguration(ConfigurationObjectDetails configurationObjec periodicReportingManager.pause(); - manager.reconfigureDefinitions(confSetIdents.getObjInstIds(), idents, confSetDefs.getObjInstIds(), pDefs); // Reconfigures the Manager + manager.reconfigureDefinitions(confSetIdents.getObjInstIds(), idents, + confSetDefs.getObjInstIds(), pDefs); // Reconfigures the Manager periodicReportingManager.refreshAll(); // Refresh the reporting periodicReportingManager.start(); @@ -1016,8 +1019,8 @@ public Boolean pushMultipleParameterValues(final List paramet // If the conversion value was not provided, we can try to generate it if (parameters.get(i).getParameterValue().getConvertedValue() == null) { - ParameterValue newPVal = manager.generateNewParameterValue(parameters.get(i).getParameterValue() - .getRawValue(), pDef2, false); + ParameterValue newPVal = manager.generateNewParameterValue( + parameters.get(i).getParameterValue().getRawValue(), pDef2, false); parameters.get(i).getParameterValue().setConvertedValue(newPVal.getConvertedValue()); parameters.get(i).getParameterValue().setValidityState(newPVal.getValidityState()); } @@ -1042,8 +1045,9 @@ public Boolean pushMultipleParameterValues(final List paramet for (int i = 0; i < outIds.size(); i++) { relatedIds.add(outIds.get(i).getObjDefInstanceId()); sourceIds.add(parameters.get(i).getSource()); - final FineTime timestamp = (parameters.get(i).getTimestamp() != null) ? HelperTime.timeToFineTime( - parameters.get(i).getTimestamp()) : defaultTimestamp; + final FineTime timestamp = (parameters.get(i).getTimestamp() != null) + ? HelperTime.timeToFineTime(parameters.get(i).getTimestamp()) + : defaultTimestamp; timestamps.add(timestamp); } @@ -1103,7 +1107,8 @@ private void publishPeriodicParameterUpdate(final Long identityId) { * publishes a periodic parameter update for the given parameter * * @param identityId the id of the parameter identity - * @param storeInCOMArchive flag indicating whether or not the parameter should be stored in the archive + * @param storeInCOMArchive flag indicating whether or not the parameter + * should be stored in the archive */ private void publishPeriodicParameterUpdate(final Long identityId, boolean storeInCOMArchive) { try { diff --git a/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java b/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java index e2017289e..063ef2d39 100644 --- a/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java +++ b/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java @@ -102,13 +102,184 @@ public class CommonMOAdapterImpl extends NMFConsumer implements SimpleCommanding private Subscription parameterSubscription = null; private Subscription aggregationSubscription = null; - /** - * The constructor of this class - * - * @param connection The connection details of the provider - */ - public CommonMOAdapterImpl(final ConnectionConsumer connection) { - this(connection, null, null); + /** + * The constructor of this class + * + * @param connection The connection details of the provider + */ + public CommonMOAdapterImpl(final ConnectionConsumer connection) + { + this(connection, null, null); + } + + /** + * The constructor of this class + * + * @param connection The connection details of the provider + * @param authenticationId authenticationId of the logged in user + * @param localNamePrefix the prefix for the local name of the consumer + */ + public CommonMOAdapterImpl(final ConnectionConsumer connection, final Blob authenticationId, final String localNamePrefix) + { + super(connection, authenticationId, localNamePrefix); + super.init(); + } + + /** + * The constructor of this class + * + * @param providerDetails The Provider details. This object can be obtained from the Directory + * service + */ + public CommonMOAdapterImpl(final ProviderSummary providerDetails) + { + this(providerDetails, null, null); + } + + /** + * The constructor of this class + * + * @param providerDetails The Provider details. This object can be obtained from the Directory + * service + * @param authenticationId authenticationId of the logged in user + * @param localNamePrefix the prefix for the local name of the consumer + */ + public CommonMOAdapterImpl(final ProviderSummary providerDetails, final Blob authenticationId, final String localNamePrefix) + { + super(providerDetails, authenticationId, localNamePrefix); + super.init(); + } + + @Override + public void setParameter(final String parameterName, final Serializable content) + { + // Check if the parameter exists + IdentifierList parameters = new IdentifierList(1); + parameters.add(new Identifier(parameterName)); + + // If it is java type, then convert it to Attribute + Object midValue = HelperAttributes.javaType2Attribute(content); + Attribute rawValue; + + if (midValue instanceof Attribute) { // Is the parameter MAL type or something else? + rawValue = (Attribute) midValue; + } else { + try { + // Well, if it is something else, then it will have to serialize it and put it inside a Blob + rawValue = HelperAttributes.serialObject2blobAttribute(content); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return; + } + } + + ParameterStub parameterService = super.getMCServices().getParameterService().getParameterStub(); + + try { + ObjectInstancePairList objIds = parameterService.listDefinition(parameters); + + if (objIds == null) { + return; // something went wrong... Connection problem? + } + + ObjectInstancePair objId = objIds.get(0); + + // If the definition does not exist, then create it automatically for the user + if (objId == null) { + // Well, then let's create a new Parameter Definition and add it on the provider... + ParameterDefinitionDetails parameterDefinition = new ParameterDefinitionDetails(); + parameterDefinition.setDescription( + "This Definition was automatically generated by: " + CommonMOAdapterImpl.class.getName()); + + if (rawValue instanceof Attribute) { // Is the parameter MAL type or something else? + parameterDefinition.setRawType(((Attribute) midValue).getTypeShortForm().byteValue()); + } else { + parameterDefinition.setRawType(HelperAttributes.SERIAL_OBJECT_RAW_TYPE); + } + + parameterDefinition.setRawUnit(null); + parameterDefinition.setGenerationEnabled(false); + parameterDefinition.setReportInterval(new Duration(0)); + parameterDefinition.setValidityExpression(null); + parameterDefinition.setConversion(null); + + ParameterCreationRequestList request = new ParameterCreationRequestList(1); + request.add(new ParameterCreationRequest(new Identifier(parameterName), parameterDefinition)); + + // Now, add the definition to the service provider + objIds = parameterService.addParameter(request); + } + + // Continues here... + ParameterRawValueList raws = new ParameterRawValueList(); + Long objIdInsID = objIds.get(0).getObjIdentityInstanceId(); + rawValue = (content == null) ? null : rawValue; + raws.add(new ParameterRawValue(objIdInsID, rawValue)); + + // Ok, now, let's finally set the Value! + parameterService.setValue(raws); + } catch (MALInteractionException ex) { + LOGGER.log(Level.SEVERE, "The parameter could not be set!", ex); + } catch (MALException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + } + + @Override + public void addDataReceivedListener(final DataReceivedListener listener) + { + // Make the parameter adapter to call the receiveDataListener when there's a new object available + class DataReceivedParameterAdapter extends ParameterAdapter + { + + @Override + public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, + final Identifier lIdentifier, final UpdateHeaderList lUpdateHeaderList, + final ObjectIdList lObjectIdList, final ParameterValueList lParameterValueList, + final Map qosp) + { + + if (lParameterValueList.size() == lUpdateHeaderList.size()) { + for (int i = 0; i < lUpdateHeaderList.size(); i++) { + String parameterName = lUpdateHeaderList.get(i).getKey().getFirstSubKey().toString(); + Attribute parameterValue = lParameterValueList.get(i).getRawValue(); + Serializable object; + + // Is it a Blob? + if (parameterValue instanceof Blob) { + // If so, try to unserialize it + try { + object = HelperAttributes.blobAttribute2serialObject((Blob) parameterValue); + } catch (IOException ex) { + // Didn't work? Well, maybe it is just a normal Blob... + object = (Serializable) HelperAttributes.attribute2JavaType(parameterValue); + } + } else { + // Not a Blob? + // Then make it a Java type if possible + object = (Serializable) HelperAttributes.attribute2JavaType(parameterValue); + } + + // Push the data to the user interface + // Simple interface + if (listener instanceof SimpleDataReceivedListener) { + ((SimpleDataReceivedListener) listener).onDataReceived(parameterName, object); + } + + // Complete interface + if (listener instanceof CompleteDataReceivedListener) { + ObjectId source = lObjectIdList.get(i); + Time timestamp = lUpdateHeaderList.get(i).getTimestamp(); + + ParameterInstance parameterInstance = new ParameterInstance(new Identifier( + parameterName), + lParameterValueList.get(i), source, timestamp); + + ((CompleteDataReceivedListener) listener).onDataReceived(parameterInstance); + } + } + } + } } /** From 8332b8174f279bf8e205a4101fae48cce313d9bb Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 22 Sep 2022 17:09:31 +0200 Subject: [PATCH 070/173] Adds a preprocess operation to the Camera service. Updates the CameraSettings structure to include an extra field. --- .../gen/CameraProviderServiceImpl.java | 7 ++ .../main/resources/xml/ServiceDefPLATFORM.xml | 41 +++++++++ .../CameraAcquisitorSystemCameraHandler.java | 85 +++++++++++-------- .../esa/mo/nmf/apps/MCSnapNMFAdapter.java | 38 ++++++--- .../nmf/apps/PayloadsTestActionsHandler.java | 68 +++++++++------ .../mo/PictureProcessorMCAdapter.java | 4 +- 6 files changed, 169 insertions(+), 74 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java index 23e58d22f..27883795c 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java @@ -57,6 +57,7 @@ import org.ccsds.moims.mo.platform.camera.body.GetPropertiesResponse; import org.ccsds.moims.mo.platform.camera.provider.CameraInheritanceSkeleton; import org.ccsds.moims.mo.platform.camera.provider.PicturesStreamPublisher; +import org.ccsds.moims.mo.platform.camera.provider.PreprocessPictureInteraction; import org.ccsds.moims.mo.platform.camera.provider.TakeAutoExposedPictureInteraction; import org.ccsds.moims.mo.platform.camera.provider.TakePictureInteraction; import org.ccsds.moims.mo.platform.camera.structures.CameraSettings; @@ -359,6 +360,12 @@ public GetPropertiesResponse getProperties(MALInteraction interaction) throws return new GetPropertiesResponse(availableResolutions, availableFormats, extraInfo); } + @Override + public void preprocessPicture(Picture inputPicture, CameraSettings settings, + PreprocessPictureInteraction interaction) throws MALInteractionException, MALException { + throw new UnsupportedOperationException("Not supported yet."); + } + public static final class PublishInteractionListener implements MALPublishInteractionListener { @Override diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index f3084bbc2..b0e906127 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -277,6 +277,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java b/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java index 511f52526..823131f9c 100644 --- a/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java +++ b/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java @@ -237,41 +237,54 @@ public void takePictureResponseErrorReceived(org.ccsds.moims.mo.mal.transport.MA } } } - - /** - * Takes a photograph (instantly) - * - * @param actionInstanceObjId the Instance ID of the action that triggers the Photograph - * @param stageOffset number of states that where already executed before taking a - * photograph - * @param totalStages total number of Stages (including all stages needed for a - * photograph) - * @param fileName a text that is added at the end of the filename (before the file - * ending) - * @throws NMFException - * @throws IOException - * @throws MALInteractionException - * @throws MALException - */ - public void takePhotograph(long actionInstanceObjId, int stageOffset, int totalStages, String fileName) - throws NMFException, IOException, MALInteractionException, MALException { - PixelResolution resolution = new PixelResolution(new UInteger(casMCAdapter.getPictureWidth()), new UInteger( - casMCAdapter.getPictureHeight())); - - CameraAdapter adapter = new CameraDataHandler(actionInstanceObjId, stageOffset, totalStages, fileName, - this.casMCAdapter); - - CameraSettings settings = new CameraSettings(resolution, casMCAdapter.getPictureType(), new Duration( - casMCAdapter.getExposureTime()), casMCAdapter.getGainRed(), casMCAdapter.getGainGreen(), casMCAdapter - .getGainBlue()); - - if (casMCAdapter.getExposureType() == CameraAcquisitorSystemMCAdapter.ExposureTypeModeEnum.AUTOMATIC) { - LOGGER.log(Level.INFO, "Taking Photograph with automatic exposure"); - this.casMCAdapter.getConnector().getPlatformServices().getCameraService().takeAutoExposedPicture(settings, - adapter); - } else { - LOGGER.log(Level.INFO, "Taking Photograph with manual exposure"); - this.casMCAdapter.getConnector().getPlatformServices().getCameraService().takePicture(settings, adapter); - } + } + + /** + * Takes a photograph (instantly) + * + * @param actionInstanceObjId the Instance ID of the action that triggers the Photograph + * @param stageOffset number of states that where already executed before taking a + * photograph + * @param totalStages total number of Stages (including all stages needed for a + * photograph) + * @param fileName a text that is added at the end of the filename (before the file + * ending) + * @throws NMFException + * @throws IOException + * @throws MALInteractionException + * @throws MALException + */ + public void takePhotograph(long actionInstanceObjId, int stageOffset, int totalStages, + String fileName) throws + NMFException, + IOException, + MALInteractionException, + MALException + { + PixelResolution resolution = new PixelResolution( + new UInteger(casMCAdapter.getPictureWidth()), + new UInteger(casMCAdapter.getPictureHeight())); + + CameraAdapter adapter = new CameraDataHandler(actionInstanceObjId, stageOffset, totalStages, + fileName, + this.casMCAdapter); + + CameraSettings settings = new CameraSettings( + resolution, + casMCAdapter.getPictureType(), + new Duration(casMCAdapter.getExposureTime()), + casMCAdapter.getGainRed(), + casMCAdapter.getGainGreen(), + casMCAdapter.getGainBlue(), + null); + + if (casMCAdapter.getExposureType() == CameraAcquisitorSystemMCAdapter.ExposureTypeModeEnum.AUTOMATIC) { + LOGGER.log(Level.INFO, "Taking Photograph with automatic exposure"); + this.casMCAdapter.getConnector().getPlatformServices().getCameraService() + .takeAutoExposedPicture(settings, adapter); + } else { + LOGGER.log(Level.INFO, "Taking Photograph with manual exposure"); + this.casMCAdapter.getConnector().getPlatformServices().getCameraService() + .takePicture(settings, adapter); } } diff --git a/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java b/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java index c9a941595..3c84e13d6 100644 --- a/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java +++ b/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java @@ -70,16 +70,34 @@ public class MCSnapNMFAdapter extends MonitorAndControlNMFAdapter { private static final String ACTION_TAKE_PICTURE_RAW = "TakeSnap.RAW"; private static final String ACTION_TAKE_PICTURE_JPG = "TakeSnap.JPG"; - private final AtomicInteger snapsTaken = new AtomicInteger(0); - private final int width = 2048; - private final int height = 1944; - private final int TOTAL_STAGES = 3; - private final float DEFAULT_GAIN_R = 10; - private final float DEFAULT_GAIN_G = 8; - private final float DEFAULT_GAIN_B = 10; - - public void setNMF(NMFInterface connector) { - this.connector = connector; + PixelResolution resolution = new PixelResolution(new UInteger(width), new UInteger(height)); + + if (ACTION_TAKE_PICTURE_RAW.equals(name.getValue())) { + try { + DataReceivedAdapter adapter = new DataReceivedAdapter(actionInstanceObjId); + connector.getPlatformServices().getCameraService().takePicture( + new CameraSettings(resolution, PictureFormat.RAW, new Duration(0.200), + DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B, null), + adapter + ); + return null; // Success! + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, null, ex); + } + } + + if (ACTION_TAKE_PICTURE_JPG.equals(name.getValue())) { + try { + DataReceivedAdapter adapter = new DataReceivedAdapter(actionInstanceObjId); + connector.getPlatformServices().getCameraService().takePicture( + new CameraSettings(resolution, PictureFormat.JPG, new Duration(0.200), + DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B, null), + adapter + ); + return null; // Success! + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, null, ex); + } } @Override diff --git a/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java b/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java index a4f1a95c3..6607ba337 100644 --- a/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java +++ b/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java @@ -130,34 +130,50 @@ public void run() { return null; // Success! } - public UInteger takePicture(Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction, - PictureFormat format) { - try { - payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takePicture(new CameraSettings( - payloadsTestMCAdapter.defaultCameraResolution, format, new Duration( - payloadsTestMCAdapter.cameraExposureTime), payloadsTestMCAdapter.cameraGainR, - payloadsTestMCAdapter.cameraGainG, payloadsTestMCAdapter.cameraGainB), - new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); - return null; // Success! - } catch (MALInteractionException | MALException | IOException | NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); - return new UInteger(1); - } + public UInteger takePicture( + Long actionInstanceObjId, + boolean reportProgress, + MALInteraction interaction, + PictureFormat format) + { + try { + payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takePicture( + new CameraSettings( + payloadsTestMCAdapter.defaultCameraResolution, + format, + new Duration(payloadsTestMCAdapter.cameraExposureTime), + payloadsTestMCAdapter.cameraGainR, + payloadsTestMCAdapter.cameraGainG, + payloadsTestMCAdapter.cameraGainB, + null), + new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); + return null; // Success! + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return new UInteger(1); } - public UInteger takeAutoExposedPicture(Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction, - PictureFormat format) { - try { - payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takeAutoExposedPicture( - new CameraSettings(payloadsTestMCAdapter.defaultCameraResolution, format, new Duration( - payloadsTestMCAdapter.cameraExposureTime), payloadsTestMCAdapter.cameraGainR, - payloadsTestMCAdapter.cameraGainG, payloadsTestMCAdapter.cameraGainB), - new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); - return null; // Success! - } catch (MALInteractionException | MALException | IOException | NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); - return new UInteger(1); - } + public UInteger takeAutoExposedPicture( + Long actionInstanceObjId, + boolean reportProgress, + MALInteraction interaction, + PictureFormat format) + { + try { + payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takeAutoExposedPicture( + new CameraSettings( + payloadsTestMCAdapter.defaultCameraResolution, + format, + new Duration(payloadsTestMCAdapter.cameraExposureTime), + payloadsTestMCAdapter.cameraGainR, + payloadsTestMCAdapter.cameraGainG, + payloadsTestMCAdapter.cameraGainB, + null), + new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); + return null; // Success! + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return new UInteger(1); } public UInteger setDeviceState(Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction, diff --git a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java index 58b814af7..187e9f9af 100644 --- a/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java +++ b/sdk/examples/space/picture-processor/src/main/java/esa/mo/nmf/apps/pictureprocessor/mo/PictureProcessorMCAdapter.java @@ -179,7 +179,6 @@ private void takeAndProcessPicture(Long actionInstanceObjId, AttributeValueList try { connector.getPlatformServices().getCameraService().takePicture(defaultCameraSettings(), adapter); processMap.put(actionInstanceObjId, adapter); - } catch (MALInteractionException | MALException | IOException | NMFException ex) { LOG.log(Level.SEVERE, null, ex); } @@ -214,7 +213,8 @@ private static CameraSettings defaultCameraSettings() { final PixelResolution resolution = new PixelResolution(new UInteger(2048), new UInteger(1944)); final Duration exposureTime = new Duration(0.200); - return new CameraSettings(resolution, PictureFormat.JPG, exposureTime, gainR, gainG, gainB); + return new CameraSettings(resolution, PictureFormat.JPG, + exposureTime, gainR, gainG, gainB, null); } private static T getAs(AttributeValue attributeValue) { From 291bd63a1fa97b4b17bc7cb195b923771e7150da Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 28 Sep 2022 17:13:28 +0200 Subject: [PATCH 071/173] Updates the AI adapter interface --- .../ArtificialIntelligenceIntelMovidiusAdapter.java | 9 +++++++-- ...ceAdapterInterface.java => AIAdapterInterface.java} | 10 +++++++++- .../gen/ArtificialIntelligenceProviderServiceImpl.java | 4 ++-- .../impl/util/PlatformServicesProviderSoftSim.java | 1 - 4 files changed, 18 insertions(+), 6 deletions(-) rename core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/{ArtificialIntelligenceAdapterInterface.java => AIAdapterInterface.java} (84%) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java index 1b533fe6d..bae4f5d8a 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java @@ -25,11 +25,11 @@ import esa.mo.helpertools.misc.OSValidator; import esa.mo.helpertools.misc.ShellCommander; -import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceAdapterInterface; import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; +import esa.mo.platform.impl.provider.gen.AIAdapterInterface; /** * The Artificial Intelligence adapter for the Intel Movidius Neural Compute @@ -37,7 +37,7 @@ * * @author Cesar Coelho */ -public class ArtificialIntelligenceIntelMovidiusAdapter implements ArtificialIntelligenceAdapterInterface { +public class ArtificialIntelligenceIntelMovidiusAdapter implements AIAdapterInterface { private static final Logger LOGGER = Logger.getLogger(ArtificialIntelligenceIntelMovidiusAdapter.class.getName()); private final File setupVarsPath; @@ -158,4 +158,9 @@ public String generateScriptBAT(String pathIntelVar, String pythonFile) { return str.toString(); } + @Override + public void doComputerVision(String jsonPath) throws IOException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java similarity index 84% rename from core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java rename to core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java index 4937b2252..43edc683e 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java @@ -22,7 +22,7 @@ import java.io.IOException; -public interface ArtificialIntelligenceAdapterInterface { +public interface AIAdapterInterface { /** * Sets a model to the Artificial Intelligence device. @@ -42,4 +42,12 @@ public interface ArtificialIntelligenceAdapterInterface { */ public void executeInference(String inputPath, String outputPath); + /** + * Executes the computer vision process for the provided json file. + * + * @param jsonFile The json file that contains the information for executing + * the computer vision process on the device. + */ + public void doComputerVision(String jsonPath) throws IOException; + } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index cf1c99404..0e1224916 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -42,7 +42,7 @@ public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelli private MALProvider aiServiceProvider; private boolean initialiased = false; private final ConnectionProvider connection = new ConnectionProvider(); - private ArtificialIntelligenceAdapterInterface adapter; + private AIAdapterInterface adapter; private final static Long TIMESTAMP = System.currentTimeMillis(); private final ArrayList modelPaths = new ArrayList(); @@ -53,7 +53,7 @@ public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelli * @param adapter The Artificial Intelligence adapter * @throws MALException On initialisation error. */ - public synchronized void init(ArtificialIntelligenceAdapterInterface adapter) throws MALException { + public synchronized void init(AIAdapterInterface adapter) throws MALException { if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index 696507479..867116208 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -37,7 +37,6 @@ import esa.mo.com.impl.util.COMServicesProvider; import esa.mo.platform.impl.provider.adapters.ArtificialIntelligenceIntelMovidiusAdapter; -import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceAdapterInterface; import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceProviderServiceImpl; import esa.mo.platform.impl.provider.gen.AutonomousADCSAdapterInterface; import esa.mo.platform.impl.provider.gen.AutonomousADCSProviderServiceImpl; From 98f3efb5863fd332ad274dee895d2e120a867b71 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 28 Sep 2022 21:20:58 +0200 Subject: [PATCH 072/173] [nmf-package] Updates the plugin to support dependencies and the dependencies of the dependencies --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 17 +++-- .../descriptor/NMFPackageDetails.java | 14 ++++ core/nmf-package-maven-plugin/pom.xml | 11 ++- .../nmfpackage/GenerateNMFPackageMojo.java | 75 +++++++++++++++++-- sdk/examples/space/python-script/pom.xml | 2 - 5 files changed, 97 insertions(+), 22 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 29c84cadf..07522ada8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -47,7 +47,8 @@ public class NMFPackageCreator { private static final int BUFFER = 2048; - private static void zipFiles(String outputPath, ArrayList from, ArrayList newLocations) { + public static void zipFiles(String outputPath, ArrayList from, + ArrayList newLocations) { try { BufferedInputStream origin; FileOutputStream dest = new FileOutputStream(outputPath); @@ -57,7 +58,8 @@ private static void zipFiles(String outputPath, ArrayList from, ArrayLis for (int i = 0; i < from.size(); i++) { String file = from.get(i); String newPath = newLocations.get(i); - System.out.println(i + ".Adding file: " + file + "\n" + i + ".On path: " + newPath); + System.out.println(" (" + i + ") Selecting file: " + file + + "\n (" + i + ") To NMF Package path: " + newPath); origin = new BufferedInputStream(new FileInputStream(file), BUFFER); ZipEntry entry = new ZipEntry(newPath); @@ -71,7 +73,8 @@ private static void zipFiles(String outputPath, ArrayList from, ArrayLis } out.close(); } catch (Exception ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, "The Files could not be zipped!", ex); + Logger.getLogger(NMFPackageCreator.class.getName()).log( + Level.SEVERE, "The Files could not be zipped!", ex); } } @@ -89,8 +92,9 @@ public static String nmfPackageCreator(NMFPackageDetails details, ArrayListmaven-plugin-api 3.6.0 + + org.apache.maven + maven-project + 2.2.1 + org.apache.maven.plugin-tools @@ -96,12 +101,6 @@ - org.apache.maven.plugins maven-dependency-plugin diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index f247198ad..d568af32f 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -21,6 +21,7 @@ package esa.mo.nmf.nmfpackage; import esa.mo.helpertools.helpers.HelperTime; +import esa.mo.helpertools.misc.Const; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; import java.io.File; import java.io.IOException; @@ -28,10 +29,14 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; import org.ccsds.moims.mo.mal.structures.Time; /** @@ -39,10 +44,16 @@ * * @author Cesar Coelho */ -@Mojo(name = "generate-nmf-package") +@Mojo(name = "generate-nmf-package", defaultPhase = LifecyclePhase.PROCESS_RESOURCES, + requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME, + requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) public class GenerateNMFPackageMojo extends AbstractMojo { - private final static String SEPARATOR = File.separator; + /** + * The App name of the NMF Package + */ + @Parameter(defaultValue = "${project}") + private MavenProject project; /** * The App name of the NMF Package @@ -92,6 +103,7 @@ public enum Privilege { @Parameter(property = "generate-nmf-package.privilege", defaultValue = "normal") private Privilege privilege; + private final static String TARGET_FOLDER = "target"; final ArrayList inputFiles = new ArrayList<>(); final ArrayList locations = new ArrayList<>(); String appPath = "no-path"; @@ -99,11 +111,11 @@ public enum Privilege { @Override public void execute() throws MojoExecutionException { getLog().info("Generating NMF Package..."); - appPath = "apps" + SEPARATOR + name + SEPARATOR; + appPath = "apps" + File.separator + name + File.separator; String mainJar = ""; try { - File target = new File("target"); + File target = new File(TARGET_FOLDER); File myAppFilename = HelperNMFPackage.findAppJarInFolder(target); mainJar = myAppFilename.getName(); inputFiles.add(myAppFilename.getAbsolutePath()); @@ -134,13 +146,15 @@ public void execute() throws MojoExecutionException { getLog().info(">> maxHeap = " + maxHeap); if (mainClass == null) { - throw new MojoExecutionException("The mainClass property needs to be defined!\n" - + "Please use the tag inside the tag!\n"); + throw new MojoExecutionException("The mainClass property needs to " + + "be defined!\nPlease use the tag inside the " + + " tag!\n"); } if ("${esa.nmf.version-qualifier}".equals(nmfVersion)) { - throw new MojoExecutionException("The nmfVersion property needs to be defined!\n" - + "Please use the tag inside the tag!\n"); + throw new MojoExecutionException("The nmfVersion property needs to " + + "be defined!\nPlease use the tag inside the " + + " tag!\n"); } final Time time = new Time(System.currentTimeMillis()); @@ -150,6 +164,51 @@ public void execute() throws MojoExecutionException { NMFPackageDetails details = new NMFPackageDetails(name, version, timestamp, mainClass, mainJar, maxHeap); NMFPackageCreator.nmfPackageCreator(details, inputFiles, locations, "target"); + + // Now let's take care of the project dependencies + // They must also be packaged as NMF Packages that will be shared libraries + getLog().info("------\nGenerating shared libraries...\n"); + + for (Object unresolvedArtifact : this.project.getArtifacts()) { + Artifact artifact = (Artifact) unresolvedArtifact; + String artifactId = artifact.getGroupId(); + + boolean isKnown = artifactId.contains("int.esa.nmf"); + boolean fromConnector = false; + List trail = artifact.getDependencyTrail(); + if (trail != null && trail.size() > 2) { + fromConnector = trail.get(1).contains("nanosat-mo-connector"); + } + + if (isKnown || fromConnector) { + StringBuilder str = new StringBuilder(); + str.append(artifact.getGroupId()).append(":"); + str.append(artifact.getArtifactId()).append(":"); + str.append(artifact.getVersion()); + getLog().info(" >> Ignoring artifactId: " + str.toString()); + } else { + getLog().info("---\nFor dependency:"); + getLog().info(" >> GroupId = " + artifact.getGroupId()); + getLog().info(" >> ArtifactId = " + artifact.getArtifactId()); + getLog().info(" >> Version = " + artifact.getVersion()); + packageJarDependency(artifact); + } + } + } + + private void packageJarDependency(Artifact artifact) { + File file = artifact.getFile(); + String destinationPath = TARGET_FOLDER + File.separator + + artifact.getArtifactId() + "-" + + artifact.getVersion() + "." + Const.NMF_PACKAGE_SUFFIX; + + ArrayList files = new ArrayList<>(); + files.add(file.toPath().toString()); + + ArrayList newLocations = new ArrayList<>(); + newLocations.add("jar-others" + File.separator + file.getName()); + + NMFPackageCreator.zipFiles(destinationPath, files, newLocations); } private void addFileOrDirectory(String path, String nest) { diff --git a/sdk/examples/space/python-script/pom.xml b/sdk/examples/space/python-script/pom.xml index 7f9ec501a..673c85b1b 100644 --- a/sdk/examples/space/python-script/pom.xml +++ b/sdk/examples/space/python-script/pom.xml @@ -75,8 +75,6 @@ - - org.apache.maven.plugins From ad35a04a4bc5c8f697bfa3ca1506e50041e9d7d8 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 28 Sep 2022 22:28:28 +0200 Subject: [PATCH 073/173] Reorders the list of artifacts to be compiled --- core/nmf-composites/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-composites/pom.xml b/core/nmf-composites/pom.xml index 739b9e1a8..74cb9ac0f 100644 --- a/core/nmf-composites/pom.xml +++ b/core/nmf-composites/pom.xml @@ -50,8 +50,8 @@ true - generic-ground-mo-proxy generic-composite-model + generic-ground-mo-proxy generic-nanosat-monolithic nanosat-mo-connector nanosat-mo-supervisor From 4dcd2188a846b6df25e7d27cdace35a0e56ca67d Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 5 Oct 2022 17:09:08 +0200 Subject: [PATCH 074/173] [ai-service] WIP - Latest batch updates to the AI service --- ...iusAdapter.java => AIMovidiusAdapter.java} | 62 +++++++++++-------- .../impl/provider/gen/AIAdapterInterface.java | 13 ++-- ...ficialIntelligenceProviderServiceImpl.java | 29 +++++++-- .../main/resources/xml/ServiceDefPLATFORM.xml | 5 ++ .../util/PlatformServicesProviderSoftSim.java | 8 +-- 5 files changed, 73 insertions(+), 44 deletions(-) rename core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/{ArtificialIntelligenceIntelMovidiusAdapter.java => AIMovidiusAdapter.java} (75%) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java similarity index 75% rename from core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java rename to core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index bae4f5d8a..990b01627 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/ArtificialIntelligenceIntelMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -33,16 +33,20 @@ /** * The Artificial Intelligence adapter for the Intel Movidius Neural Compute - * Stick via a python script. + * Stick via a python script. Note that this code was not developed for the + * Intel Movidius Neural Compute Stick 2 and therefore this version will not + * work. * * @author Cesar Coelho */ -public class ArtificialIntelligenceIntelMovidiusAdapter implements AIAdapterInterface { +public class AIMovidiusAdapter implements AIAdapterInterface { - private static final Logger LOGGER = Logger.getLogger(ArtificialIntelligenceIntelMovidiusAdapter.class.getName()); + private static final Logger LOGGER = Logger.getLogger(AIMovidiusAdapter.class.getName()); + private static final String PYTHON_FILENAME = "aiInference.py"; + private OSValidator os = new OSValidator(); private final File setupVarsPath; - public ArtificialIntelligenceIntelMovidiusAdapter() throws IOException { + public AIMovidiusAdapter() throws IOException { // Check if Python3 is installed! ShellCommander shellCommander = new ShellCommander(); String cmdPython = "python3 --version"; @@ -62,8 +66,6 @@ public ArtificialIntelligenceIntelMovidiusAdapter() throws IOException { + "\n>>>> Please update your Python version!"); } - OSValidator os = new OSValidator(); - // Is it Linux or Windows? if (os.isUnix()) { // Find the folder where the Intel Movidius software is installed @@ -86,7 +88,7 @@ public ArtificialIntelligenceIntelMovidiusAdapter() throws IOException { setupVarsPath = this.crawlOptions(options, "setupvars.bat"); - // Please install version: 2020.3 + // Please install version: 2020.2 return; } @@ -112,10 +114,10 @@ private File findPathToFile(File path, String toBeMatched) { if (path.isFile()) { return toBeMatched.equals(path.getName()) ? path : null; } - + File[] list = path.listFiles(); - - if(list == null) { + + if (list == null) { return null; } @@ -130,18 +132,7 @@ private File findPathToFile(File path, String toBeMatched) { return null; } - @Override - public void setModel(String modelPath, String weightsPath) throws IOException { - - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public void executeInference(String inputPath, String outputPath) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - public String generateScriptSH(String pathIntelVar, String pythonFile) { + private String generateScriptSH(String pathIntelVar, String pythonFile) { StringBuilder str = new StringBuilder(); str.append("#!/bin/bash \n\n"); str.append("source ").append(pathIntelVar); @@ -150,7 +141,7 @@ public String generateScriptSH(String pathIntelVar, String pythonFile) { return str.toString(); } - public String generateScriptBAT(String pathIntelVar, String pythonFile) { + private String generateScriptBAT(String pathIntelVar, String pythonFile) { StringBuilder str = new StringBuilder(); str.append(pathIntelVar); str.append("\n\n"); @@ -159,8 +150,29 @@ public String generateScriptBAT(String pathIntelVar, String pythonFile) { } @Override - public void doComputerVision(String jsonPath) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + public void executeInference(String modelPath, String weightsPath, + String inputPath, String outputPath) throws IOException { + String pathIntelVar = setupVarsPath.getAbsolutePath(); + String script = null; + + if (os.isUnix()) { + script = this.generateScriptSH(pathIntelVar, PYTHON_FILENAME); + } + if (os.isWindows()) { + script = this.generateScriptBAT(pathIntelVar, PYTHON_FILENAME); + } + + if (script == null) { + throw new IOException("Unsupported OS!"); + } + + ShellCommander shellCommander = new ShellCommander(); + String out = shellCommander.runCommandAndGetOutputMessage(script); } + @Override + public void doComputerVision(String jsonPath) throws IOException { + throw new UnsupportedOperationException("The operation needs to be " + + "extended for AI specific applications that do Computer Vision!"); + } } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java index 43edc683e..59ebfdb69 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AIAdapterInterface.java @@ -25,22 +25,17 @@ public interface AIAdapterInterface { /** - * Sets a model to the Artificial Intelligence device. + * Executes the inference on the Artificial Intelligence device. * * @param modelPath The file path to the model. * @param weightsPath The file path to the weights of the model. - * @throws IOException If the model was not set. - */ - public void setModel(String modelPath, String weightsPath) throws IOException; - - /** - * Executes the inference on the Artificial Intelligence device. - * * @param inputPath The path to a folder with a set of files to be * processed. * @param outputPath The path to a folder to store the processed files. + * @throws IOException If the inference was not successful. */ - public void executeInference(String inputPath, String outputPath); + public void executeInference(String modelPath, String weightsPath, + String inputPath, String outputPath) throws IOException; /** * Executes the computer vision process for the provided json file. diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index 0e1224916..d9c30fd3b 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -33,8 +33,10 @@ import org.ccsds.moims.mo.platform.artificialintelligence.ArtificialIntelligenceHelper; import org.ccsds.moims.mo.platform.artificialintelligence.provider.ArtificialIntelligenceInheritanceSkeleton; import esa.mo.helpertools.connections.ConnectionProvider; +import java.io.File; import java.io.IOException; import java.util.ArrayList; +import org.ccsds.moims.mo.mal.MALStandardError; public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelligenceInheritanceSkeleton { @@ -107,12 +109,18 @@ public void close() { @Override public Long setModel(String modelPath, MALInteraction interaction) throws MALInteractionException, MALException { if (modelPath == null) { - throw new MALException("The modelPath is null!"); + throw new MALException("The modelPath cannot be null!"); } - for (String path : modelPaths) { + if (!modelPath.endsWith(".xml")) { + throw new MALException("The model does not end with the file extension: .xml"); + } + + for (int i = 0; i < modelPaths.size(); i++) { + String path = modelPaths.get(i); if (path.equals(modelPath)) { - throw new MALException("The model already exists!"); + //Already exists... return the id: + return TIMESTAMP + (long) i; } } @@ -131,6 +139,16 @@ public String doInference(Long modelId, String inputTilesPath, throw new MALException("The inputTilesPath is null!"); } + // inputTilesPath needs to be an existing folder!! + File inputTiles = new File(inputTilesPath); + + if (!inputTiles.exists()) { + String msg = "The inputTilesPath does not exist in path: " + inputTilesPath; + throw new MALInteractionException( + new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, msg) + ); + } + String modelPath = modelPaths.get((int) (modelId - TIMESTAMP)); if (!modelPath.endsWith(".xml")) { @@ -140,11 +158,10 @@ public String doInference(Long modelId, String inputTilesPath, String weightsPath = modelPath.substring(0, modelPath.length() - 4) + ".bin"; Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( Level.INFO, "The weights file path is:\n >> " + weightsPath); - + try { - adapter.setModel(modelPath, weightsPath); String outputTilesPath = ""; - adapter.executeInference(inputTilesPath, outputTilesPath); + adapter.executeInference(modelPath, weightsPath, inputTilesPath, outputTilesPath); return outputTilesPath; } catch (IOException ex) { Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index b0e906127..9bea9a3d7 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2237,6 +2237,11 @@ + + + + + diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index 867116208..d640811d5 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -36,7 +36,7 @@ import org.ccsds.moims.mo.platform.softwaredefinedradio.provider.SoftwareDefinedRadioInheritanceSkeleton; import esa.mo.com.impl.util.COMServicesProvider; -import esa.mo.platform.impl.provider.adapters.ArtificialIntelligenceIntelMovidiusAdapter; +import esa.mo.platform.impl.provider.adapters.AIMovidiusAdapter; import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceProviderServiceImpl; import esa.mo.platform.impl.provider.gen.AutonomousADCSAdapterInterface; import esa.mo.platform.impl.provider.gen.AutonomousADCSProviderServiceImpl; @@ -78,7 +78,7 @@ public class PlatformServicesProviderSoftSim implements PlatformServicesProvider public void init(COMServicesProvider comServices) throws MALException { // Check if hybrid setup is used CameraAdapterInterface camAdapter; - ArtificialIntelligenceIntelMovidiusAdapter aiAdapter; + AIMovidiusAdapter aiAdapter; AutonomousADCSAdapterInterface adcsAdapter; GPSAdapterInterface gpsAdapter; OpticalDataReceiverAdapterInterface optRxAdapter; @@ -271,7 +271,7 @@ public void init(COMServicesProvider comServices) throws MALException { } else { pcAdapter = new PowerControlSoftSimAdapter(); camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); - aiAdapter = new ArtificialIntelligenceIntelMovidiusAdapter(); + aiAdapter = new AIMovidiusAdapter(); adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); @@ -285,7 +285,7 @@ public void init(COMServicesProvider comServices) throws MALException { pcAdapter = new PowerControlSoftSimAdapter(); camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); try { - aiAdapter = new ArtificialIntelligenceIntelMovidiusAdapter(); + aiAdapter = new AIMovidiusAdapter(); } catch (IOException ex) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log( Level.SEVERE, "The AI adapter could not be started!", ex); From f5923d0d84fdbda9060547009c8f2223fd30f18f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 5 Oct 2022 19:19:33 +0200 Subject: [PATCH 075/173] [edge-ai] Updates the example with a model and two tiles to be used as demo --- .../space/edge-ai/ai-model/dummy_model.bin | Bin 0 -> 1804 bytes .../space/edge-ai/ai-model/dummy_model.xml | 282 ++++++++++++++++++ .../space/edge-ai/demo-tiles/tile_1.png | Bin 0 -> 58012 bytes .../space/edge-ai/demo-tiles/tile_2.png | Bin 0 -> 82686 bytes sdk/examples/space/edge-ai/pom.xml | 16 +- .../esa/mo/nmf/apps/edgeai/EdgeAIApp.java | 4 +- .../esa/mo/nmf/apps/edgeai/MCAdapter.java | 28 +- .../src/main/resources/scripts/myScript.py | 8 - 8 files changed, 317 insertions(+), 21 deletions(-) create mode 100644 sdk/examples/space/edge-ai/ai-model/dummy_model.bin create mode 100644 sdk/examples/space/edge-ai/ai-model/dummy_model.xml create mode 100644 sdk/examples/space/edge-ai/demo-tiles/tile_1.png create mode 100644 sdk/examples/space/edge-ai/demo-tiles/tile_2.png delete mode 100644 sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py diff --git a/sdk/examples/space/edge-ai/ai-model/dummy_model.bin b/sdk/examples/space/edge-ai/ai-model/dummy_model.bin new file mode 100644 index 0000000000000000000000000000000000000000..5d175fe2e58b130ee2044b6100ff345eb49182f7 GIT binary patch literal 1804 zcmW-ac{JAf9>;Cfkm)%|q>}AX##pM6()0U%z9Eg}rluh!F_&UgD2k(Eie&9Uwqvc! zWXY073(xaij3rHFnkGr&WXqLSRE|pSo!2hA!UF638!>onw2-SMevhv*@-yF;jXGh41W^;X02NZ2qkl ztdwLzX;~yw{WTSODoWT5rD7(_t7ApVKGdTB9jpFu5Kk7b;pWp)-X8xoEf25dn;yJk zqNo$NAm=cSYt_KJYKqy{#dC4vv#TsYHk&Ivk7jL>G@S5@h>ta-VvW>Tco*?E%}Q3| z+8Nm($kh0iEuWy;(v9gnjmE30nz(9F0w3Bq!3HL8a=mqqJVnm|##k`#?!C?T&uqft z+Cje3E|*KyM_BhRU7YQviD!l6GI}|QtLc3f&JG`A51ZAo+PDHAa;yV}s-ZJKYx?84*!<~lt-k6un zr6->o^{j-38@4!7{a4mCB*ziuC%M*tQh9^H0ybnl59=uFaK#RcZ+n!0uHRGk%(D|- zWmBeA>CMZDKK5GBPb-bRaOh|)D8fTlYPytb6j$J+`!-0>=7K0p4?ceP2VQ78$@Hil z9tyt64lJJyE6laIOG-Y^TDpVz&+}$ElkqtH$|W#Y-+;q|#QcTg1>QCy<%VXjA>~OL z?t7Pq163lqeUb&Q__Gk}J2dkVzXom@7y~iK3&HizPQco)V8FB!f}F1*=f)*Cru8|S ze!2w5xdB?(S;{i4pRrc6G!j|Y$3wJ^@t!$dIANxM?~Rx(QR&G?EzyslyM2fYrtWB2 zfhOHOBNuEfYq7GWA@o*Q2&0lQ#x<* zT|JF%SDUcaGDAFYFM-Rh{uc%va-p#IIej$$9xr&ehA$dDh30iOaL04$5OSr8xlNbD z_UF4un&w5k%|ncZ#`hA1|F1HC4Y~3u`HLIJZ6e)2-)?B%xR?CXT21x{|4{wldCB29 zal+hQXCZ$d77nI+2tOaNlDk*U|I!D|n(O~I43hsO@gb+I&f9b~$C3rc`T{MPFO=B% z%XS`jA}IrB*A;qN$?}aOeTkNx02w<6>^pP zUc!*dh-6NB7>RakmE=@CmaOj#CV}y~B;0sS16!{vS9aY(TF+*`qj zMqnRrA?6yG1^344p*J%VWgp3B7nB!T6npzeMd)>?A1`*BZt+zQ?USCQ&7CN)it~{i! ze1h#PutTM76Z9)j5wZ};sk?Xw+z^|gkypx49GXZCq)xEkt&`3umdKA39HmqDwPA@M zV8^P4}K-{%V(6!l^5<9npouZWrXx6|O9 zyHqJkO6OXKg8r6AWLZ{|aML6P>bf4H#|Z>p#-@NO*#O(ZmeH9w7nnFIg4ZRr^wNTB zti$O8-6~6h>FPx4mVBJ8)qF;##=M}T{2&YpEmUC~u}g8)!lKh>fP)=d{x*Q=znKF% zP6~9)_aPZ39w^ke1zlTSDa_rt6vS<=%sJ78xvc*e5-p!5VSXu8@ppY{d-4eF`uG3^ zb?;^-@mjE?`ynZD*J16Kq-?aI3t69Y1cy6$a0_XG@Hz`wiRI+E8bc3~-_pEbb6C8; zg9<+uGP%+Wfy*v1Ydn|u99}{DD|FGZAbaxSjs;to_!c>sYQoWy07$4m3(^pMu#1j| z-_E>3dVcQE8KOd_Tuqp}ax^q+^r8Jqwk&7K4rYD6fofh(LfO++a4|lCUYeR?|n8Afv!{@s|TZHZtRd$3$!A$;ZTzfEDG=?Et?zZ6H|M7y0~4axDdnMxs;+_ zc`z8qq{88}ct(geJGIt=rPPElh0BbMTCPUE)@i6u!G`uu+EArbQxG+@(V`#1Xx&5s zU1woO2TGdRUaviHvMiq3j}%dO`W-v)k|TxTkH`aWg2bJf=<~uoU~Lh{_Q?ZDw%cp! a*%Ly%#wuZ}o*07tu1W@n{RzH#Me;wkS!+T7 literal 0 HcmV?d00001 diff --git a/sdk/examples/space/edge-ai/ai-model/dummy_model.xml b/sdk/examples/space/edge-ai/ai-model/dummy_model.xml new file mode 100644 index 000000000..2ebff9083 --- /dev/null +++ b/sdk/examples/space/edge-ai/ai-model/dummy_model.xml @@ -0,0 +1,282 @@ + + + + + + + + 1 + 3 + 512 + 512 + + + + + + + + 64 + 3 + 1 + 1 + + + + + + + + 1 + 3 + 512 + 512 + + + 64 + 3 + 1 + 1 + + + + + 1 + 64 + 512 + 512 + + + + + + + + 1 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 512 + 512 + + + 1 + 64 + 1 + 1 + + + + + 1 + 64 + 512 + 512 + + + + + + + 1 + 64 + 512 + 512 + + + + + 1 + 64 + 512 + 512 + + + + + + + + 3 + 64 + 1 + 1 + + + + + + + + 1 + 64 + 512 + 512 + + + 3 + 64 + 1 + 1 + + + + + 1 + 3 + 512 + 512 + + + + + + + + 1 + 3 + 1 + 1 + + + + + + + + 1 + 3 + 512 + 512 + + + 1 + 3 + 1 + 1 + + + + + 1 + 3 + 512 + 512 + + + + + + + 1 + 3 + 512 + 512 + + + + + 1 + 3 + 512 + 512 + + + + + + + 1 + 3 + 512 + 512 + + + + + 1 + 3 + 512 + 512 + + + + + + + 1 + 3 + 512 + 512 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/examples/space/edge-ai/demo-tiles/tile_1.png b/sdk/examples/space/edge-ai/demo-tiles/tile_1.png new file mode 100644 index 0000000000000000000000000000000000000000..958a882863eb9183f0d83ab20a19961448b4289d GIT binary patch literal 58012 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
    (eXEHrK6L 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 FV1j2yD$xJ{ literal 0 HcmV?d00001 diff --git a/sdk/examples/space/edge-ai/demo-tiles/tile_2.png b/sdk/examples/space/edge-ai/demo-tiles/tile_2.png new file mode 100644 index 0000000000000000000000000000000000000000..c0c6bb220dfd2d4a218f00762d7f6db4de1ca17c GIT binary patch literal 82686 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
      E&q{=cxd<}ybXNvv(l#v? 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%0D8z|pMB+3k5!-wkt0+_CkBCZ3WT6x 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

      _R_+t{rc~{ZvV~a->^%yy#4rxuG@~7{Eb@& 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 z zx)8767j@+av-sqvGNf!dfx_$$F)_EZat%tdYHIbe^048~zMA?gI-$rjq6OOmOak;B zA!i)#++Gv&S1m7p8{eod9O+l9D^pnQLUV+fjdJ*i7txrFSuw;~pf09#6vBb}3_WJq zM-z@%0E{bICi7qXr~k>TFn6)2z^mePUIW6EPD4RcV6RHDMKs>of!XMESWQ&p8YMI; z)BBvJSsZU{M6{(Zf~XR-*q(e71dSznGyz5N4H)pS*&J5;&4B^942e9)6xEDY+espSe$bv!92fr=eFDZd?uOw7LAyj z$@rxlQ&MMCpZdcLu0G>vLtK2ZxM*;8Iw379CenENL1Yo!8AD7>S%C4$NtmX^_-J*Q zt*O~*SFOD8izTI`aRr!N7+(1% zN`pV~xehfOGj1qP((s#Eb)42jaaX=QN13+p_jWh|BJmJ^Kvzy-uw>7E7M}+|z^N1A zgWu^JGc^kB;1g`S*YEXI^Et@(*e#GZkKr%l& z?{>d0Y14>^g=y(~L#otgTK#1p_)#(TzQXh@DhSXBNG${1lsUr*>!PM{1{tk}#$;+1 z`^Yq7S-<6GXBV@s9W*G%iJGk5Nzmi>y4g~oea-~(Nj3zjER%=fIMd*BV3n1pL)qKS z%?)cGz(8hiy?@INRp;UHfo<*_iK(YW%w1`tS@)}0kYV6p=q5hI(T=oo*rs4*6VrzN za(wITbW$c+UFl*xIqh>B~+_TOCdB|31ODwNBYdJj$&qpEshDr2ccqY&}8A)^jWA1jEBIpIK%5H zIQ?vl!h9Xgg80HLT+u$(#=*gnAE%mKn6@QZCyNX7Zr!w5Kw(K-ZNdvIHcVzw0IU%6 zISB9*Ga}p~0Ja8hhtCk2-NBtBV3=+d`OyING&xQtT#GEGh+kNx#sy$3;Z5*IurO2k zT5tHocJTXU3b+fv%&khKuw|`?&hQ(*7>Oc5@zefSUi+%7rfrqu#ZdDTH&|Tsm8Es~ z5Fb1AA@D4C!4L31<|njis6H$@EGTAB|5)jt|JfgZl@%HWnWaotT^KMr!v0N`c zzQJk_-%dD_c~g-#KK6T`u4T{k#6S!pjdoAuw`dAxpG9O)nx=Qv&+i!VGoU!PyrjoU z(tEe=`srwV8@P{sCjY5SG>--bWFaX2722$$PRuUM`9W9q99U>z=E0$*9~^sPnS6H_ zp~%^cOw@jly_Kfg7V`_o4y${OL;nUiQ~A61)~zS)?k4aFev%Z8`oPjW1IZp%7A-0K zco7iBU6^0=??Lz`wg_Jky-qdzfeZdB+X3v?xRzFcR(uMK#fN-WG!et(#eg%sQgfD- zS=iLfz9kL1r}i6u$d+%GqtVguESj+o#y2mT>I>TwSP`r+#+i)OyZX$mn}i58Ca2?~ zw$!{sP;g>CY5F56CSLd81P1r~h#P(cdwAfza&c9rZdDA#Z+nFqcOr9Q75SY)Lu1Wp z^kbQ(``!+Ukrg)Ieqr2X#=&?jgJUYAU^v9<3uEdN0?CyH0%nZ*H2zg0I2wBv8pOiB z8i#r7!ij07`uLUx%7BG5ggh#4`cAr^s#pH70?oDzFM@W(&!VmRhHu5f7l(7%%*V&W zPp#MGV&pWhx)gKzy{xtoDha8^8Ge9QS&YIGz=Gmb|KS0z2BG*^p)I-)X8y{*`*W|t z$S^(2p$Gt*uS}E7R-6#P2ZDGkN8>l}X|TGqGbR|bMz_K0Q`@IUR%LJm8=6vGvuc2w zBA(BB>MW+Ef73u6=E^T{)HJ9FVL{rB6Wrj!!Cg!Z4&Bmu_A$_Y6*-HTT<&12|1%OU z@aB*u0)=mak8}V2ridaF6Z~YmbL^^*@<5x3DNbQvgrn26jXepU`pW(p&MmJHtX#Zc zS!P=i^-P1+5uUU23%=3H2@U#5ig5>1@9#;;$xi0HU`1`>sB2CN zvzL@3ZyaOd;CnEgQ4V@Te}s(p)WQh_;VI@|eDO=JJ@u4Z7|%-=l|SKzsmGa=Q)EFUPwE!^>t};X*8zKnoKJ;)$naF6W9pm)qk`C4lm~5 zzRV|IIT9k6OPta`x&xvoZrg{G8q5}9$DCCk-Zk=XO-Km&1$tJ-c+G*CiZaxJ-OOMh zG-wOTqxpHQonD6xXY-TXek@6ZLfF9#8=ob5+F?Zu6Bsk(ROuPsXA(oN?KW-m;Mn&~ zSS@X7fOz}0r`e6!35`p8oIvqY=Q3se!~1HJnTVB9UU?{r(K(3hulP#?qft2<$uF67 zrF~((zL@K6VBY-oChSgvW81y6vIQ^Jz&>M3NUg4cA z7OU7VWyW4uSk{abHm>nuSRC=~4Dkx5D431#gTf&PDQ(ddp<{el(Zo7p_QvYMcbu7< zb>>Haa2v`}448KW`V{tXSuo2x4Y8WwOYjFU`v7>4d;i)q46ZWJi){|ZdQYbH&enm1 zt0bD%Bt!WB3V;6R{`9N9=b#6^u2U34U>YDqth`{KD#&FdDgz7+y z!`>G{g`lxi%J&{H$5?`=epbftP0(DtU&azHz^`EN25MKr!v|}~kil0oIky^srNwz$ zo?o&Ha!luCb7$1IiWm@koxy|1tY~4du!`6fGckkFcRt|aujGs2_QepG$GoP%i~;jj zMAzJed_MWA@2+?4sGYN`*Di~We9urOlB|a^?_B8_Ch^%)4_w zyv0|9Da9UYSAMUwIwx9=_qT0bLdXguvn$`j2(P;EJIdjp0W%`LBA)1>((p+z<1u3q zY{m`~jxXq9_TA@1hy>AxI#ql|k zS%{!7@(!O&V;1l-fAxR&^RF`V!2ER~cXGmjW~HGPooUcM>-`SLGFi330s;=q{fMbIf;Rq%bWk~%9>vvDj!$~-`epyklgi!1YP z>jryWT3RL^@tCaG>8wo3H1_%zmX^ev8Q*VXnUrthao&%ONoLSi|$8WlYqC#<>5K_ht+0TjF%nauIPlA+WbU{iD35O#LoZ2Lxhlbd?&4NgJQ_;^O2K_K z;ROTfVm-||TkC7Se7&>1rT(=vTZq=;CC)~&t-?7--sP}-bwM>tt^^g{_U`7!%Btj&REPN8G2F;nxYHB3tO0TBvTbeYK(7d0;PGqMK6 z3z`}7ZUw<>9kq?`hQAL#b=8w#nj=^UL)d(m(r3cZM1bN@v;IY2R+!ZZrvaPXnwGpA z{6!roNf$27_Kc4ot`M)Gyr~DCcFS!~zNPBpBRuTy^1ff@Z~oGM@G6ZI{%{MlJ!;f8e-N|G?oMB`_-M;<4n*%H{Gt;tsEGbqSVX65@f(LUWh#naDvMO}<-n#G$f_`?I z@g?x8a9CU4l+C>%;Vjw4*0xNXeW>X9ShZ}+2f{Swr4;sr0u7|`ch~)l-|2}=CD9H4 z=1^wO#@4>=%4gzzHGH(DG&diCVSq75r^I-?^EE3c+*bv~G-3y5a$oh8GAX+Ghp6@3 z>|%L7jDrT+nI+@-Q4qc)4ui=wZ^^gCoMn6#HIuQ)@83zR;=8upvSBP)(BV`AraSax zwqzK2DUeMo#&XKzyop0{I$RQi?7mAXFO%+ zw_N2Yh>)_A#oS@pR)eC>(tsZi5g|Ft#)oVWAYRkJoIsG6K{!%^5V8k_xrSh{!h+w% zVgy}1V);@IC>o1F^1T!du79*f8j?j51eEX8VG2b%oGkzrRv1ub#%@al-#xHR`H1)K z-nAVGC=7%DGB?A%5qn)3F=*G#JLwfWmHB~Cuwn*&C<7D+_B6IMuVv7mwYzI};lf3` zbm^iy^6clZVaahUOqV?kJPSBzu$k%P-Lcb2d;j*DX4fO(jCN$3TUX)FSA(*mLw&9$ zy0v{FX6^o_AD`hMGoMIqEB_YT1zkDkVy+Dd+1>Rmo2&8d@>7593&3cV3<{IDOh}#ADqHGegAhN%AEL>0Ae1-X7Y7{d}${}0$3Ys+~ zIN-rb9)bgotYTicc)@uQ;e^jHL8F%zzY2%rl}pdjUr5`cI71xV4H zSqGjaAOiU72&&lHPq)y%FU0UqbVW$n(m>%LbXXQxb}X#05(z(Z%*wyhK?V|8G{6ig zXisbUhH`omO)22>7>7~ zCsV-@({zr|Ai$V6INNM~a%`sC;nkCxrz7~h{X0LmY%43P%8$?;OY^t<tC9FU%q z-^(ZG7`3d@pdJ1#mJ#MGf`zXIekg4EPCbm1I9ct829r`M@()pJ0CaNN=!(i<(T=|O z61~bZj*K~z4EP|h#8ZxE+F_xD0}chv-1w8YOuQYxe*d0rZ*52+$Ul_jft3Y)kgLou zY3AbnA~h{7Eb~lAGE;1720&n7c8>jEBGzT1xv)tyvA@Ae6bRslpcPpZ@YC0d>$f?u zd1(7G2as~!`|7LVqrF}KnySoYIsbh0MuUTGt&Y()8_B#-$qD-nMzbc`$2nhTn`R4TQ)Fp^1gb7uZS=*^K$Nwl~nv2z6wkE zLOJIj>*SSun1g{qHSX;0t6lTDUU}su)w^$-JNwq=Wh@DELjnS$Uszlg<4)Pti#500 zk2F4-t7JhG`p>oU{#oRP4K@J+UMcAb%6{H$Dsb}N|QEF8caP8-!9j#7#7#V1H-<8V(*#s_^Q zu<8naAtyPoNLVq(@?rCMV{=(-U{Ip?+3p9)+!tCtZnzI94otmbb;{%5GfZ>*G-i2xEsol863N#B zBoEB+EL`|3r#OZz9Iq3vh@KjJU5`a8eu;%odz&T|i0FulH zC-GqzjJPMjNpKD)Vk#kxm|Xs$NJ%zGpfP$vlG({Mg!1&o{Mf_yq>1j_yJr_QGtdUM zHoMrIUcfA2F@tk_5Q~M9_?9W=4_}$341>rDCGCJyLC$PdMB*w+U~pmbtH2OEsPn#>mwX8g-&}2jid%A9^VO#=-(4WbM}KN&7R(-1mkO8 ze@o_-@^+<&gx@X;1;UGSifjY8h8Nvfb-QtC##%?bxhqFp9b#VxE($08!w+8j-jtS(9$}B6N1uf5O z9ncyJ1alqQ?(fJP*O*{Q@CzSo=(C`~q6uxIi17gD=jJqC)5AhrEf6()7v&?8#Cm0YB7dF^w&J>no0uX%sa4%eD^p@G4dXv)$hAk?6!E z!R)Ade&J_-{8iqL-4t_!Fv7(kgcBGd9EeC0vRARZv}||p+|_I{?MtgPh<}A+AN?)R z+?Ph0)Bw#a%=TGQxV-BV{6zBNuwh=a*uvt$3}4tqY3Uye5UZ;**a~i* z@Y6vI&iaO&b>Xog;a%t34-$;L%#LFz3|@U{sILew@3rxDtdBf*MfW|sE#K1pQqh{( zgF0ab7={^u7XqO(+PNqH1LnZlhRGu>`3xE-P#8OC!~PcvgdhLjkub7Yf^hL84m+D0 zY6n3tx&gQVNB_|9YbQAJm};EFsbX?V>A8}VaJ5CBnVAJwa6TJ|{_qnD7}FaI1c3~u z9WDjuA9*uCxXJW=>znV(+&-2dE{XQDqO+!V2|l#p{3nZTHH|R}ml*=n6$Q$bm1GW5 zv%<{ypx|g1-elIoiV->*qY2yH+H{_)sC{N<))C+p;yfr0Ul<>hX9$k@?TQ?eg8>j- p{ZNGXVpqb2Z#z3%SM-Gae*uCvg2#WCB*Fjy002ovPDHLkV1f*H6fOV& literal 0 HcmV?d00001 diff --git a/sdk/examples/space/edge-ai/pom.xml b/sdk/examples/space/edge-ai/pom.xml index e6af6afef..ccd3c99b9 100644 --- a/sdk/examples/space/edge-ai/pom.xml +++ b/sdk/examples/space/edge-ai/pom.xml @@ -57,9 +57,9 @@ - CesarCoelho - César Coelho - https://github.com/CesarCoelho + CesarCoelho + César Coelho + https://github.com/CesarCoelho @@ -75,8 +75,6 @@ - - org.apache.maven.plugins @@ -94,10 +92,6 @@ org.apache.maven.plugins maven-compiler-plugin - - org.apache.maven.plugins - maven-resources-plugin - @@ -117,6 +111,10 @@ ${assembly.mainClass} + + ${basedir}/ai-model + ${basedir}/demo-tiles + diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java index 4bd51061a..4e9df5e8c 100644 --- a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/EdgeAIApp.java @@ -29,7 +29,9 @@ public class EdgeAIApp { public EdgeAIApp() { NanoSatMOConnectorImpl connector = new NanoSatMOConnectorImpl(); - connector.init(new MCAdapter(connector)); + MCAdapter adapter = new MCAdapter(connector); + connector.init(adapter); + //adapter.triggerAIInference(null, null); } /** diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java index bbc134f15..7fbcb71bd 100644 --- a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java @@ -41,6 +41,7 @@ import esa.mo.nmf.NMFException; import esa.mo.nmf.NMFInterface; import esa.mo.nmf.NMFProvider; +import java.io.File; import java.io.IOException; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; @@ -125,7 +126,7 @@ private void registerActionAICancel(ActionDefinitionDetailsList actionDefs, Iden actionNames.add(new Identifier(ACTION_CANCEL_AI)); } - private void triggerAIInference(Long actionInstanceObjId, AttributeValueList attributeValues) { + public void triggerAIInference(Long actionInstanceObjId, AttributeValueList attributeValues) { /* int minProcessingDurationSeconds = getAs(attributeValues.get(0)); int maxProcessingDurationSeconds = getAs(attributeValues.get(1)); @@ -146,8 +147,29 @@ private void triggerAIInference(Long actionInstanceObjId, AttributeValueList att */ try { - String modelPath = ""; - String inputTilesPath = ""; + File aiModel = new File("ai-model"); + + if(!aiModel.exists()) { + throw new IOException("The folder does not exist: " + aiModel.getAbsolutePath()); + } + + if(!aiModel.isDirectory()) { + throw new IOException("The path is not a directory: " + aiModel.getAbsolutePath()); + } + + String modelPath = aiModel.getAbsolutePath() + File.separator + "dummy_model.xml"; + + File demoTiles = new File("demo-tiles"); + + if(!demoTiles.exists()) { + throw new IOException("The folder does not exist: " + demoTiles.getAbsolutePath()); + } + + if(!demoTiles.isDirectory()) { + throw new IOException("The path is not a directory: " + demoTiles.getAbsolutePath()); + } + + String inputTilesPath = demoTiles.getAbsolutePath() + File.separator + "tile_1.png"; ArtificialIntelligenceStub aiService = connector.getPlatformServices().getAIService(); Long id = aiService.setModel(modelPath); diff --git a/sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py b/sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py deleted file mode 100644 index 981251b7b..000000000 --- a/sdk/examples/space/edge-ai/src/main/resources/scripts/myScript.py +++ /dev/null @@ -1,8 +0,0 @@ -import time - -def start_demo(): - for x in range(1, 6): - print ("Hello, World! Counter:",x) - time.sleep(1) - -start_demo() From 5fcd532487442819f97cccd6174491ca1da7ec15 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 5 Oct 2022 19:20:47 +0200 Subject: [PATCH 076/173] [nmf-package] Improves error message when the mainClass is not provided. --- .../nmf/nmfpackage/GenerateNMFPackageMojo.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index d568af32f..7980a460b 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -70,7 +70,7 @@ public class GenerateNMFPackageMojo extends AbstractMojo { /** * The App main class */ - @Parameter(property = "generate-nmf-package.mainClass") + @Parameter(property = "generate-nmf-package.mainClass", defaultValue = "${assembly.mainClass}") private String mainClass; /** @@ -146,11 +146,17 @@ public void execute() throws MojoExecutionException { getLog().info(">> maxHeap = " + maxHeap); if (mainClass == null) { - throw new MojoExecutionException("The mainClass property needs to " - + "be defined!\nPlease use the tag inside the " - + " tag!\n"); + throw new MojoExecutionException("The mainClass tag is not defined!" + + " Please include in the tag:\n" + + "-> \t\t\n" + + "-> \t\t\t${assembly.mainClass}\n" + + "-> \t\t\n\n\n" + + "-> Or add to the tag the mainclass. Example:\n" + + "-> \t\t\n" + + "-> \t\t\tesa.mo.nmf.apps.myapp.ExampleApp\n" + + "-> \t\t\n\n\n"); } - + if ("${esa.nmf.version-qualifier}".equals(nmfVersion)) { throw new MojoExecutionException("The nmfVersion property needs to " + "be defined!\nPlease use the tag inside the " From c4b7b8d9c663f5acebab9f0944cd9520da71252a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 5 Oct 2022 22:50:18 +0200 Subject: [PATCH 077/173] [edge-ai] Updates the inputTilesPath --- .../edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java index 7fbcb71bd..39fab65d7 100644 --- a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java @@ -169,7 +169,7 @@ public void triggerAIInference(Long actionInstanceObjId, AttributeValueList attr throw new IOException("The path is not a directory: " + demoTiles.getAbsolutePath()); } - String inputTilesPath = demoTiles.getAbsolutePath() + File.separator + "tile_1.png"; + String inputTilesPath = demoTiles.getAbsolutePath(); ArtificialIntelligenceStub aiService = connector.getPlatformServices().getAIService(); Long id = aiService.setModel(modelPath); From 7ee7fe4e3085a5a39805ec5da1b69ef919661c80 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 6 Oct 2022 23:32:17 +0200 Subject: [PATCH 078/173] [nmf-package] Refactors the code & Adds a new Metadata mechanism for the packages (WIP) --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 36 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 401 +++++++++--------- .../descriptor/NMFPackageDescriptor.java | 58 ++- .../descriptor/NMFPackageDetails.java | 39 +- .../descriptor/NMFPackageMetadata.java | 109 +++++ .../nmf/nmfpackage/receipt/ReceiptMaster.java | 2 +- .../tests/SimpleDemoPackageCreation.java | 16 + .../nmfpackage/GenerateNMFPackageMojo.java | 3 + 8 files changed, 431 insertions(+), 233 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageMetadata.java diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 07522ada8..2490f5908 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -24,6 +24,7 @@ import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageMetadata; import esa.mo.nmf.nmfpackage.receipt.ReceiptMaster; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -40,6 +41,7 @@ import java.util.zip.ZipOutputStream; /** + * The NMF Package Creator class. * * @author Cesar Coelho */ @@ -86,15 +88,18 @@ public static String nmfPackageCreator(NMFPackageDetails details, ArrayList filesInput, ArrayList newLocationsInput, String destinationFolder) { NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); - final ArrayList files = new ArrayList<>(filesInput); + NMFPackageMetadata metadata = new NMFPackageMetadata(details.getProperties()); + final ArrayList files = new ArrayList<>(filesInput); final ArrayList newLocations = new ArrayList<>(newLocationsInput); for (int i = 0; i < newLocations.size(); i++) { try { + String path = newLocations.get(i); long crc = HelperNMFPackage.calculateCRCFromFile(files.get(i)); - NMFPackageFile nmfPackageFile = new NMFPackageFile(newLocations.get(i), crc); - descriptor.addFile(nmfPackageFile); + descriptor.addFile(new NMFPackageFile(path, crc)); + metadata.addProperty(NMFPackageMetadata.FILE_PATH + "_" + i, path); + metadata.addProperty(NMFPackageMetadata.FILE_CRC + "_" + i, String.valueOf(crc)); } catch (IOException ex) { Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, "There was a problem during the CRC calculation.", ex); @@ -103,9 +108,10 @@ public static String nmfPackageCreator(NMFPackageDetails details, ArrayList -1) { + baos.write(buffer, 0, len); + } + baos.flush(); + InputStream is1 = new ByteArrayInputStream(baos.toByteArray()); + + NMFPackageMetadata metadata = NMFPackageMetadata.load(is1); + is1.close(); + String metadataVersion = metadata.getMetadataVersion(); + + // Old system based of package receipts + if (metadataVersion == null) { + NMFPackageDescriptor newDescriptor = null; + InputStream is2 = new ByteArrayInputStream(baos.toByteArray()); + InputStreamReader isr = new InputStreamReader(is2, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr); + + String line = br.readLine(); // Reads the first line! + + if (line != null) { + // Extract the version from the first line + if (line.startsWith(line)) { + int length = HelperNMFPackage.NMF_PACKAGE_DESCRIPTOR_VERSION.length(); + String version = line.substring(length).trim(); + newDescriptor = ReceiptMaster.parseReceipt(version, br); + } else { + throw new IOException("Could not read the NMF Package Descriptor version!"); + } } else { - throw new IOException("Could not read the NMF Package Descriptor version!"); + throw new IOException("The receipt file is empty!"); } - } else { - throw new IOException("The receipt file is empty!"); - } - br.close(); + br.close(); + + return newDescriptor; + } - return newDescriptor; + return metadata.toPackageDescriptor(); } /** diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java index fd6b72c15..1b9055954 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java @@ -20,7 +20,7 @@ */ package esa.mo.nmf.nmfpackage.descriptor; -import java.util.HashMap; +import java.util.Properties; /** * @@ -34,7 +34,7 @@ public class NMFPackageDetails { private final String mainclass; private final String mainJar; private final String maxHeap; - private final HashMap properties; + private final Properties properties; public NMFPackageDetails(final String packageName, final String version, final String timestamp, final String mainclass, @@ -48,7 +48,7 @@ public NMFPackageDetails(final String packageName, final String version, this.properties = null; } - public NMFPackageDetails(final HashMap properties) { + public NMFPackageDetails(final Properties properties) { this.packageName = null; this.version = null; this.timestamp = null; @@ -57,28 +57,43 @@ public NMFPackageDetails(final HashMap properties) { this.maxHeap = null; this.properties = properties; } - + + public Properties getProperties() { + if (properties != null) { + return properties; + } else { + Properties props = new Properties(); + props.put(NMFPackageMetadata.PACKAGE_NAME, packageName); + props.put(NMFPackageMetadata.PACKAGE_VERSION, version); + props.put(NMFPackageMetadata.PACKAGE_TIMESTAMP, timestamp); + props.put(NMFPackageMetadata.APP_MAINCLASS, mainclass); + props.put(NMFPackageMetadata.APP_MAIN_JAR, mainJar); + props.put(NMFPackageMetadata.APP_MAX_HEAP, maxHeap); + return props; + } + } + public String getPackageName() { - return packageName; + return (properties == null) ? packageName : properties.getProperty(NMFPackageMetadata.PACKAGE_NAME); } public String getVersion() { - return version; + return (properties == null) ? version : properties.getProperty(NMFPackageMetadata.PACKAGE_VERSION); } public String getTimestamp() { - return timestamp; + return (properties == null) ? timestamp : properties.getProperty(NMFPackageMetadata.PACKAGE_TIMESTAMP); } public String getMainclass() { - return mainclass; + return (properties == null) ? mainclass : properties.getProperty(NMFPackageMetadata.APP_MAINCLASS); } - public String getMaxHeap() { - return maxHeap; + public String getMainJar() { + return (properties == null) ? mainJar : properties.getProperty(NMFPackageMetadata.APP_MAIN_JAR); } - public String getMainJar() { - return mainJar; + public String getMaxHeap() { + return (properties == null) ? maxHeap : properties.getProperty(NMFPackageMetadata.APP_MAX_HEAP); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageMetadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageMetadata.java new file mode 100644 index 000000000..df03c1746 --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageMetadata.java @@ -0,0 +1,109 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage.descriptor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; + +/** + * + * @author Cesar Coelho + */ +public class NMFPackageMetadata { + + public static final String FILENAME = "metadata.properties"; + + public static final String METADATA_VERSION = "NMFPackageMetadataVersion"; + public static final String PACKAGE_TIMESTAMP = "PackageCreationTimestamp"; + public static final String PACKAGE_NAME = "PackageName"; + public static final String PACKAGE_VERSION = "PackageVersion"; + // PACKAGE_TYPE: "app", "nmf-update", "mission-update", "dependency", "java" + public static final String PACKAGE_TYPE = "PackageType"; + + public static final String FILE_COUNT = "FileCount"; + public static final String FILE_PATH = "FilePath"; + public static final String FILE_CRC = "FileCRC"; + + public static final String APP_MAINCLASS = "MainClass"; + public static final String APP_MAIN_JAR = "MainJar"; + public static final String APP_MAX_HEAP = "MaxHeap"; + public static final String APP_MIN_HEAP = "MinHeap"; + + private final Properties properties; + + public NMFPackageMetadata(final Properties properties) { + this.properties = properties; + + // Validation needs to occur for the mandatory field values + } + + public String getProperty(String key) { + return properties.getProperty(key); + } + + public void addProperty(String key, String value) { + properties.put(key, value); + } + + public String getMetadataVersion() { + return properties.getProperty(METADATA_VERSION); + } + + public String getPackageName() { + return properties.getProperty(PACKAGE_NAME); + } + + public String getPackageVersion() { + return properties.getProperty(PACKAGE_VERSION); + } + + public String getPackageTimestamp() { + return properties.getProperty(PACKAGE_TIMESTAMP); + } + + public void store(OutputStream outStream) throws IOException { + properties.store(outStream, null); + } + + public static NMFPackageMetadata load(InputStream inStream) throws IOException { + Properties props = new Properties(); + props.load(inStream); + return new NMFPackageMetadata(props); + } + + public NMFPackageDescriptor toPackageDescriptor() { + NMFPackageDetails details = new NMFPackageDetails(properties); + NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); + int size = Integer.parseInt(properties.getProperty(FILE_COUNT, "0")); + + for (int i = 0; i < size; i++) { + String suffix = "_" + i; + String path = properties.getProperty(FILE_PATH + suffix, ""); + long crc = Long.parseLong(properties.getProperty(FILE_CRC + suffix, "0")); + NMFPackageFile file = new NMFPackageFile(path, crc); + descriptor.addFile(file); + } + + return descriptor; + } +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java index 200c6df59..87f689c8d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java @@ -56,5 +56,5 @@ public static NMFPackageDescriptor parseReceipt(final String version, throw new IOException("Unknown version: " + version); } } - + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index dd0cc0975..b17eafe3c 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -21,14 +21,18 @@ package esa.mo.nmf.nmfpackage.tests; import esa.mo.helpertools.helpers.HelperTime; +import esa.mo.nmf.nmfpackage.HelperNMFPackage; import esa.mo.nmf.nmfpackage.NMFPackageCreator; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageMetadata; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.ccsds.moims.mo.mal.structures.Time; @@ -89,6 +93,18 @@ public static void createPackage() { // Test if the created file can be parsed ZipFile writtenFile = new ZipFile(location); NMFPackageDescriptor theDescriptor = NMFPackageDescriptor.parseZipFile(writtenFile); + theDescriptor = null; + + + ZipEntry entry = writtenFile.getEntry(NMFPackageMetadata.FILENAME); + + // Try to open the the receipt file inside the Zip file + // and parse it into a NMFPackageDescriptor object + try (InputStream stream = writtenFile.getInputStream(entry)) { + NMFPackageMetadata metadata = NMFPackageMetadata.load(stream); + metadata = null; + } + } catch (IOException ex) { Logger.getLogger(SimpleDemoPackageCreation.class.getName()).log( Level.SEVERE, "The file could not be processed!", ex); diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 7980a460b..c56c0d411 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -79,6 +79,9 @@ public class GenerateNMFPackageMojo extends AbstractMojo { @Parameter(property = "generate-nmf-package.nmfVersion", defaultValue = "${esa.nmf.version-qualifier}") private String nmfVersion; + /** + * The App maximum heap size to be set on the JVM + */ @Parameter(property = "generate-nmf-package.maxHeap", defaultValue = "128m") private String maxHeap; From 46003062a4aad8934bbfd3117431430a6dc0ee62 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 10:58:12 +0200 Subject: [PATCH 079/173] [nmf-pack] Fixes the max heap problem --- .../java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 290daab7a..806b3e6ad 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -139,7 +139,7 @@ public static void writeReceipt(final BufferedWriter bw, bw.newLine(); bw.write(MAINJAR + descriptor.getDetails().getMainJar()); bw.newLine(); - bw.write(MAXHEAP + descriptor.getDetails().getMainJar()); + bw.write(MAXHEAP + descriptor.getDetails().getMaxHeap()); bw.newLine(); // Iterate the newLocations and write them down on the file From 7929d4a0dabf86987243dcf515041696b44b9c60 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 16:30:49 +0200 Subject: [PATCH 080/173] Updates the AI service to provide more information --- ...ficialIntelligenceProviderServiceImpl.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index d9c30fd3b..8d58fc0a4 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -35,7 +35,9 @@ import esa.mo.helpertools.connections.ConnectionProvider; import java.io.File; import java.io.IOException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import org.ccsds.moims.mo.mal.MALStandardError; public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelligenceInheritanceSkeleton { @@ -155,13 +157,24 @@ public String doInference(Long modelId, String inputTilesPath, throw new MALException("The model does not end with the file extension: .xml"); } - String weightsPath = modelPath.substring(0, modelPath.length() - 4) + ".bin"; - Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( - Level.INFO, "The weights file path is:\n >> " + weightsPath); + int endIndex = modelPath.length() - 4; + String weightsPath = modelPath.substring(0, endIndex) + ".bin"; try { - String outputTilesPath = ""; + String time = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new Date()); + String outputTilesPath = inputTiles.getParent() + File.separator + "output_tiles_" + time; + + Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( + Level.INFO, "The AI service will do inference with the parameters:" + + "\n >> model: " + modelPath + + "\n >> weights: " + weightsPath + + "\n >> inputTiles: " + inputTilesPath + + "\n >> outputTiles: " + outputTilesPath); + adapter.executeInference(modelPath, weightsPath, inputTilesPath, outputTilesPath); + + Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( + Level.INFO, "The inference has been completed successfully!"); return outputTilesPath; } catch (IOException ex) { Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()).log( From dc457a66708b8ab4e4fde5e1e2326eb81687eecd Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 16:32:40 +0200 Subject: [PATCH 081/173] Updates the Linux commands to provide more info on the errors. --- .../mo/nmf/nmfpackage/LinuxUsersGroups.java | 30 +++++++++++++------ .../mo/nmf/nmfpackage/NMFPackageManager.java | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java index 4e8bf955d..07fa8c37b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java @@ -22,6 +22,7 @@ import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -260,26 +261,37 @@ private static String runCommand(String[] cmd) throws IOException { p.destroyForcibly(); } - BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); - StringBuilder buffer = new StringBuilder(); - String line; - while ((line = br.readLine()) != null) { - buffer.append(line); - buffer.append("\n"); - } - + String out = extractString(p.getInputStream()); int exitValue = p.exitValue(); - String out = buffer.toString(); if (exitValue == 127) { // Command not found! throw new IOException(MSG_NOT_FOUND + "\n >> " + String.join(" ", cmd) + "\n" + out); } + if (exitValue != 0) { // Error! + String error = extractString(p.getErrorStream()); + throw new IOException("There was an error:\n >> " + + String.join(" ", cmd) + "\n" + out + "\nError:\n" + error); + } + return out; } catch (InterruptedException ex) { throw new IOException(ex); } } + private static String extractString(InputStream in) throws IOException { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + StringBuilder buffer = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + buffer.append(line); + buffer.append("\n"); + } + + return buffer.toString(); + } + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 938922ac5..a188d2c21 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -189,7 +189,7 @@ public static void install(final String packageLocation, /** * Uninstalls an NMF Package using the respective package descriptor. * - * @param descriptor The desccriptor + * @param descriptor The descriptor * @param keepUserData A flag that sets if the user data is kept * @throws IOException if there was a problem during the uninstallation */ From ea934e259ce19ec0d8a17491f6315d5d4476e3e2 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 16:35:43 +0200 Subject: [PATCH 082/173] CTT can now run directly from the main project folder (example, for live debugging) --- .../consumer-test-tool/consumer.properties | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 sdk/tools/consumer-test-tool/consumer.properties diff --git a/sdk/tools/consumer-test-tool/consumer.properties b/sdk/tools/consumer-test-tool/consumer.properties new file mode 100644 index 000000000..c7414a031 --- /dev/null +++ b/sdk/tools/consumer-test-tool/consumer.properties @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------------------------------ +# MO App configurations +helpertools.configurations.MOappName=CTT +#------------------------------------------------------------------------------------------------------ + +# Network Configuration tags (shall be used to form the network field) +helpertools.configurations.OrganizationName=esa +helpertools.configurations.MissionName=NMF_SDK +helpertools.configurations.NetworkZone=Ground +helpertools.configurations.DeviceName=Workstation +#------------------------------------------------------------------------------------------------------ + +# Provider URI file location +providerURI.properties=providerURIs.properties + +# MAL HTTP protocol properties +org.ccsds.moims.mo.mal.transport.protocol.malhttp=esa.mo.mal.transport.http.HTTPTransportFactoryImpl +org.ccsds.moims.mo.mal.transport.http.numconnections=10 +org.ccsds.moims.mo.mal.transport.http.inputprocessors=10 +#org.ccsds.moims.mo.mal.transport.http.port=xxxxx +#org.ccsds.moims.mo.mal.transport.http.host=localhost +#org.ccsds.moims.mo.mal.encoding.protocol.malhttp=esa.mo.mal.encoder.string.StringStreamFactory +org.ccsds.moims.mo.mal.encoding.protocol.malhttp=esa.mo.mal.encoder.binary.BinaryStreamFactory +#org.ccsds.moims.mo.mal.transport.http.serverimpl=esa.mo.mal.transport.http.api.impl.jetty.JettyServer +#org.ccsds.moims.mo.mal.transport.http.clientimpl=esa.mo.mal.transport.http.api.impl.jetty.JettyClient +#org.ccsds.moims.mo.mal.transport.http.bindingmode=NoResponse +org.ccsds.moims.mo.mal.transport.http.bindingmode=NoEncoding +#org.ccsds.moims.mo.mal.transport.http.bindingmode=RequestResponse + +# TCP/IP protocol properties +org.ccsds.moims.mo.mal.transport.protocol.maltcp=esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl +org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory +#org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.split.SplitBinaryStreamFactory +org.ccsds.moims.mo.mal.transport.tcpip.autohost=true + +# RMI protocol properties +org.ccsds.moims.mo.mal.transport.protocol.rmi=esa.mo.mal.transport.rmi.RMITransportFactoryImpl +#org.ccsds.moims.mo.mal.encoding.protocol.rmi=esa.mo.mal.encoder.string.StringStreamFactory +org.ccsds.moims.mo.mal.encoding.protocol.rmi=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory + +org.ccsds.moims.mo.mal.transport.gen.debug=true +org.ccsds.moims.mo.mal.transport.gen.wrap=false \ No newline at end of file From a97b56433ccf2e2324a51bc85a4aeb27f17b7688 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 16:36:35 +0200 Subject: [PATCH 083/173] Cleans the code --- .../esa/mo/nmf/apps/edgeai/MCAdapter.java | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java index 39fab65d7..19e5a0842 100644 --- a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java @@ -72,9 +72,29 @@ public void initialRegistrations(MCRegistration registration) { ActionDefinitionDetailsList actionDefs = new ActionDefinitionDetailsList(); IdentifierList actionNames = new IdentifierList(); - registerActionAIStart(actionDefs, actionNames); - registerActionAICancel(actionDefs, actionNames); - // ---- + ArgumentDefinitionDetailsList arguments1 = new ArgumentDefinitionDetailsList(); + actionDefs.add(new ActionDefinitionDetails( + "Starts the AI inference using the AI service", + new UOctet((short) 0), + new UShort(TOTAL_STAGES), + arguments1)); + actionNames.add(new Identifier(ACTION_START_AI)); + + ArgumentDefinitionDetailsList arguments2 = new ArgumentDefinitionDetailsList(); + { + Byte rawType = Attribute._LONG_TYPE_SHORT_FORM; + arguments2.add(new ArgumentDefinitionDetails( + new Identifier("process id"), + "process id", + rawType, "", null, null, null)); + } + + actionDefs.add(new ActionDefinitionDetails( + "Cancel the AI processing", + new UOctet((short) 0), + new UShort(1), + arguments2)); + actionNames.add(new Identifier(ACTION_CANCEL_AI)); registration.registerActions(actionNames, actionDefs); } @@ -82,6 +102,8 @@ public void initialRegistrations(MCRegistration registration) { @Override public UInteger actionArrived(Identifier name, AttributeValueList attributeValues, Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { + LOG.log(Level.INFO, "Action arrived, with name: " + name.getValue()); + if (ACTION_START_AI.equals(name.getValue())) { triggerAIInference(actionInstanceObjId, attributeValues); return null; // Success! @@ -98,34 +120,6 @@ public void onProcessCompleted(Long id, int exitCode) { publishParameter(id.toString(), exitCode); } - private void registerActionAIStart(ActionDefinitionDetailsList actionDefs, IdentifierList actionNames) { - ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); - actionDefs.add(new ActionDefinitionDetails( - "Starts the AI inference using the AI service", - new UOctet((short) 0), - new UShort(TOTAL_STAGES), - arguments)); - actionNames.add(new Identifier(ACTION_START_AI)); - } - - private void registerActionAICancel(ActionDefinitionDetailsList actionDefs, IdentifierList actionNames) { - ArgumentDefinitionDetailsList arguments = new ArgumentDefinitionDetailsList(); - { - Byte rawType = Attribute._LONG_TYPE_SHORT_FORM; - arguments.add(new ArgumentDefinitionDetails( - new Identifier("process id"), - "process id", - rawType, "", null, null, null)); - } - - actionDefs.add(new ActionDefinitionDetails( - "Cancel the AI processing", - new UOctet((short) 0), - new UShort(1), - arguments)); - actionNames.add(new Identifier(ACTION_CANCEL_AI)); - } - public void triggerAIInference(Long actionInstanceObjId, AttributeValueList attributeValues) { /* int minProcessingDurationSeconds = getAs(attributeValues.get(0)); @@ -145,6 +139,8 @@ public void triggerAIInference(Long actionInstanceObjId, AttributeValueList attr processMap.put(actionInstanceObjId, exec); */ + + LOG.log(Level.INFO, "Triggering AI inference..."); try { File aiModel = new File("ai-model"); @@ -173,7 +169,10 @@ public void triggerAIInference(Long actionInstanceObjId, AttributeValueList attr ArtificialIntelligenceStub aiService = connector.getPlatformServices().getAIService(); Long id = aiService.setModel(modelPath); + LOG.log(Level.SEVERE, "The model was set with id: " + id); + aiService.doInference(id, inputTilesPath); + LOG.log(Level.SEVERE, "The AI inference was successful!"); } catch (MALInteractionException | MALException | IOException | NMFException ex) { LOG.log(Level.SEVERE, "AI was not performed...", ex); } From 275af692bb1f5587e47d9038822df6fcc9896738 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 16:46:13 +0200 Subject: [PATCH 084/173] Better logging messages --- .../esa/mo/nmf/ctt/guis/ConsumerTestToolGUI.java | 8 -------- .../mo/nmf/ctt/services/mc/ActionConsumerPanel.java | 13 +++++++++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/guis/ConsumerTestToolGUI.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/guis/ConsumerTestToolGUI.java index 97fa87da0..98603f8c2 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/guis/ConsumerTestToolGUI.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/guis/ConsumerTestToolGUI.java @@ -133,14 +133,6 @@ private void initComponents() { tabs = new javax.swing.JTabbedPane(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - addWindowListener(new java.awt.event.WindowAdapter() { - @Override - public void windowClosing(java.awt.event.WindowEvent e) { - // call dispose here, so on panels the removeNotify is also called - // to clean up the connections - e.getWindow().dispose(); - } - }); setMinimumSize(new java.awt.Dimension(800, 600)); setName("Form"); // NOI18N setPreferredSize(new java.awt.Dimension(1100, 600)); diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/mc/ActionConsumerPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/mc/ActionConsumerPanel.java index ecc65cb44..88e39b2d5 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/mc/ActionConsumerPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/services/mc/ActionConsumerPanel.java @@ -241,7 +241,11 @@ private void submitActionActionPerformed(java.awt.event.ActionEvent evt) {//GEN- } try { - gma.launchAction(actionTable.getSelectedDefinitionObjId(), argumentValueList, new ActionAdapter() { + Long definitionObjId = actionTable.getSelectedDefinitionObjId(); + Logger.getLogger(ActionConsumerPanel.class.getName()).log(Level.INFO, + "Triggering action with id: " + definitionObjId); + + gma.launchAction(definitionObjId, argumentValueList, new ActionAdapter() { @Override public void submitActionAckReceived(MALMessageHeader msgHeader, Map qosProperties) { super.submitActionAckReceived(msgHeader, qosProperties); @@ -253,11 +257,12 @@ public void submitActionAckReceived(MALMessageHeader msgHeader, Map qosPropertie public void submitActionErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { super.submitActionErrorReceived(msgHeader, error, qosProperties); - JOptionPane.showMessageDialog(null, "The action submittal has failed.", "Error", - JOptionPane.PLAIN_MESSAGE); + JOptionPane.showMessageDialog( + null, + "The submitted action failed: " + error.toString(), + "Error", JOptionPane.PLAIN_MESSAGE); } }); - } catch (NMFException ex) { JOptionPane.showMessageDialog(null, "There was an error with the submitted action.", "Error", JOptionPane.PLAIN_MESSAGE); From 2405f8985cbf4885ec1aadd770a579bc73e49dc0 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 21:18:31 +0200 Subject: [PATCH 085/173] Removes the exec from the generation of the start app script. --- .../src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index 1116b72c4..2488a5b33 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -100,7 +100,9 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("export NMF_LIB\n"); str.append("\n"); - str.append("exec $JAVA_CMD $JAVA_OPTS \\\n"); + // The command "exec" spawns the execution in a different process + // str.append("exec "); + str.append("$JAVA_CMD $JAVA_OPTS \\\n"); str.append(" -classpath \"$NMF_LIB/*:$MAIN_JAR_NAME\" \\\n"); str.append(" \"$MAIN_CLASS_NAME\" \\\n"); str.append(" \"$@\"\n"); From 6c0aa741aa295d6068d1c9a7aa14de475c83eea2 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 7 Oct 2022 21:19:07 +0200 Subject: [PATCH 086/173] Updates the comment message --- .../esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java index 6b1e8dc81..ab429baa3 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java @@ -359,7 +359,7 @@ public void setValue(final ParameterRawValueList rawValueList, final MALInteract continue; } - // requirement: 3.3.9.2.f the new rawValues type and its definitions rawType must be the same + // requirement: 3.3.9.2.f the new rawValues type and definitions rawType must be the same if (newValue.getRawValue() != null && !newValue.getRawValue().getTypeShortForm().equals(new Integer(pDef.getRawType()))) { invIndexList.add(new UInteger(index)); From 1a266dd20bf21b96b51d63c8a773290e73a0c186 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 12 Oct 2022 12:25:52 +0200 Subject: [PATCH 087/173] Cleans up the code and adds the license to the header of the files --- .../impl/archive/db/CallableDeleteQuery.java | 23 +++++++++++++- .../impl/archive/db/CallableGenericQuery.java | 25 ++++++++++++++-- .../db/CallableGetAllCOMObjectIds.java | 26 +++++++++++++--- .../archive/db/CallableGetCOMObjects.java | 30 +++++++++++++++---- .../impl/archive/db/CallableSelectQuery.java | 20 +++++++++++++ .../com/impl/archive/db/DatabaseBackend.java | 7 ++--- .../impl/archive/db/PreparedStatements.java | 20 +++++++++++++ .../com/impl/archive/db/RunnableInsert.java | 22 +++++++++++++- .../com/impl/archive/db/RunnableRemove.java | 20 +++++++++++++ .../com/impl/archive/db/RunnableUpdate.java | 20 +++++++++++++ .../mo/com/impl/archive/fast/FastIndex.java | 8 +++-- .../mo/com/impl/archive/fast/FastObjId.java | 1 + .../ParameterProviderServiceImpl.java | 2 +- .../sm/impl/provider/AppsLauncherManager.java | 2 +- 14 files changed, 203 insertions(+), 23 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableDeleteQuery.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableDeleteQuery.java index 710ccda4b..485f64a3d 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableDeleteQuery.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableDeleteQuery.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.Connection; @@ -11,7 +31,8 @@ import org.ccsds.moims.mo.mal.structures.IntegerList; public class CallableDeleteQuery extends CallableGenericQuery { - public static final Logger LOGGER = Logger.getLogger(CallableDeleteQuery.class.getName()); + + public static Logger LOGGER = Logger.getLogger(CallableDeleteQuery.class.getName()); public CallableDeleteQuery(TransactionsProcessor transactionsProcessor, IntegerList objTypeIds, ArchiveQuery archiveQuery, IntegerList domainIds, Integer providerURIId, Integer networkId, diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGenericQuery.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGenericQuery.java index d17082c29..c861cf6c2 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGenericQuery.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGenericQuery.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.util.concurrent.Callable; @@ -9,7 +29,8 @@ import org.ccsds.moims.mo.com.archive.structures.QueryFilter; import org.ccsds.moims.mo.mal.structures.IntegerList; -abstract class CallableGenericQuery implements Callable { +public abstract class CallableGenericQuery implements Callable { + public static Logger LOGGER = Logger.getLogger(CallableDeleteQuery.class.getName()); protected final TransactionsProcessor transactionsProcessor; @@ -136,4 +157,4 @@ public static String generateQueryStringFromLists(final String field, final Inte return stringForWildcards + ") AND "; } -} \ No newline at end of file +} diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetAllCOMObjectIds.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetAllCOMObjectIds.java index 625dcb2df..9e832ecfe 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetAllCOMObjectIds.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetAllCOMObjectIds.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.PreparedStatement; @@ -9,9 +29,7 @@ import org.ccsds.moims.mo.mal.structures.LongList; final class CallableGetAllCOMObjectIds implements Callable { - /** - * - */ + private final TransactionsProcessor transactionsProcessor; private final Integer domainId; private final Integer objTypeId; @@ -49,4 +67,4 @@ public LongList call() { this.transactionsProcessor.dbBackend.getAvailability().release(); return objIds; } -} \ No newline at end of file +} diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetCOMObjects.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetCOMObjects.java index dc6d6d0d4..f737f4031 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetCOMObjects.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableGetCOMObjects.java @@ -1,5 +1,26 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; +import esa.mo.com.impl.archive.entities.COMObjectEntity; import java.sql.Array; import java.sql.Connection; import java.sql.PreparedStatement; @@ -10,12 +31,9 @@ import java.util.concurrent.Callable; import java.util.logging.Level; import java.util.stream.Collectors; - import org.ccsds.moims.mo.mal.structures.LongList; -import esa.mo.com.impl.archive.entities.COMObjectEntity; - -final class CallableGetCOMObjects implements Callable> { +public final class CallableGetCOMObjects implements Callable> { // for sqlite. %s will be replaced with proper ids. private final static String SELECT_COM_OBJECTS = "SELECT objectTypeId, domainId, objId, " + @@ -51,7 +69,7 @@ public List call() { if (this.transactionsProcessor.dbBackend.isPostgres) { // Array-bind is supported in Postgres PreparedStatement stmt = this.transactionsProcessor.dbBackend.getPreparedStatements() - .getSelectCOMObjects(); + .getSelectCOMObjects(); Array idsArray = c.createArrayOf("BIGINT", ids.toArray()); stmt.setInt(1, objTypeId); stmt.setInt(2, domainId); @@ -78,4 +96,4 @@ public List call() { this.transactionsProcessor.dbBackend.getAvailability().release(); return perObjs; } -} \ No newline at end of file +} diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableSelectQuery.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableSelectQuery.java index a84e6fc4c..3e4500616 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableSelectQuery.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/CallableSelectQuery.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.Connection; diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java index 30d1a8ff0..5d1fecd9f 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency + * Copyright (C) 2022 European Space Agency * European Space Operations Centre * Darmstadt * Germany @@ -13,15 +13,14 @@ * You on an "as is" basis and without warranties of any kind, including without * limitation merchantability, fitness for a particular purpose, absence of * defects or errors, accuracy or non-infringement of intellectual property rights. - * + * * See the License for the specific language governing permissions and - * limitations under the License. + * limitations under the License. * ---------------------------------------------------------------------------- */ package esa.mo.com.impl.archive.db; import esa.mo.com.impl.provider.ArchiveManager; - import java.io.File; import java.io.IOException; import java.sql.Connection; diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/PreparedStatements.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/PreparedStatements.java index f4af4dded..7ccb8c66b 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/PreparedStatements.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/PreparedStatements.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.Connection; diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableInsert.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableInsert.java index aaa12ca32..77cc64f67 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableInsert.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableInsert.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.Connection; @@ -92,4 +112,4 @@ void persistObjects(final ArrayList perObjs) { LOGGER.log(Level.SEVERE, null, ex); } } -} \ No newline at end of file +} diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableRemove.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableRemove.java index e27aa2cc0..5565fb12e 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableRemove.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableRemove.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.Connection; diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableUpdate.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableUpdate.java index 7f4cdc5ac..69f1a3ac7 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableUpdate.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/RunnableUpdate.java @@ -1,3 +1,23 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ package esa.mo.com.impl.archive.db; import java.sql.Connection; diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastIndex.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastIndex.java index 97f5b19b3..95ce64b6e 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastIndex.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastIndex.java @@ -31,11 +31,13 @@ import java.util.logging.Logger; /** - * Contains the set of different key fields that the database contains in its dedicated table - * and avoids constant checking on it which makes things go much faster. + * Contains the set of different key fields that the database contains in its + * dedicated table and avoids constant checking on it which makes things go much + * faster. */ public abstract class FastIndex { - public static final Logger LOGGER = Logger.getLogger(FastIndex.class.getName()); + + protected static final Logger LOGGER = Logger.getLogger(FastIndex.class.getName()); protected final String QUERY_DELETE; protected final String QUERY_SELECT; protected final String QUERY_INSERT; diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastObjId.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastObjId.java index 5f4ab38b9..4c3ad3875 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastObjId.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/fast/FastObjId.java @@ -34,6 +34,7 @@ * database when it is necessary. */ public class FastObjId { + private final DatabaseBackend dbBackend; private HashMap fastID; diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java index ab429baa3..6b1e8dc81 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java @@ -359,7 +359,7 @@ public void setValue(final ParameterRawValueList rawValueList, final MALInteract continue; } - // requirement: 3.3.9.2.f the new rawValues type and definitions rawType must be the same + // requirement: 3.3.9.2.f the new rawValues type and its definitions rawType must be the same if (newValue.getRawValue() != null && !newValue.getRawValue().getTypeShortForm().equals(new Integer(pDef.getRawType()))) { invIndexList.add(new UInteger(index)); diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index cf9c8ba23..90ddf7d8b 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -497,7 +497,7 @@ protected void startAppProcess(final ProcessExecutionHandler handler, final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); pb.environment().clear(); pb.environment().putAll(env); - + pb.directory(appFolder); LOGGER.log(Level.INFO, "Initializing ''{0}'' app in dir: {1}, using launcher command: {2}", From 848fe5a02d2a74623891074cd2b53a51e81cb753 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 15:52:33 +0200 Subject: [PATCH 088/173] Code cleanup --- core/nmf-composites/nanosat-mo-supervisor/pom.xml | 1 - .../MCSupervisorBasicAdapter.java | 14 +++++++++++--- .../NanosatMOSupervisorBasicImpl.java | 1 - .../Metadata.java} | 0 .../mo/nmf/nmfpackage/metadata/package-info.java | 4 ++++ 5 files changed, 15 insertions(+), 5 deletions(-) rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{descriptor/NMFPackageMetadata.java => metadata/Metadata.java} (100%) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java diff --git a/core/nmf-composites/nanosat-mo-supervisor/pom.xml b/core/nmf-composites/nanosat-mo-supervisor/pom.xml index f054e138e..08986f52e 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/pom.xml +++ b/core/nmf-composites/nanosat-mo-supervisor/pom.xml @@ -58,7 +58,6 @@ int.esa.nmf.core nmf-package-lib - 2.1.0-SNAPSHOT jar diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java index 8cf8b3e19..32cbe0709 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/MCSupervisorBasicAdapter.java @@ -21,15 +21,23 @@ package esa.mo.nmf.nanosatmosupervisor; import esa.mo.helpertools.connections.ConnectionConsumer; - +import esa.mo.helpertools.misc.OSValidator; +import esa.mo.helpertools.misc.ShellCommander; +import esa.mo.nmf.annotations.Action; +import esa.mo.nmf.annotations.ActionParameter; +import esa.mo.nmf.annotations.Parameter; +import esa.mo.nmf.nanosatmosupervisor.parameter.OBSWParameterManager; +import esa.mo.nmf.MCRegistration; +import esa.mo.nmf.MonitorAndControlNMFAdapter; +import esa.mo.nmf.NMFException; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import jakarta.xml.bind.JAXBException; import javax.xml.stream.XMLStreamException; +import jakarta.xml.bind.JAXBException; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; import org.ccsds.moims.mo.mal.MALStandardError; @@ -38,7 +46,6 @@ import org.ccsds.moims.mo.mal.transport.MALMessageHeader; import org.ccsds.moims.mo.mc.parameter.structures.ParameterRawValue; import org.ccsds.moims.mo.platform.gps.consumer.GPSAdapter; - import esa.mo.nmf.MCRegistration; import esa.mo.nmf.MonitorAndControlNMFAdapter; import esa.mo.nmf.NMFException; @@ -56,6 +63,7 @@ import org.ccsds.moims.mo.platform.autonomousadcs.structures.AttitudeModeSunPointing; import org.ccsds.moims.mo.platform.autonomousadcs.structures.AttitudeTelemetry; import org.ccsds.moims.mo.platform.autonomousadcs.structures.Quaternion; +import org.ccsds.moims.mo.platform.gps.consumer.GPSAdapter; /** * diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java index 8eb102b46..ea88566d1 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java @@ -29,7 +29,6 @@ import esa.mo.platform.impl.util.PlatformServicesConsumer; import esa.mo.platform.impl.util.PlatformServicesProviderInterface; import esa.mo.platform.impl.util.PlatformServicesProviderSoftSim; - import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.mal.MALException; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageMetadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java similarity index 100% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageMetadata.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java new file mode 100644 index 000000000..eed5aee2c --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java @@ -0,0 +1,4 @@ +/** + * Package containing the NMF Package classes for the descriptor of the package. + */ +package esa.mo.nmf.nmfpackage.descriptor; From 4141ca5e69ec5fd1477a3058756a3f91c3a33501 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 15:54:22 +0200 Subject: [PATCH 089/173] [nmf-package] Migrates NMF Packages to version 4 --- .../PackageManagementProviderServiceImpl.java | 8 +- .../mo/nmf/nmfpackage/HelperNMFPackage.java | 12 +- .../nmf/nmfpackage/NMFDigitalSignature.java | 2 +- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 108 ++++++++ .../mo/nmf/nmfpackage/NMFPackageCreator.java | 73 ++--- .../mo/nmf/nmfpackage/NMFPackageManager.java | 233 +++++++--------- .../nmf/nmfpackage/NMFPackagePMBackend.java | 25 +- .../descriptor/NMFPackageDescriptor.java | 79 +++--- .../descriptor/NMFPackageDetails.java | 25 +- .../mo/nmf/nmfpackage/metadata/Metadata.java | 253 ++++++++++++++++-- .../nmf/nmfpackage/metadata/package-info.java | 4 +- .../nmf/nmfpackage/receipt/ReceiptMaster.java | 13 +- .../nmfpackage/receipt/ReceiptVersion1.java | 6 +- .../nmfpackage/receipt/ReceiptVersion2.java | 1 + .../nmfpackage/receipt/ReceiptVersion3.java | 1 + .../tests/SimpleDemoPackageCreation.java | 24 +- .../nmfpackage/GenerateNMFPackageMojo.java | 6 +- 17 files changed, 576 insertions(+), 297 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java index 397e2937c..8160ff986 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java @@ -344,13 +344,11 @@ public void upgrade(final IdentifierList names, final UpgradeInteraction interac unkIndexList.add(new UInteger(i)); } - if (backend.isPackageInstalled(names.get(i).getValue())) { - invIndexList.add(new UInteger(i)); - } - - // Throw error if already installed! // Before installing, we need to check the package integrity! boolean integrity = backend.checkPackageIntegrity(availablePackages.get(i)); + if (!integrity) { + invIndexList.add(new UInteger(i)); + } // The installation cannot go forward here if the integrity is false! } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java index 2488a5b33..8d3c5669b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to @@ -62,7 +62,7 @@ public static long calculateCRCFromInputStream(final InputStream inputStream) th return crc.getValue(); } - private static String getBanner(){ + private static String getBanner() { StringBuilder str = new StringBuilder(); str.append("#######################################################\n"); str.append("# This file was auto-generated by the NMF\n"); @@ -156,16 +156,20 @@ public static String generateTransportProperties() throws IOException { str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); */ - str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=true\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.host=xxx.xxx.xxx.xxx\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); - + return str.toString(); } public static File findAppJarInFolder(File folder) throws IOException { File[] fList = folder.listFiles(); + + if (fList == null) { + throw new IOException("The directory was not found: " + folder.getAbsolutePath()); + } + ArrayList possibleOptions = new ArrayList(); for (File file : fList) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java index 3a4a3f15b..7febf7bd5 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java new file mode 100644 index 000000000..1c56177cf --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -0,0 +1,108 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this zipFile except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage; + +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.metadata.Metadata; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +/** + * The NMFPackage class holds the information contained in an NMF Package. + * + * @author Cesar Coelho + */ +public class NMFPackage { + + private final ZipFile zipFile; + private Metadata metadata; + + public NMFPackage(String filepath) throws IOException { + this.zipFile = new ZipFile(filepath); + } + + public ZipFile getZipFile() { + return zipFile; + } + + public synchronized Metadata getMetadata() throws IOException { + if (metadata != null) { + return metadata; + } + + metadata = Metadata.parseZipFile(zipFile); + return metadata; + } + + public long calculateMetadataCRC() throws IOException { + ZipEntry entry = zipFile.getEntry(Metadata.FILENAME); + + if (entry == null) { + entry = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); + } + + long crc; + try (InputStream zis = zipFile.getInputStream(entry)) { + crc = HelperNMFPackage.calculateCRCFromInputStream(zis); + } + + return crc; + } + + public ZipEntry getZipFileEntry(String path) { + ZipEntry entry = zipFile.getEntry(path); + + if (entry == null) { + entry = zipFile.getEntry(path.replace("\\", "/")); + } + + return entry; + } + + public void verifyPackageIntegrity() throws IOException { + ArrayList files = metadata.getFiles(); + + for (int i = 0; i < files.size(); i++) { + NMFPackageFile filepack = files.get(i); + String path = filepack.getPath().trim(); + ZipEntry entry = this.getZipFileEntry(path); + + if (entry == null) { + StringBuilder allEntries = new StringBuilder(); + for (Object o : zipFile.stream().toArray()) { + allEntries.append(((ZipEntry) o).getName()).append("\n"); + } + + throw new IOException("(" + i + "/" + files.size() + ")" + + " The metadata is incorrect. " + + "One of the files does not exist: " + path + + "\nAvailable entries:\n" + allEntries.toString()); + } + + if (filepack.getCRC() != entry.getCrc()) { + throw new IOException("The CRC does not match!"); + } + } + } +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 2490f5908..bac534c03 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to @@ -22,18 +22,13 @@ import esa.mo.helpertools.misc.Const; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageMetadata; -import esa.mo.nmf.nmfpackage.receipt.ReceiptMaster; +import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -80,42 +75,52 @@ public static void zipFiles(String outputPath, ArrayList from, } } - public static String nmfPackageCreator(NMFPackageDetails details, ArrayList filesInput, - ArrayList newLocationsInput) { + @Deprecated + public static String nmfPackageCreator(NMFPackageDetails details, + ArrayList filesInput, ArrayList newLocationsInput) { return NMFPackageCreator.nmfPackageCreator(details, filesInput, newLocationsInput, null); } - public static String nmfPackageCreator(NMFPackageDetails details, ArrayList filesInput, - ArrayList newLocationsInput, String destinationFolder) { - NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); - NMFPackageMetadata metadata = new NMFPackageMetadata(details.getProperties()); + @Deprecated + public static String nmfPackageCreator(NMFPackageDetails details, + ArrayList filesInput, ArrayList newLocationsInput, + String destinationFolder) { + Metadata metadata = new Metadata(details.getProperties()); + return NMFPackageCreator.nmfPackageCreator(metadata, filesInput, newLocationsInput, destinationFolder); + } + public static String nmfPackageCreator(Metadata metadata, + ArrayList filesInput, ArrayList newLocationsInput, + String destinationFolder) { final ArrayList files = new ArrayList<>(filesInput); final ArrayList newLocations = new ArrayList<>(newLocationsInput); + int size = newLocations.size(); - for (int i = 0; i < newLocations.size(); i++) { + for (int i = 0; i < size; i++) { try { String path = newLocations.get(i); long crc = HelperNMFPackage.calculateCRCFromFile(files.get(i)); - descriptor.addFile(new NMFPackageFile(path, crc)); - metadata.addProperty(NMFPackageMetadata.FILE_PATH + "_" + i, path); - metadata.addProperty(NMFPackageMetadata.FILE_CRC + "_" + i, String.valueOf(crc)); + //descriptor.addFile(new NMFPackageFile(path, crc)); + metadata.addProperty(Metadata.FILE_PATH + "." + i, path); + metadata.addProperty(Metadata.FILE_CRC + "." + i, String.valueOf(crc)); } catch (IOException ex) { Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, "There was a problem during the CRC calculation.", ex); } } + + metadata.addProperty(Metadata.FILE_COUNT, String.valueOf(size)); // ------------------------------------------------------------------- // Generate nmfPackage.receipt + /* Logger.getLogger(NMFPackageCreator.class.getName()).log( Level.INFO, "Generating receipt file..."); - try { // Write the receipt file - FileOutputStream sigfos = new FileOutputStream(HelperNMFPackage.RECEIPT_FILENAME); + // Write the receipt file + try (FileOutputStream sigfos = new FileOutputStream(HelperNMFPackage.RECEIPT_FILENAME)) { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sigfos)); ReceiptMaster.writeLatestReceipt(descriptor, bw); - sigfos.close(); } catch (IOException ex) { Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, null, ex); } @@ -124,27 +129,27 @@ public static String nmfPackageCreator(NMFPackageDetails details, ArrayList> From version: " + oldDescriptor.getDetails().getVersion() - + "\n >> To version: " + newDescriptor.getDetails().getVersion() + + "\n >> From version: " + oldPackMetadata.getPackageVersion() + + " (timestamp: " + oldPackMetadata.getPackageTimestamp() + ")" + + "\n >> To version: " + newPackMetadata.getPackageVersion() + + " (timestamp: " + newPackMetadata.getPackageTimestamp() + ")" ); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Removing the previous files..."); - removeFiles(oldDescriptor); - - String packageName = oldDescriptor.getDetails().getPackageName(); + removeFiles(oldPackMetadata); - boolean isApp = true; + String packageName = oldPackMetadata.getPackageName(); + boolean isApp = oldPackMetadata.isAppPackage(); if (isApp) { // This directory should be passed in the method signature: @@ -308,7 +302,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the new files to the locations..."); - installFiles(zipFile, nmfDir); + installFiles(newPack, nmfDir); if (isApp) { String username = null; @@ -318,7 +312,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro if ((new OSValidator()).isUnix()) { username = generateUsername(packageName); - generateStartSHScript(newDescriptor, installationDir, nmfDir); + generateStartSHScript(newPackMetadata, installationDir, nmfDir); } createAuxiliaryFiles(installationDir, username); @@ -336,10 +330,12 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro // --------------------------------------- // Store a copy of the newReceipt to know that it has been installed! + newPackMetadata.store(oldReceiptFile); + + /* //create the file otherwise we get FileNotFoundException new File(oldReceiptFile.getParent()).mkdirs(); - // ----------------- - + final FileOutputStream fos = new FileOutputStream(oldReceiptFile); // Output location final InputStream zis = zipFile.getInputStream(newReceipt); byte[] buffer = new byte[1024]; @@ -351,31 +347,14 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro fos.close(); zis.close(); + */ // --------------------------------------- - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully upgraded from location: " + packageLocation); System.out.printf(SEPARATOR); } - private static void verifyPackageIntegrity(ZipFile zipFile, - NMFPackageDescriptor descriptor) throws IOException { - for (int i = 0; i < descriptor.getFiles().size(); i++) { - NMFPackageFile file = descriptor.getFiles().get(i); - ZipEntry entry = zipFile.getEntry(file.getPath()); - - if (entry == null) { - throw new IOException("The descriptor is incorrect. " - + "One of the files does not exist: " + file.getPath()); - } - - if (file.getCRC() != entry.getCrc()) { - throw new IOException("The CRC does not match!"); - } - } - } - private static void removeAuxiliaryFiles(File installationDir, String appName) throws IOException { String providerPath = installationDir.getAbsolutePath() + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; @@ -386,7 +365,7 @@ private static void removeAuxiliaryFiles(File installationDir, String appName) t // Remove the provider.properties // Remove the transport.properties - // Remove the start_benchmark.sh + // Remove the start_myAppName.sh NMFPackageManager.removeFile(new File(providerPath)); NMFPackageManager.removeFile(new File(transportPath)); NMFPackageManager.removeFile(new File(startPath)); @@ -406,10 +385,10 @@ private static void createAuxiliaryFiles(File installationDir, String username) NMFPackageManager.writeFile(transportPath, transportContent); } - private static void generateStartSHScript(NMFPackageDescriptor newDescriptor, + private static void generateStartSHScript(Metadata appDetails, File installationDir, File nmfDir) throws IOException { - String packageName = newDescriptor.getDetails().getPackageName(); - String jarName = newDescriptor.getDetails().getMainJar(); + String packageName = appDetails.getPackageName(); + String jarName = appDetails.getAppMainJar(); if (jarName.equals("")) { File jar = HelperNMFPackage.findAppJarInFolder(installationDir); @@ -419,8 +398,8 @@ private static void generateStartSHScript(NMFPackageDescriptor newDescriptor, // The Java version for now will be forced to 8, however in // the future the package should recommend a version String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); - String mainClass = newDescriptor.getDetails().getMainclass(); - String maxHeap = newDescriptor.getDetails().getMaxHeap(); + String mainClass = appDetails.getAppMainclass(); + String maxHeap = appDetails.getAppMaxHeap(); String content = HelperNMFPackage.generateLinuxStartAppScript( javaCMD, mainClass, jarName, maxHeap); @@ -432,6 +411,18 @@ private static void generateStartSHScript(NMFPackageDescriptor newDescriptor, startApp.setExecutable(true, true); } + private static void writeFile(String path, String content) { + System.out.println(" >> Creating file on: " + path); + + try (FileWriter writer = new FileWriter(path)) { + writer.write(content); + writer.flush(); + writer.close(); + } catch (IOException e) { + // Handle the exception + } + } + /** * Checks if a certain NMF package is installed. Based on the name, goes to * the receipts folder and checks. @@ -442,36 +433,22 @@ private static void generateStartSHScript(NMFPackageDescriptor newDescriptor, public static boolean isPackageInstalled(final String packageLocation) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, "Verifying if the package is installed..."); - // Find the newReceipt and get it out of the package - ZipFile zipFile; - try { - zipFile = new ZipFile(packageLocation); - } catch (IOException ex) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "The package could not be opened from file: " + packageLocation, ex); - return false; - } - ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); - NMFPackageDescriptor descriptorFromPackage; - long crcDescriptorFromPackage; + // Find the newReceipt and get it out of the package + NMFPackage pack; + Metadata metadata; try { - InputStream zis = zipFile.getInputStream(receipt); - descriptorFromPackage = NMFPackageDescriptor.parseInputStream(zis); - zis.close(); - zis = zipFile.getInputStream(receipt); - crcDescriptorFromPackage = HelperNMFPackage.calculateCRCFromInputStream(zis); - zis.close(); + pack = new NMFPackage(packageLocation); + metadata = pack.getMetadata(); } catch (IOException ex) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, - "There was a problem while determining the CRCs!", ex); + "There was a problem while reading the NMF Package!", ex); return false; } File temp = getReceiptsFolder(); - NMFPackageDetails details = descriptorFromPackage.getDetails(); - String packageName = details.getPackageName(); + String packageName = metadata.getPackageName(); String receiptFilename = packageName + RECEIPT_ENDING; File receiptFile; try { @@ -491,43 +468,30 @@ public static boolean isPackageInstalled(final String packageLocation) { } // Check the version of the installed newReceipt - NMFPackageDescriptor descriptorFromExistingReceipt; - long crcDescriptorFromExistingReceipt; - + Metadata installedMetadata; try { - FileInputStream fis = new FileInputStream(receiptFile); - descriptorFromExistingReceipt = NMFPackageDescriptor.parseInputStream(fis); - fis.close(); - fis = new FileInputStream(receiptFile); - crcDescriptorFromExistingReceipt = HelperNMFPackage.calculateCRCFromInputStream(fis); - fis.close(); + installedMetadata = Metadata.load(new FileInputStream(receiptFile)); } catch (IOException ex) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, null, ex); - return false; - } - - if (descriptorFromExistingReceipt == null) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, "This is unexpected!"); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, + "The file could not be loaded!", ex); return false; } - // Compare the versions - String version = descriptorFromExistingReceipt.getDetails().getVersion(); - if (!details.getVersion().equals(version)) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, - "The version does not match!"); + if (installedMetadata == null) { + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, + "This is unexpected! The installedMetadata should not be null"); return false; } - // We need to double check if the crc match! - if (crcDescriptorFromPackage != crcDescriptorFromExistingReceipt) { + // We need to check if the metadatas are the same! + if (!metadata.sameAs(installedMetadata)) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, - "The CRC of the receipts do not match!" + "Maybe the NMF Package is tainted!"); + "The NMF Package is not the same as the installed one!"); return false; } Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, - "The package " + details.getPackageName() + " installation folder was found!"); + "The package " + metadata.getPackageName() + " installation folder was found!"); return true; } @@ -567,16 +531,19 @@ private static String generateFilePathForSystem(final String path) throws IOExce return out.replace('\\', File.separatorChar); } - private static void installFiles(final ZipFile zipFile, File to) throws IOException { - NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); + private static void installFiles(NMFPackage pack, File to) throws IOException { + Metadata metadata = pack.getMetadata(); + ZipFile zipFile = pack.getZipFile(); File newFile; byte[] buffer = new byte[1024]; // Iterate through the files, unpack them into the right folders - for (int i = 0; i < descriptor.getFiles().size(); i++) { - NMFPackageFile file = descriptor.getFiles().get(i); - ZipEntry entry = zipFile.getEntry(file.getPath()); + ArrayList files = metadata.getFiles(); + + for (int i = 0; i < files.size(); i++) { + NMFPackageFile file = files.get(i); + ZipEntry entry = pack.getZipFileEntry(file.getPath()); final String path = generateFilePathForSystem(entry.getName()); newFile = new File(to.getCanonicalPath() + File.separator + path); @@ -609,13 +576,13 @@ private static void installFiles(final ZipFile zipFile, File to) throws IOExcept } } - private static void removeFiles(final NMFPackageDescriptor descriptor) throws IOException { + private static void removeFiles(Metadata metadata) throws IOException { File folder = getInstallationFolder(); File file; // Do the files actually match the descriptor? - for (int i = 0; i < descriptor.getFiles().size(); i++) { - NMFPackageFile packageFile = descriptor.getFiles().get(i); + for (int i = 0; i < metadata.getFiles().size(); i++) { + NMFPackageFile packageFile = metadata.getFiles().get(i); final String path = generateFilePathForSystem(packageFile.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); @@ -653,18 +620,6 @@ public static String getPublicKey(String folderLocation) { throw new UnsupportedOperationException("Not supported yet."); } - private static void writeFile(String path, String content) { - System.out.println(" >> Creating file on: " + path); - - try (FileWriter writer = new FileWriter(path)) { - writer.write(content); - writer.flush(); - writer.close(); - } catch (IOException e) { - // Handle the exception - } - } - private static String generateUsername(String appName) { return USER_NMF_APP_PREFIX + appName; } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index ca42eddfc..bdb4367ba 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to @@ -21,7 +21,7 @@ package esa.mo.nmf.nmfpackage; import esa.mo.helpertools.misc.Const; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; +import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import esa.mo.sm.impl.util.PMBackend; import java.io.IOException; @@ -92,8 +92,8 @@ public void install(final String packageName) { try { NMFPackageManager.install(packageLocation, destination); } catch (IOException ex) { - Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, "The package '" + packageName + - "' could not be installed!", ex); + Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, + "The package '" + packageName + "' could not be installed!", ex); } } @@ -102,20 +102,20 @@ public void uninstall(final String packageName, final boolean keepUserData) { String folderLocation = this.getFolderLocation(packageName); Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, "Uninstalling the package from: {0}", folderLocation); - + try { // Get the Package and descriptor to be uninstalled ZipFile zipFile = new ZipFile(folderLocation); - + // Verify integrity of the file: Are all the declared files matching their CRCs? Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Reading the receipt file that includes the list of files to be uninstalled..."); + "Reading the metadata file that includes the list of files to be uninstalled..."); - NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); - NMFPackageManager.uninstall(descriptor, keepUserData); + Metadata metadata = Metadata.parseZipFile(zipFile); + NMFPackageManager.uninstall(metadata, keepUserData); } catch (IOException ex) { - Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, "The package '" + packageName + - "' could not be uninstalled!", ex); + Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, + "The package '" + packageName + "' could not be uninstalled!", ex); } } @@ -131,7 +131,8 @@ public void upgrade(final String packageName) { try { NMFPackageManager.upgrade(packageLocation, destination); } catch (IOException ex) { - Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(NMFPackagePMBackend.class.getName()).log( + Level.SEVERE, "The package could not be upgraded!", ex); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java index 1397486c4..bffe7d8ba 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java @@ -20,16 +20,16 @@ */ package esa.mo.nmf.nmfpackage.descriptor; +import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.HelperNMFPackage; import esa.mo.nmf.nmfpackage.receipt.ReceiptMaster; import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -37,10 +37,12 @@ * * @author Cesar Coelho */ +@Deprecated public class NMFPackageDescriptor { private final NMFPackageDetails details; private final ArrayList files; + private String descriptorVersion; public NMFPackageDescriptor(NMFPackageDetails details) { this.details = details; @@ -66,48 +68,28 @@ public void addFile(final NMFPackageFile file) { * @return The descriptor of the NMF Package. */ public static NMFPackageDescriptor parseInputStream(final InputStream stream) throws IOException { - // Copy the stream to a Byte Array - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int len; - while ((len = stream.read(buffer)) > -1) { - baos.write(buffer, 0, len); - } - baos.flush(); - InputStream is1 = new ByteArrayInputStream(baos.toByteArray()); - - NMFPackageMetadata metadata = NMFPackageMetadata.load(is1); - is1.close(); - String metadataVersion = metadata.getMetadataVersion(); - - // Old system based of package receipts - if (metadataVersion == null) { - NMFPackageDescriptor newDescriptor = null; - InputStream is2 = new ByteArrayInputStream(baos.toByteArray()); - InputStreamReader isr = new InputStreamReader(is2, StandardCharsets.UTF_8); - BufferedReader br = new BufferedReader(isr); - - String line = br.readLine(); // Reads the first line! - - if (line != null) { - // Extract the version from the first line - if (line.startsWith(line)) { - int length = HelperNMFPackage.NMF_PACKAGE_DESCRIPTOR_VERSION.length(); - String version = line.substring(length).trim(); - newDescriptor = ReceiptMaster.parseReceipt(version, br); - } else { - throw new IOException("Could not read the NMF Package Descriptor version!"); - } + NMFPackageDescriptor newDescriptor = null; + InputStreamReader isr = new InputStreamReader(stream, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr); + + String line = br.readLine(); // Reads the first line! + + if (line != null) { + // Extract the version from the first line + if (line.startsWith(line)) { + int length = HelperNMFPackage.NMF_PACKAGE_DESCRIPTOR_VERSION.length(); + String version = line.substring(length).trim(); + newDescriptor = ReceiptMaster.parseReceipt(version, br); } else { - throw new IOException("The receipt file is empty!"); + throw new IOException("Could not read the NMF Package Descriptor version!"); } - - br.close(); - - return newDescriptor; + } else { + throw new IOException("The receipt file is empty!"); } - return metadata.toPackageDescriptor(); + br.close(); + + return newDescriptor; } /** @@ -124,6 +106,23 @@ public static NMFPackageDescriptor parseZipFile(final ZipFile zipFile) throws IO // and parse it into a NMFPackageDescriptor object try (InputStream stream = zipFile.getInputStream(receipt)) { return NMFPackageDescriptor.parseInputStream(stream); + //Reader reader = new InputStreamReader(stream); + //return ReceiptMaster.parseReceipt("3", new BufferedReader(reader)); } } + + public Metadata toMetadata() { + Properties props = details.getProperties(); + props.put(Metadata.PACKAGE_METADATA_VERSION, descriptorVersion); + props.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); + return new Metadata(props, files); + } + + public void setMetadataVersion(String descriptorVersion) { + this.descriptorVersion = descriptorVersion; + } + + public String getMetadataVersion() { + return this.descriptorVersion; + } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java index 1b9055954..e91ca6766 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java @@ -20,6 +20,7 @@ */ package esa.mo.nmf.nmfpackage.descriptor; +import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.util.Properties; /** @@ -63,37 +64,37 @@ public Properties getProperties() { return properties; } else { Properties props = new Properties(); - props.put(NMFPackageMetadata.PACKAGE_NAME, packageName); - props.put(NMFPackageMetadata.PACKAGE_VERSION, version); - props.put(NMFPackageMetadata.PACKAGE_TIMESTAMP, timestamp); - props.put(NMFPackageMetadata.APP_MAINCLASS, mainclass); - props.put(NMFPackageMetadata.APP_MAIN_JAR, mainJar); - props.put(NMFPackageMetadata.APP_MAX_HEAP, maxHeap); + props.put(Metadata.PACKAGE_NAME, packageName); + props.put(Metadata.PACKAGE_VERSION, version); + props.put(Metadata.PACKAGE_TIMESTAMP, timestamp); + props.put(Metadata.APP_MAINCLASS, mainclass); + props.put(Metadata.APP_MAIN_JAR, mainJar); + props.put(Metadata.APP_MAX_HEAP, maxHeap); return props; } } public String getPackageName() { - return (properties == null) ? packageName : properties.getProperty(NMFPackageMetadata.PACKAGE_NAME); + return (properties == null) ? packageName : properties.getProperty(Metadata.PACKAGE_NAME); } public String getVersion() { - return (properties == null) ? version : properties.getProperty(NMFPackageMetadata.PACKAGE_VERSION); + return (properties == null) ? version : properties.getProperty(Metadata.PACKAGE_VERSION); } public String getTimestamp() { - return (properties == null) ? timestamp : properties.getProperty(NMFPackageMetadata.PACKAGE_TIMESTAMP); + return (properties == null) ? timestamp : properties.getProperty(Metadata.PACKAGE_TIMESTAMP); } public String getMainclass() { - return (properties == null) ? mainclass : properties.getProperty(NMFPackageMetadata.APP_MAINCLASS); + return (properties == null) ? mainclass : properties.getProperty(Metadata.APP_MAINCLASS); } public String getMainJar() { - return (properties == null) ? mainJar : properties.getProperty(NMFPackageMetadata.APP_MAIN_JAR); + return (properties == null) ? mainJar : properties.getProperty(Metadata.APP_MAIN_JAR); } public String getMaxHeap() { - return (properties == null) ? maxHeap : properties.getProperty(NMFPackageMetadata.APP_MAX_HEAP); + return (properties == null) ? maxHeap : properties.getProperty(Metadata.APP_MAX_HEAP); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index df03c1746..eacc384e9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency + * Copyright (C) 2022 European Space Agency * European Space Operations Centre * Darmstadt * Germany @@ -18,43 +18,94 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage.descriptor; +package esa.mo.nmf.nmfpackage.metadata; +import esa.mo.nmf.nmfpackage.NMFPackageManager; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; +import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Map; import java.util.Properties; +import java.util.Set; +import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** + * The Metadata class holds the metadata of a NMF Package. * * @author Cesar Coelho */ -public class NMFPackageMetadata { +public class Metadata { - public static final String FILENAME = "metadata.properties"; + public static final String FILENAME = "package-metadata.properties"; + + public static final String PACKAGE_TIMESTAMP = "info.creation-timestamp"; + public static final String PACKAGE_METADATA_VERSION = "info.metadata-version"; + public static final String METADATA_VERSION_LATEST = "4"; + + public static final String PACKAGE_NAME = "info.name"; + public static final String PACKAGE_VERSION = "info.version"; - public static final String METADATA_VERSION = "NMFPackageMetadataVersion"; - public static final String PACKAGE_TIMESTAMP = "PackageCreationTimestamp"; - public static final String PACKAGE_NAME = "PackageName"; - public static final String PACKAGE_VERSION = "PackageVersion"; // PACKAGE_TYPE: "app", "nmf-update", "mission-update", "dependency", "java" - public static final String PACKAGE_TYPE = "PackageType"; + public static final String PACKAGE_TYPE = "info.type"; + public static final String TYPE_APP = "app"; + public static final String TYPE_DEPENDENCY = "dependency"; + public static final String TYPE_UPDATE_JAVA = "java"; + public static final String TYPE_UPDATE_MISSION = "mission"; + public static final String TYPE_UPDATE_NMF = "nmf"; - public static final String FILE_COUNT = "FileCount"; - public static final String FILE_PATH = "FilePath"; - public static final String FILE_CRC = "FileCRC"; + public static final String APP_MAINCLASS = "pack.app.mainclass"; + public static final String APP_MAIN_JAR = "pack.app.mainjar"; + public static final String APP_MAX_HEAP = "pack.app.maxheap"; + public static final String APP_MIN_HEAP = "pack.app.minheap"; + public static final String APP_DEPENDENCIES = "pack.app.dependencies"; - public static final String APP_MAINCLASS = "MainClass"; - public static final String APP_MAIN_JAR = "MainJar"; - public static final String APP_MAX_HEAP = "MaxHeap"; - public static final String APP_MIN_HEAP = "MinHeap"; + public static final String FILE_COUNT = "zipped.file.count"; + public static final String FILE_PATH = "zipped.file.path"; + public static final String FILE_CRC = "zipped.file.crc"; private final Properties properties; + private ArrayList files; + + public Metadata() { + this(new Properties()); + } + + public Metadata(final Properties properties) { + this(properties, null); + } + + public Metadata(Properties properties, ArrayList files) { + this.files = files; + this.properties = this.newOrderedProperties(); + this.properties.put(PACKAGE_METADATA_VERSION, METADATA_VERSION_LATEST); + this.properties.putAll(properties); + + if (files != null) { + this.properties.put(FILE_COUNT, String.valueOf(files.size())); - public NMFPackageMetadata(final Properties properties) { - this.properties = properties; + for (int i = 0; i < files.size(); i++) { + NMFPackageFile file = files.get(i); + this.properties.put(FILE_PATH + "." + i, file.getPath()); + this.properties.put(FILE_CRC + "." + i, String.valueOf(file.getCRC())); + } - // Validation needs to occur for the mandatory field values + } } public String getProperty(String key) { @@ -65,8 +116,9 @@ public void addProperty(String key, String value) { properties.put(key, value); } - public String getMetadataVersion() { - return properties.getProperty(METADATA_VERSION); + public int getMetadataVersion() { + String version = properties.getProperty(PACKAGE_METADATA_VERSION); + return Integer.parseInt(version); } public String getPackageName() { @@ -81,16 +133,104 @@ public String getPackageTimestamp() { return properties.getProperty(PACKAGE_TIMESTAMP); } + public String getPackageType() { + return properties.getProperty(PACKAGE_TYPE); + } + + public String getAppMainclass() { + return properties.getProperty(APP_MAINCLASS); + } + + public String getAppMainJar() { + return properties.getProperty(APP_MAIN_JAR); + } + + public String getAppMaxHeap() { + return properties.getProperty(APP_MAX_HEAP); + } + + public String getAppMinHeap() { + return properties.getProperty(APP_MIN_HEAP); + } + + public String getAppDependencies() { + return properties.getProperty(APP_DEPENDENCIES); + } + + public synchronized ArrayList getFiles() { + if (files != null) { + return files; + } + + files = new ArrayList<>(); + int count = Integer.parseInt(properties.getProperty(FILE_COUNT, "0")); + + for (int i = 0; i < count; i++) { + String path = properties.getProperty(FILE_PATH + "." + i); + long crc = Long.parseLong(properties.getProperty(FILE_CRC + "." + i)); + files.add(new NMFPackageFile(path, crc)); + } + + return files; + } + public void store(OutputStream outStream) throws IOException { - properties.store(outStream, null); + properties.store(outStream, "NMF Package Metadata"); + } + + public void store() throws IOException, FileNotFoundException, IOException { + this.store(new FileOutputStream(Metadata.FILENAME)); + } + + public void store(File file) throws FileNotFoundException, IOException { + String parent = file.getParent(); + + if (parent != null) { + new File(parent).mkdirs(); + } + + try (FileOutputStream sigfos = new FileOutputStream(file)) { + this.store(sigfos); + } + } + + /** + * Parses a ZipFile, finds the receipt file and generates the respective + * Metadata. + * + * @param zipFile The zip file with the receipt file. + * @return The metadata of the NMF Package. + */ + public static Metadata parseZipFile(final ZipFile zipFile) throws IOException { + ZipEntry receipt = zipFile.getEntry(FILENAME); + + if (receipt == null) { + // This code can be removed in the future! It is here at the + // moment in order to support backward compatibility + NMFPackageDescriptor descriptor = NMFPackageDescriptor.parseZipFile(zipFile); + Metadata metadata = descriptor.toMetadata(); + + if (metadata != null) { + return metadata; + } + + throw new IOException("The " + FILENAME + " file does not exist!"); + } + + // Try to open the the receipt file inside the Zip file + // and parse it into a Metadata object + try (InputStream stream = zipFile.getInputStream(receipt)) { + return Metadata.load(stream); + } } - public static NMFPackageMetadata load(InputStream inStream) throws IOException { + public static Metadata load(InputStream inStream) throws IOException { Properties props = new Properties(); props.load(inStream); - return new NMFPackageMetadata(props); + return new Metadata(props); } + @Deprecated public NMFPackageDescriptor toPackageDescriptor() { NMFPackageDetails details = new NMFPackageDetails(properties); NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); @@ -106,4 +246,69 @@ public NMFPackageDescriptor toPackageDescriptor() { return descriptor; } + + @SuppressWarnings("serial") + private Properties newOrderedProperties() { + return new Properties() { + @Override + public synchronized Enumeration keys() { + return Collections.enumeration(new TreeSet<>(super.keySet())); + } + + @Override + public synchronized Set> entrySet() { + return Collections.synchronizedSet( + super.entrySet() + .stream() + .sorted(Comparator.comparing(e -> e.getKey().toString())) + .collect(Collectors.toCollection(LinkedHashSet::new))); + } + }; + } + + public boolean isAppPackage() { + // Before version 4, all NMF Packages were used to carry Apps + // Version 4 is more dynamic and allows NMF Packages to carry other + // types of data, such as: NMF updates, NMF Mission updates, JREs, etc + if (this.getMetadataVersion() < 4) { + return true; + } + + String type = this.getPackageType(); + return TYPE_APP.equals(type); + } + + public boolean sameAs(Metadata installedMetadata) { + // Starts with the timestamp because this is most of the times unique! + if (!this.getPackageTimestamp().equals(installedMetadata.getPackageTimestamp())) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.FINE, "The creation timestamp does not match!"); + return false; + } + + if (!this.getPackageName().equals(installedMetadata.getPackageName())) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.FINE, "The name does not match!"); + return false; + } + + if (!this.getPackageVersion().equals(installedMetadata.getPackageVersion())) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.FINE, "The version does not match!"); + return false; + } + + return true; + } + + public String print() { + StringBuilder str = new StringBuilder(); + + for (Map.Entry entry : properties.entrySet()) { + str.append(" >> ").append(entry.getKey()).append(" = ") + .append(entry.getValue()).append("\n"); + } + + return str.toString(); + } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java index eed5aee2c..9fb7020fa 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/package-info.java @@ -1,4 +1,4 @@ /** - * Package containing the NMF Package classes for the descriptor of the package. + * Package containing the NMF Package classes for the metadata of the package. */ -package esa.mo.nmf.nmfpackage.descriptor; +package esa.mo.nmf.nmfpackage.metadata; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java index 87f689c8d..6ce79be72 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java @@ -30,6 +30,7 @@ * * @author Cesar Coelho */ +@Deprecated public class ReceiptMaster { public static void writeLatestReceipt(NMFPackageDescriptor descriptor, @@ -43,15 +44,21 @@ public static void writeLatestReceipt(NMFPackageDescriptor descriptor, public static NMFPackageDescriptor parseReceipt(final String version, final BufferedReader br) throws IOException { if ("1".equals(version)) { - return ReceiptVersion1.readReceipt(br); + NMFPackageDescriptor descriptor = ReceiptVersion1.readReceipt(br); + descriptor.setMetadataVersion("1"); + return descriptor; } if ("2".equals(version)) { - return ReceiptVersion2.readReceipt(br); + NMFPackageDescriptor descriptor = ReceiptVersion2.readReceipt(br); + descriptor.setMetadataVersion("2"); + return descriptor; } if ("3".equals(version)) { - return ReceiptVersion3.readReceipt(br); + NMFPackageDescriptor descriptor = ReceiptVersion3.readReceipt(br); + descriptor.setMetadataVersion("3"); + return descriptor; } else { throw new IOException("Unknown version: " + version); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java index 9d4790aa9..afc5331f5 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java @@ -31,6 +31,7 @@ * * @author Cesar Coelho */ +@Deprecated public class ReceiptVersion1 { private static final String PACKAGE_NAME = "PackageName="; @@ -69,7 +70,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I throw new IOException("Could not read the package timestamp!"); } - final NMFPackageDetails details = new NMFPackageDetails(name, + final NMFPackageDetails details = new NMFPackageDetails(name, version, timestamp, "", "", "96m"); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); @@ -98,7 +99,8 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I return descriptor; } - public static void writeReceipt(final BufferedWriter bw, final NMFPackageDescriptor descriptor) throws IOException { + public static void writeReceipt(final BufferedWriter bw, + final NMFPackageDescriptor descriptor) throws IOException { bw.write(PACKAGE_NAME + descriptor.getDetails().getPackageName()); bw.newLine(); bw.write(PACKAGE_VERSION + descriptor.getDetails().getVersion()); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java index 9d596ff79..fcc5c206a 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java @@ -31,6 +31,7 @@ * * @author Cesar Coelho */ +@Deprecated public class ReceiptVersion2 { private static final String PACKAGE_NAME = "PackageName="; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 806b3e6ad..24862e7fd 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -31,6 +31,7 @@ * * @author Cesar Coelho */ +@Deprecated public class ReceiptVersion3 { private static final String PACKAGE_NAME = "PackageName="; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index b17eafe3c..b833d7164 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to @@ -21,18 +21,14 @@ package esa.mo.nmf.nmfpackage.tests; import esa.mo.helpertools.helpers.HelperTime; -import esa.mo.nmf.nmfpackage.HelperNMFPackage; import esa.mo.nmf.nmfpackage.NMFPackageCreator; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageMetadata; +import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.ccsds.moims.mo.mal.structures.Time; @@ -92,19 +88,11 @@ public static void createPackage() { try { // Test if the created file can be parsed ZipFile writtenFile = new ZipFile(location); - NMFPackageDescriptor theDescriptor = NMFPackageDescriptor.parseZipFile(writtenFile); - theDescriptor = null; - - ZipEntry entry = writtenFile.getEntry(NMFPackageMetadata.FILENAME); - - // Try to open the the receipt file inside the Zip file - // and parse it into a NMFPackageDescriptor object - try (InputStream stream = writtenFile.getInputStream(entry)) { - NMFPackageMetadata metadata = NMFPackageMetadata.load(stream); - metadata = null; - } - + // Try to open the the metadata file inside the Zip file + // and parse it into a Metadata object + Metadata metadata = Metadata.parseZipFile(writtenFile); + metadata = null; } catch (IOException ex) { Logger.getLogger(SimpleDemoPackageCreation.class.getName()).log( Level.SEVERE, "The file could not be processed!", ex); diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index c56c0d411..5f56c7ccf 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -23,6 +23,7 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.Const; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; +import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -172,7 +173,10 @@ public void execute() throws MojoExecutionException { // Package NMFPackageDetails details = new NMFPackageDetails(name, version, timestamp, mainClass, mainJar, maxHeap); - NMFPackageCreator.nmfPackageCreator(details, inputFiles, locations, "target"); + + Metadata metadata = new Metadata(details.getProperties()); + metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); + NMFPackageCreator.nmfPackageCreator(metadata, inputFiles, locations, "target"); // Now let's take care of the project dependencies // They must also be packaged as NMF Packages that will be shared libraries From 4c4686aa06b197311d2acd48cdae5a006a4f5709 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 18:47:14 +0200 Subject: [PATCH 090/173] [nmf-package] Code cleanup --- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 2 +- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 28 +------ .../{descriptor => }/NMFPackageFile.java | 4 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 76 +++++-------------- .../descriptor/NMFPackageDescriptor.java | 10 ++- .../DetailsApp.java} | 9 +-- .../mo/nmf/nmfpackage/metadata/Metadata.java | 20 +---- .../nmf/nmfpackage/receipt/ReceiptMaster.java | 2 +- .../nmfpackage/receipt/ReceiptVersion1.java | 6 +- .../nmfpackage/receipt/ReceiptVersion2.java | 6 +- .../nmfpackage/receipt/ReceiptVersion3.java | 6 +- .../tests/SimpleDemoPackageCreation.java | 8 +- .../{ => utils}/HelperNMFPackage.java | 2 +- .../{ => utils}/LinuxUsersGroups.java | 2 +- .../{ => utils}/NMFDigitalSignature.java | 2 +- .../nmfpackage/GenerateNMFPackageMojo.java | 7 +- 16 files changed, 56 insertions(+), 134 deletions(-) rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{descriptor => }/NMFPackageFile.java (95%) rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{descriptor/NMFPackageDetails.java => metadata/DetailsApp.java} (92%) rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{ => utils}/HelperNMFPackage.java (99%) rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{ => utils}/LinuxUsersGroups.java (99%) rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{ => utils}/NMFDigitalSignature.java (99%) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 1c56177cf..b8b0deba3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -20,7 +20,7 @@ */ package esa.mo.nmf.nmfpackage; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.IOException; import java.io.InputStream; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index bac534c03..891b4746e 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -20,8 +20,9 @@ */ package esa.mo.nmf.nmfpackage; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.misc.Const; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -76,13 +77,13 @@ public static void zipFiles(String outputPath, ArrayList from, } @Deprecated - public static String nmfPackageCreator(NMFPackageDetails details, + public static String nmfPackageCreator(DetailsApp details, ArrayList filesInput, ArrayList newLocationsInput) { return NMFPackageCreator.nmfPackageCreator(details, filesInput, newLocationsInput, null); } @Deprecated - public static String nmfPackageCreator(NMFPackageDetails details, + public static String nmfPackageCreator(DetailsApp details, ArrayList filesInput, ArrayList newLocationsInput, String destinationFolder) { Metadata metadata = new Metadata(details.getProperties()); @@ -111,27 +112,6 @@ public static String nmfPackageCreator(Metadata metadata, metadata.addProperty(Metadata.FILE_COUNT, String.valueOf(size)); - // ------------------------------------------------------------------- - // Generate nmfPackage.receipt - /* - Logger.getLogger(NMFPackageCreator.class.getName()).log( - Level.INFO, "Generating receipt file..."); - - // Write the receipt file - try (FileOutputStream sigfos = new FileOutputStream(HelperNMFPackage.RECEIPT_FILENAME)) { - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sigfos)); - ReceiptMaster.writeLatestReceipt(descriptor, bw); - } catch (IOException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, null, ex); - } - - // Add the receipt file to the list of Files to be zipped - File receipt = new File(HelperNMFPackage.RECEIPT_FILENAME); - files.add(receipt.getPath()); - newLocations.add(HelperNMFPackage.RECEIPT_FILENAME); - */ - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- // Generate metadata.properties Logger.getLogger(NMFPackageCreator.class.getName()).log( Level.INFO, "Generating metadata file..."); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageFile.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java similarity index 95% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageFile.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java index c555002ca..f5c3f8a11 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageFile.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to @@ -18,7 +18,7 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage.descriptor; +package esa.mo.nmf.nmfpackage; /** * diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 8781a0a67..24591788b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -20,9 +20,10 @@ */ package esa.mo.nmf.nmfpackage; +import esa.mo.nmf.nmfpackage.utils.LinuxUsersGroups; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.misc.OSValidator; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.FileInputStream; @@ -99,10 +100,8 @@ public static void install(final String packageLocation, Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the files to the new locations..."); - installFiles(pack, nmfDir); + extractFiles(pack, nmfDir); String packageName = metadata.getPackageName(); - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Metadata:\n" + metadata.print()); if (metadata.isAppPackage()) { // We can do additional checks... for example: @@ -154,34 +153,13 @@ public static void install(final String packageLocation, } } - // --------------------------------------- // Store a copy of the newReceipt to know that it has been installed! File receiptsFolder = getReceiptsFolder(); String receiptFilename = packageName + RECEIPT_ENDING; String receiptPath = receiptsFolder.getCanonicalPath() + File.separator + receiptFilename; File receiptFile = new File(receiptPath); - metadata.store(receiptFile); - /* - - //create the file otherwise we get FileNotFoundException - new File(receiptFile.getParent()).mkdirs(); - - ZipEntry receipt = zipFile.getEntry(HelperNMFPackage.RECEIPT_FILENAME); - final FileOutputStream fos = new FileOutputStream(receiptFile); - final InputStream zis = zipFile.getInputStream(receipt); - byte[] buffer = new byte[1024]; - int len; - - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - - fos.close(); - zis.close(); - */ - // --------------------------------------- Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully installed from: {0}", packageLocation); @@ -204,9 +182,7 @@ public static void uninstall(final Metadata packageMetadata, removeFiles(packageMetadata); String packageName = packageMetadata.getPackageName(); - boolean isApp = true; - - if (isApp) { + if (packageMetadata.isAppPackage()) { // This directory should be passed in the method signature: File nmfDir = getInstallationFolder(); File installationDir = new File(nmfDir.getAbsolutePath() @@ -265,7 +241,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro File oldReceiptFile = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); // Get the text out of that file and parse it into a NMFPackageDescriptor object - final InputStream stream2 = new FileInputStream(oldReceiptFile); + InputStream stream2 = new FileInputStream(oldReceiptFile); Metadata oldPackMetadata = Metadata.load(stream2); stream2.close(); @@ -277,7 +253,8 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro + " (timestamp: " + newPackMetadata.getPackageTimestamp() + ")" ); - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Removing the previous files..."); + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "Removing the previous files..."); removeFiles(oldPackMetadata); @@ -302,7 +279,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the new files to the locations..."); - installFiles(newPack, nmfDir); + extractFiles(newPack, nmfDir); if (isApp) { String username = null; @@ -318,37 +295,20 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro createAuxiliaryFiles(installationDir, username); if ((new OSValidator()).isUnix()) { + String path = installationDir.getAbsolutePath(); // Change Group owner of the installationDir if (username != null) { - LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); + LinuxUsersGroups.chgrp(true, username, path); } // chmod the installation directory with recursive - LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + LinuxUsersGroups.chmod(false, true, "750", path); } } - // --------------------------------------- // Store a copy of the newReceipt to know that it has been installed! newPackMetadata.store(oldReceiptFile); - /* - //create the file otherwise we get FileNotFoundException - new File(oldReceiptFile.getParent()).mkdirs(); - - final FileOutputStream fos = new FileOutputStream(oldReceiptFile); // Output location - final InputStream zis = zipFile.getInputStream(newReceipt); - byte[] buffer = new byte[1024]; - int len; - - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - - fos.close(); - zis.close(); - */ - // --------------------------------------- Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully upgraded from location: " + packageLocation); @@ -531,7 +491,7 @@ private static String generateFilePathForSystem(final String path) throws IOExce return out.replace('\\', File.separatorChar); } - private static void installFiles(NMFPackage pack, File to) throws IOException { + private static void extractFiles(NMFPackage pack, File to) throws IOException { Metadata metadata = pack.getMetadata(); ZipFile zipFile = pack.getZipFile(); @@ -545,7 +505,7 @@ private static void installFiles(NMFPackage pack, File to) throws IOException { NMFPackageFile file = files.get(i); ZipEntry entry = pack.getZipFileEntry(file.getPath()); - final String path = generateFilePathForSystem(entry.getName()); + String path = generateFilePathForSystem(entry.getName()); newFile = new File(to.getCanonicalPath() + File.separator + path); File parent = new File(newFile.getParent()); @@ -555,10 +515,9 @@ private static void installFiles(NMFPackage pack, File to) throws IOException { System.out.println(" >> Copying file to: " + newFile.getCanonicalPath()); - final FileOutputStream fos = new FileOutputStream(newFile); - + FileOutputStream fos = new FileOutputStream(newFile); + InputStream zis = zipFile.getInputStream(entry); int len; - final InputStream zis = zipFile.getInputStream(entry); while ((len = zis.read(buffer)) > 0) { fos.write(buffer, 0, len); @@ -566,7 +525,7 @@ private static void installFiles(NMFPackage pack, File to) throws IOException { fos.close(); - final long crc = HelperNMFPackage.calculateCRCFromFile(newFile.getCanonicalPath()); + long crc = HelperNMFPackage.calculateCRCFromFile(newFile.getCanonicalPath()); // We will also need to double check the CRCs again against the real files! // Just to double-check.. better safe than sorry! @@ -583,8 +542,7 @@ private static void removeFiles(Metadata metadata) throws IOException { // Do the files actually match the descriptor? for (int i = 0; i < metadata.getFiles().size(); i++) { NMFPackageFile packageFile = metadata.getFiles().get(i); - - final String path = generateFilePathForSystem(packageFile.getPath()); + String path = generateFilePathForSystem(packageFile.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); NMFPackageManager.removeFile(file); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java index bffe7d8ba..f2cc2e4b0 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java @@ -20,8 +20,10 @@ */ package esa.mo.nmf.nmfpackage.descriptor; +import esa.mo.nmf.nmfpackage.NMFPackageFile; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; -import esa.mo.nmf.nmfpackage.HelperNMFPackage; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.nmf.nmfpackage.receipt.ReceiptMaster; import java.io.BufferedReader; import java.io.IOException; @@ -40,16 +42,16 @@ @Deprecated public class NMFPackageDescriptor { - private final NMFPackageDetails details; + private final DetailsApp details; private final ArrayList files; private String descriptorVersion; - public NMFPackageDescriptor(NMFPackageDetails details) { + public NMFPackageDescriptor(DetailsApp details) { this.details = details; this.files = new ArrayList<>(); } - public NMFPackageDetails getDetails() { + public DetailsApp getDetails() { return details; } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java similarity index 92% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java index e91ca6766..d4126ca8f 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDetails.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java @@ -18,16 +18,15 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage.descriptor; +package esa.mo.nmf.nmfpackage.metadata; -import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.util.Properties; /** * * @author Cesar Coelho */ -public class NMFPackageDetails { +public class DetailsApp { private final String packageName; private final String version; @@ -37,7 +36,7 @@ public class NMFPackageDetails { private final String maxHeap; private final Properties properties; - public NMFPackageDetails(final String packageName, final String version, + public DetailsApp(final String packageName, final String version, final String timestamp, final String mainclass, final String mainJar, final String maxHeap) { this.packageName = packageName; @@ -49,7 +48,7 @@ public NMFPackageDetails(final String packageName, final String version, this.properties = null; } - public NMFPackageDetails(final Properties properties) { + public DetailsApp(final Properties properties) { this.packageName = null; this.version = null; this.timestamp = null; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index eacc384e9..cde38bb1d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -22,8 +22,7 @@ import esa.mo.nmf.nmfpackage.NMFPackageManager; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -230,23 +229,6 @@ public static Metadata load(InputStream inStream) throws IOException { return new Metadata(props); } - @Deprecated - public NMFPackageDescriptor toPackageDescriptor() { - NMFPackageDetails details = new NMFPackageDetails(properties); - NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); - int size = Integer.parseInt(properties.getProperty(FILE_COUNT, "0")); - - for (int i = 0; i < size; i++) { - String suffix = "_" + i; - String path = properties.getProperty(FILE_PATH + suffix, ""); - long crc = Long.parseLong(properties.getProperty(FILE_CRC + suffix, "0")); - NMFPackageFile file = new NMFPackageFile(path, crc); - descriptor.addFile(file); - } - - return descriptor; - } - @SuppressWarnings("serial") private Properties newOrderedProperties() { return new Properties() { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java index 6ce79be72..9e2329799 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java @@ -20,7 +20,7 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.HelperNMFPackage; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java index afc5331f5..66039fbfd 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java @@ -21,8 +21,8 @@ package esa.mo.nmf.nmfpackage.receipt; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; +import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -70,7 +70,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I throw new IOException("Could not read the package timestamp!"); } - final NMFPackageDetails details = new NMFPackageDetails(name, + final DetailsApp details = new DetailsApp(name, version, timestamp, "", "", "96m"); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java index fcc5c206a..b8e823633 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java @@ -21,8 +21,8 @@ package esa.mo.nmf.nmfpackage.receipt; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; +import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -80,7 +80,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I throw new IOException("Could not read the package mainclass!"); } - final NMFPackageDetails details = new NMFPackageDetails(name, + final DetailsApp details = new DetailsApp(name, version, timestamp, mainclass, "", "96m"); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 24862e7fd..1fe407d5b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -21,8 +21,8 @@ package esa.mo.nmf.nmfpackage.receipt; import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageFile; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; +import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; @@ -100,7 +100,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I throw new IOException("Could not read the package maxHeap!"); } - final NMFPackageDetails details = new NMFPackageDetails(name, + final DetailsApp details = new DetailsApp(name, version, timestamp, mainclass, mainJar, maxHeap); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); String path; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index b833d7164..bc1276019 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -22,7 +22,7 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.nmfpackage.NMFPackageCreator; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.IOException; @@ -64,7 +64,7 @@ public static void createPackage() { "\n------------- Package 1 Generation -------------\n"); // Package 1 - NMFPackageDetails details = new NMFPackageDetails("TestPackage", "1.0", + DetailsApp details = new DetailsApp("TestPackage", "1.0", timestamp, "noclass", "", "96m"); NMFPackageCreator.nmfPackageCreator(details, files, newLocations); @@ -73,7 +73,7 @@ public static void createPackage() { "\n------------- Package 2 Generation -------------\n"); // Package 2 - NMFPackageDetails details2 = new NMFPackageDetails("TestPackage", "2.0", + DetailsApp details2 = new DetailsApp("TestPackage", "2.0", timestamp, "noclass", "", "96m"); NMFPackageCreator.nmfPackageCreator(details2, files, newLocations); @@ -81,7 +81,7 @@ public static void createPackage() { "\n------------- Package 3 Generation -------------\n"); // Package 3 - NMFPackageDetails details3 = new NMFPackageDetails("TestPackage", "3.0", + DetailsApp details3 = new DetailsApp("TestPackage", "3.0", timestamp, "noclass", "", "96m"); String location = NMFPackageCreator.nmfPackageCreator(details3, files, newLocations); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java similarity index 99% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 8d3c5669b..391f03fce 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -18,7 +18,7 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage; +package esa.mo.nmf.nmfpackage.utils; import esa.mo.helpertools.helpers.HelperMisc; import java.io.BufferedInputStream; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java similarity index 99% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java index 07fa8c37b..f1795c268 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java @@ -18,7 +18,7 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage; +package esa.mo.nmf.nmfpackage.utils; import java.io.BufferedReader; import java.io.IOException; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/NMFDigitalSignature.java similarity index 99% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/NMFDigitalSignature.java index 7febf7bd5..5d5494874 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFDigitalSignature.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/NMFDigitalSignature.java @@ -18,7 +18,7 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage; +package esa.mo.nmf.nmfpackage.utils; import java.io.BufferedInputStream; import java.io.FileInputStream; diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 5f56c7ccf..20d607c58 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -20,9 +20,10 @@ */ package esa.mo.nmf.nmfpackage; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.Const; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDetails; +import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.IOException; @@ -171,7 +172,7 @@ public void execute() throws MojoExecutionException { final String timestamp = HelperTime.time2readableString(time); // Package - NMFPackageDetails details = new NMFPackageDetails(name, version, + DetailsApp details = new DetailsApp(name, version, timestamp, mainClass, mainJar, maxHeap); Metadata metadata = new Metadata(details.getProperties()); @@ -219,7 +220,7 @@ private void packageJarDependency(Artifact artifact) { files.add(file.toPath().toString()); ArrayList newLocations = new ArrayList<>(); - newLocations.add("jar-others" + File.separator + file.getName()); + newLocations.add("jar-shared-dependencies" + File.separator + file.getName()); NMFPackageCreator.zipFiles(destinationPath, files, newLocations); } From ac276a86ea46e0d369da08a57b7d20f22a83223b Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 20:16:11 +0200 Subject: [PATCH 091/173] Log the output of the execution --- .../mo/platform/impl/provider/adapters/AIMovidiusAdapter.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index 990b01627..f4cff40ea 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -30,6 +30,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import esa.mo.platform.impl.provider.gen.AIAdapterInterface; +import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceProviderServiceImpl; /** * The Artificial Intelligence adapter for the Intel Movidius Neural Compute @@ -168,6 +169,9 @@ public void executeInference(String modelPath, String weightsPath, ShellCommander shellCommander = new ShellCommander(); String out = shellCommander.runCommandAndGetOutputMessage(script); + + Logger.getLogger(AIMovidiusAdapter.class.getName()).log(Level.INFO, + "Executed: " + out); } @Override From 226263768b163c0a1754f2e500e1c4553c067a85 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 20:17:02 +0200 Subject: [PATCH 092/173] Adds a Shutdown Hook to stop the running Apps when the supervisor is asked to terminate --- .../sm/impl/provider/AppsLauncherManager.java | 51 +++--- .../AppsLauncherProviderServiceImpl.java | 14 +- .../NanoSatMOSupervisor.java | 162 ++++++++++-------- 3 files changed, 124 insertions(+), 103 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index 90ddf7d8b..fe0323758 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -234,8 +234,7 @@ private LongList addAppToArchive(final AppDetails definition, final ObjectId sou Long related) throws MALException, MALInteractionException { AppDetailsList defs = new AppDetailsList(); defs.add(definition); - final ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(related, - source, uri); + ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(related, source, uri); archDetails.get(0).setInstId(objId); return super.getArchiveService().store( @@ -267,7 +266,7 @@ private void updateAppInArchive(final Long objId, final AppDetails definition, f throws MALException, MALInteractionException { AppDetailsList defs = new AppDetailsList(); defs.add(definition); - final IdentifierList domain = ConfigurationProviderSingleton.getDomain(); + IdentifierList domain = ConfigurationProviderSingleton.getDomain(); ArchiveDetails archiveDetails = HelperArchive.getArchiveDetailsFromArchive(super. getArchiveService(), @@ -319,7 +318,7 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { // Compare with the defs list! // Are there any differences? for (AppDetails singleApp : apps) { - final Long id = super.list(singleApp.getName()); + Long id = super.list(singleApp.getName()); AppDetails previousAppDetails = this.get(id); // It didn't exist... @@ -353,8 +352,9 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { } // Also needs to check if we removed a folder! - final LongList ids = this.listAll(); - final AppDetailsList localApps = this.getAll(); + LongList ids = this.listAll(); + AppDetailsList localApps = this.getAll(); + for (int i = 0; i < ids.size(); i++) { // Roll all the apps inside the apps folder AppDetails localApp = localApps.get(i); boolean appStillIntact = false; @@ -541,13 +541,12 @@ protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interac AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps // Go to the folder where the app is installed - final File appFolder - = new File(appsFolderPath + File.separator + app.getName().getValue()); + File appFolder = new File(appsFolderPath + File.separator + app.getName().getValue()); Map env = assembleAppLauncherEnvironment(""); - final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), + String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), app.getName().getValue(), app.getRunAs(), EnvironmentUtils.toStrings(env)); - final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); + ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); pb.environment().clear(); pb.directory(appFolder); LOGGER.log(Level.INFO, @@ -601,16 +600,17 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.INFO, "Sending event to app: {0} (Name: ''{1}'')", new Object[]{appInstId, appDirectoryServiceName}); - this.setRunning(appInstId, false, interaction.getInteraction()); + MALInteraction malInt = (interaction != null) ? interaction.getInteraction() : null; + this.setRunning(appInstId, false, malInt); ObjectId eventSource = super.getCOMServices().getActivityTrackingService() - .storeCOMOperationActivity(interaction.getInteraction(), null); + .storeCOMOperationActivity(malInt, null); // Generate, store and publish the events to stop the App... - final Long objId = super.getCOMServices().getEventService() + Long objId = super.getCOMServices().getEventService() .generateAndStoreEvent(objType, ConfigurationProviderSingleton.getDomain(), - appDirectoryServiceName, appInstId, eventSource, interaction.getInteraction()); + appDirectoryServiceName, appInstId, eventSource, malInt); - final URI uri = interaction.getInteraction().getMessageHeader().getURIFrom(); + URI uri = (malInt != null) ? malInt.getMessageHeader().getURIFrom() : new URI(""); if (appDirectoryServiceName != null) { try { @@ -670,11 +670,10 @@ protected void stopApps(final LongList appInstIds, final IdentifierList appDirec } if (stopExists) { Map env = assembleAppLauncherEnvironment(""); - final File appFolder - = new File(appsFolderPath + File.separator + curr.getName().getValue()); - final String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), + File appFolder = new File(appsFolderPath + File.separator + curr.getName().getValue()); + String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), curr.getName().getValue(), curr.getRunAs(), EnvironmentUtils.toStrings(env)); - final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); + ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); pb.environment().clear(); pb.directory(appFolder); @@ -739,7 +738,7 @@ public static SingleConnectionDetails getSingleConnectionDetailsFromProviderSumm throw new IOException("We have more than 1 service..."); } - final AddressDetailsList addresses = capabilities.get(0).getServiceAddresses(); + AddressDetailsList addresses = capabilities.get(0).getServiceAddresses(); int bestIndex = HelperCommon.getBestIPCServiceAddressIndex(addresses); SingleConnectionDetails connectionDetails = new SingleConnectionDetails(); @@ -775,19 +774,19 @@ private AppDetails readAppDescriptor(final String appName, final File properties app.setName(new Identifier(appName)); // Use the name of the folder try (FileInputStream inputStream = new FileInputStream(propertiesFile)) { - final Properties props = new Properties(); + Properties props = new Properties(); props.load(inputStream); app.setExtraInfo(HelperMisc.PROVIDER_PROPERTIES_FILE); - final String category = (props.getProperty(HelperMisc.APP_CATEGORY) != null) ? + String category = (props.getProperty(HelperMisc.APP_CATEGORY) != null) ? props.getProperty(HelperMisc.APP_CATEGORY) : "-"; - final String version = (props.getProperty(HelperMisc.APP_VERSION) != null) ? + String version = (props.getProperty(HelperMisc.APP_VERSION) != null) ? props.getProperty(HelperMisc.APP_VERSION) : "-"; - final String copyright = (props.getProperty(HelperMisc.APP_COPYRIGHT) != null) ? + String copyright = (props.getProperty(HelperMisc.APP_COPYRIGHT) != null) ? props.getProperty(HelperMisc.APP_COPYRIGHT) : "-"; - final String description = (props.getProperty(HelperMisc.APP_DESCRIPTION) != null) ? + String description = (props.getProperty(HelperMisc.APP_DESCRIPTION) != null) ? props.getProperty(HelperMisc.APP_DESCRIPTION) : "-"; - final String user = (props.getProperty(HelperMisc.APP_USER) != null) ? + String user = (props.getProperty(HelperMisc.APP_USER) != null) ? props.getProperty(HelperMisc.APP_USER) : null; // Since the user change is only implemented on linux this dependency is fine diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index f343c9454..7fe0d04de 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -431,9 +431,15 @@ public void stopApp(final LongList appInstIds, final StopAppInteraction interact MALHelper.INTERNAL_ERROR_NUMBER, intIndexList)); } - interaction.sendAcknowledgement(); + if(interaction != null) { + interaction.sendAcknowledgement(); + } + manager.stopApps(appInstIds, appDirectoryServiceNames, appConnections, interaction); - interaction.sendResponse(); + + if(interaction != null) { + interaction.sendResponse(); + } } private void prepareStopApp(final LongList appInstIds, final StopAppInteraction interaction, UIntegerList unkIndexList, @@ -467,8 +473,8 @@ private void prepareStopApp(final LongList appInstIds, final StopAppInteraction null, new Identifier("*"), serviceKey, new UIntegerList()); if (app.getCategory().getValue().equalsIgnoreCase("NMF_App")) { // Do a lookup on the Central Drectory service for the app that we want - ProviderSummaryList providersList = this.directoryService.lookupProvider(sf, - interaction.getInteraction()); + MALInteraction malInt = (interaction != null) ? interaction.getInteraction() : null; + ProviderSummaryList providersList = this.directoryService.lookupProvider(sf, malInt); LOGGER.log(Level.FINER, "providersList object: {0}", providersList); try { diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index be9f1bdd6..e67984c84 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -55,6 +55,7 @@ import org.ccsds.moims.mo.mc.parameter.structures.ParameterDefinitionDetails; import org.ccsds.moims.mo.mc.structures.ObjectInstancePairList; import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; /** * The implementation of the NanoSat MO Supervisor that can be extended by particular @@ -63,84 +64,99 @@ * @author Cesar Coelho */ public abstract class NanoSatMOSupervisor extends NMFProvider { - private static final Logger LOGGER = Logger.getLogger(NanoSatMOSupervisor.class.getName()); - private static final String PDU_CHANNEL_PARAMETER = "PDU1952"; - private static final Duration PDU_CHANNEL_REPORTING_PERIOD = new Duration(10); - private final PackageManagementProviderServiceImpl packageManagementService = new PackageManagementProviderServiceImpl(); - private final AppsLauncherProviderServiceImpl appsLauncherService = new AppsLauncherProviderServiceImpl(); - private final CommandExecutorProviderServiceImpl commandExecutorService = new CommandExecutorProviderServiceImpl(); + private static final Logger LOGGER = Logger.getLogger(NanoSatMOSupervisor.class.getName()); + private static final String PDU_CHANNEL_PARAMETER = "PDU1952"; + private static final Duration PDU_CHANNEL_REPORTING_PERIOD = new Duration(10); + private final PackageManagementProviderServiceImpl packageManagementService + = new PackageManagementProviderServiceImpl(); + private final AppsLauncherProviderServiceImpl appsLauncherService + = new AppsLauncherProviderServiceImpl(); + private final CommandExecutorProviderServiceImpl commandExecutorService + = new CommandExecutorProviderServiceImpl(); - /** - * Initializes the NanoSat MO Supervisor. The MonitorAndControlAdapter adapter class can be - * extended for remote monitoring and control with the CCSDS Monitor and Control services. One can - * also extend the SimpleMonitorAndControlAdapter class which contains a simpler interface. - * - * @param mcAdapter The adapter to connect the actions and parameters to the - * corresponding methods and variables of a specific entity. - * @param platformServices The Platform services consumer stubs - * @param packageManagementBackend The Package Management services backend. - */ - public void init(MonitorAndControlNMFAdapter mcAdapter, PlatformServicesConsumer platformServices, - PMBackend packageManagementBackend) { - super.startTime = System.currentTimeMillis(); - HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties - ConnectionProvider.resetURILinks(); - - // Enforce the App Name property to be Const.NANOSAT_MO_SUPERVISOR_NAME - System.setProperty(HelperMisc.PROP_MO_APP_NAME, Const.NANOSAT_MO_SUPERVISOR_NAME); - - // Provider name to be used on the Directory service... - this.providerName = System.getProperty(HelperMisc.PROP_MO_APP_NAME); - - this.platformServices = platformServices; - - try { - Quota stdQuota = new Quota(); - this.comServices.init(); - this.heartbeatService.init(); - this.directoryService.init(comServices); - this.appsLauncherService.init(comServices, directoryService); - this.commandExecutorService.init(comServices); - this.packageManagementService.init(comServices, packageManagementBackend); - this.comServices.initArchiveSync(); - super.reconfigurableServices.add(this.appsLauncherService); - this.appsLauncherService.setStdQuotaPerApp(stdQuota); - this.comServices.getArchiveSyncService().setStdQuota(stdQuota); - this.startMCServices(mcAdapter); - this.initPlatformServices(comServices); - } catch (MALException ex) { - LOGGER.log(Level.SEVERE, "The services could not be initialized. " + - "Perhaps there's something wrong with the Transport Layer.", ex); - return; - } - - // Are the dynamic changes enabled? - if ("true".equals(System.getProperty(Const.DYNAMIC_CHANGES_PROPERTY))) { - LOGGER.log(Level.INFO, "Loading previous configurations..."); - - // Activate the previous configuration - final ObjectId confId = new ObjectId(ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, new ObjectKey( - ConfigurationProviderSingleton.getDomain(), DEFAULT_PROVIDER_CONFIGURATION_OBJID)); + /** + * Initializes the NanoSat MO Supervisor. The MonitorAndControlAdapter adapter class can be + * extended for remote monitoring and control with the CCSDS Monitor and Control services. One can + * also extend the SimpleMonitorAndControlAdapter class which contains a simpler interface. + * + * @param mcAdapter The adapter to connect the actions and parameters to the + * corresponding methods and variables of a specific entity. + * @param platformServices The Platform services consumer stubs + * @param packageManagementBackend The Package Management services backend. + */ + public void init(MonitorAndControlNMFAdapter mcAdapter, + PlatformServicesConsumer platformServices, + PMBackend packageManagementBackend) { + super.startTime = System.currentTimeMillis(); + HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties + ConnectionProvider.resetURILinks(); - super.providerConfiguration = new PersistProviderConfiguration(this, confId, comServices - .getArchiveService()); + // Enforce the App Name property to be Const.NANOSAT_MO_SUPERVISOR_NAME + System.setProperty(HelperMisc.PROP_MO_APP_NAME, Const.NANOSAT_MO_SUPERVISOR_NAME); - try { - super.providerConfiguration.loadPreviousConfigurations(); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - } + // Provider name to be used on the Directory service... + this.providerName = System.getProperty(HelperMisc.PROP_MO_APP_NAME); - if (mcAdapter != null) { - MCRegistration registration = new MCRegistration(comServices, mcServices.getParameterService(), mcServices - .getAggregationService(), mcServices.getAlertService(), mcServices.getActionService()); - mcAdapter.initialRegistrations(registration); - } + this.platformServices = platformServices; - // Populate the Directory service with the entries from the URIs File - LOGGER.log(Level.INFO, "Populating Directory service..."); - this.directoryService.loadURIs(Const.NANOSAT_MO_SUPERVISOR_NAME); + try { + Quota stdQuota = new Quota(); + this.comServices.init(); + this.heartbeatService.init(); + this.directoryService.init(comServices); + this.appsLauncherService.init(comServices, directoryService); + this.commandExecutorService.init(comServices); + this.packageManagementService.init(comServices, packageManagementBackend); + this.comServices.initArchiveSync(); + super.reconfigurableServices.add(this.appsLauncherService); + this.appsLauncherService.setStdQuotaPerApp(stdQuota); + this.comServices.getArchiveSyncService().setStdQuota(stdQuota); + this.startMCServices(mcAdapter); + this.initPlatformServices(comServices); + } catch (MALException ex) { + LOGGER.log(Level.SEVERE, + "The services could not be initialized. " + + "Perhaps there's something wrong with the Transport Layer.", ex); + return; + } + + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + //Your 'pos' shutdown code goes here... + Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( + Level.INFO, "Shutting down Supervisor..."); + + // Retrieve all apps and then filter for the ones that are running... + try { + IdentifierList allApps = new IdentifierList(); + allApps.add(new Identifier("*")); + ListAppResponse response = appsLauncherService.listApp(allApps, new Identifier("*"), null); + LongList runningApps = new LongList(); + + for(int i = 0; i < response.getBodyElement0().size(); i++) { + Long appId = response.getBodyElement0().get(i); + if(response.getBodyElement1().get(i)){ + runningApps.add(appId); + } + } + + Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( + Level.SEVERE, "Stopping " + runningApps.size() + " App(s)!"); + + appsLauncherService.stopApp(runningApps, null); + } catch (MALInteractionException ex) { + Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( + Level.SEVERE, "(1) Something went wrong...", ex); + } catch (MALException ex) { + Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( + Level.SEVERE, "(2) Something went wrong...", ex); + } + + Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( + Level.INFO, "Done!"); + } + }); final String primaryURI = this.directoryService.getConnection().getPrimaryConnectionDetails().getProviderURI() .toString(); From 395a3a2310bccf4cb21030a6a6bc0f3aac869ab8 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 21:41:31 +0200 Subject: [PATCH 093/173] [nmf-package] Adds support to carry Ddependencies via NMF Packages --- .../metadata/DetailsDependency.java | 75 +++++++++++++++++++ .../nmfpackage/GenerateNMFPackageMojo.java | 20 ++--- 2 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java new file mode 100644 index 000000000..2b89e38b1 --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java @@ -0,0 +1,75 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage.metadata; + +import java.util.Properties; + +/** + * + * @author Cesar Coelho + */ +public class DetailsDependency { + + private final String packageName; + private final String version; + private final String timestamp; + private final Properties properties; + + public DetailsDependency(final String packageName, final String version, + final String timestamp) { + this.packageName = packageName; + this.version = version; + this.timestamp = timestamp; + this.properties = null; + } + + public DetailsDependency(final Properties properties) { + this.packageName = null; + this.version = null; + this.timestamp = null; + this.properties = properties; + } + + public Properties getProperties() { + if (properties != null) { + return properties; + } else { + Properties props = new Properties(); + props.put(Metadata.PACKAGE_NAME, packageName); + props.put(Metadata.PACKAGE_VERSION, version); + props.put(Metadata.PACKAGE_TIMESTAMP, timestamp); + return props; + } + } + + public String getPackageName() { + return (properties == null) ? packageName : properties.getProperty(Metadata.PACKAGE_NAME); + } + + public String getVersion() { + return (properties == null) ? version : properties.getProperty(Metadata.PACKAGE_VERSION); + } + + public String getTimestamp() { + return (properties == null) ? timestamp : properties.getProperty(Metadata.PACKAGE_TIMESTAMP); + } + +} diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 20d607c58..ad2231785 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -22,8 +22,8 @@ import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.helpers.HelperTime; -import esa.mo.helpertools.misc.Const; import esa.mo.nmf.nmfpackage.metadata.DetailsApp; +import esa.mo.nmf.nmfpackage.metadata.DetailsDependency; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.IOException; @@ -161,7 +161,7 @@ public void execute() throws MojoExecutionException { + "-> \t\t\tesa.mo.nmf.apps.myapp.ExampleApp\n" + "-> \t\t\n\n\n"); } - + if ("${esa.nmf.version-qualifier}".equals(nmfVersion)) { throw new MojoExecutionException("The nmfVersion property needs to " + "be defined!\nPlease use the tag inside the " @@ -174,7 +174,7 @@ public void execute() throws MojoExecutionException { // Package DetailsApp details = new DetailsApp(name, version, timestamp, mainClass, mainJar, maxHeap); - + Metadata metadata = new Metadata(details.getProperties()); metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); NMFPackageCreator.nmfPackageCreator(metadata, inputFiles, locations, "target"); @@ -212,17 +212,19 @@ public void execute() throws MojoExecutionException { private void packageJarDependency(Artifact artifact) { File file = artifact.getFile(); - String destinationPath = TARGET_FOLDER + File.separator - + artifact.getArtifactId() + "-" - + artifact.getVersion() + "." + Const.NMF_PACKAGE_SUFFIX; - ArrayList files = new ArrayList<>(); files.add(file.toPath().toString()); + Time time = new Time(System.currentTimeMillis()); + String timestamp = HelperTime.time2readableString(time); + DetailsDependency details = new DetailsDependency( + artifact.getArtifactId(), artifact.getVersion(), timestamp); + + Metadata metadata = new Metadata(details.getProperties()); + metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); ArrayList newLocations = new ArrayList<>(); newLocations.add("jar-shared-dependencies" + File.separator + file.getName()); - - NMFPackageCreator.zipFiles(destinationPath, files, newLocations); + NMFPackageCreator.nmfPackageCreator(metadata, files, newLocations, "target"); } private void addFileOrDirectory(String path, String nest) { From 77ff3c84d70480bd4d826465c43613a5de61d98f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 22:11:01 +0200 Subject: [PATCH 094/173] [nmf-package] Declares the dependencies on the metadata of the NMF Packages --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 2 +- .../nmf/nmfpackage/metadata/DetailsApp.java | 25 ++++++++++++-- .../nmfpackage/receipt/ReceiptVersion1.java | 2 +- .../nmfpackage/receipt/ReceiptVersion2.java | 2 +- .../nmfpackage/receipt/ReceiptVersion3.java | 2 +- .../tests/SimpleDemoPackageCreation.java | 6 ++-- .../nmfpackage/GenerateNMFPackageMojo.java | 33 +++++++++++-------- 7 files changed, 49 insertions(+), 23 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 891b4746e..095604886 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -45,7 +45,7 @@ public class NMFPackageCreator { private static final int BUFFER = 2048; - public static void zipFiles(String outputPath, ArrayList from, + private static void zipFiles(String outputPath, ArrayList from, ArrayList newLocations) { try { BufferedInputStream origin; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java index d4126ca8f..0aa61dee9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java @@ -20,6 +20,7 @@ */ package esa.mo.nmf.nmfpackage.metadata; +import java.util.ArrayList; import java.util.Properties; /** @@ -34,17 +35,19 @@ public class DetailsApp { private final String mainclass; private final String mainJar; private final String maxHeap; + private final ArrayList dependencies; private final Properties properties; public DetailsApp(final String packageName, final String version, - final String timestamp, final String mainclass, - final String mainJar, final String maxHeap) { + final String timestamp, final String mainclass, final String mainJar, + final String maxHeap, final ArrayList dependencies) { this.packageName = packageName; this.version = version; this.timestamp = timestamp; this.mainclass = mainclass; this.mainJar = mainJar; this.maxHeap = maxHeap; + this.dependencies = dependencies; this.properties = null; } @@ -55,6 +58,7 @@ public DetailsApp(final Properties properties) { this.mainclass = null; this.mainJar = null; this.maxHeap = null; + this.dependencies = null; this.properties = properties; } @@ -69,10 +73,27 @@ public Properties getProperties() { props.put(Metadata.APP_MAINCLASS, mainclass); props.put(Metadata.APP_MAIN_JAR, mainJar); props.put(Metadata.APP_MAX_HEAP, maxHeap); + + if (dependencies != null) { + props.put(Metadata.APP_DEPENDENCIES, generateDependencies()); + } + return props; } } + private String generateDependencies() { + StringBuilder str = new StringBuilder(); + + if (dependencies != null) { + for (String dependency : dependencies) { + str.append(dependency).append(";"); + } + } + + return str.toString(); + } + public String getPackageName() { return (properties == null) ? packageName : properties.getProperty(Metadata.PACKAGE_NAME); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java index 66039fbfd..7b2521237 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java @@ -71,7 +71,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I } final DetailsApp details = new DetailsApp(name, - version, timestamp, "", "", "96m"); + version, timestamp, "", "", "96m", null); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); String path; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java index b8e823633..af6a3a584 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java @@ -81,7 +81,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I } final DetailsApp details = new DetailsApp(name, - version, timestamp, mainclass, "", "96m"); + version, timestamp, mainclass, "", "96m", null); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); String path; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 1fe407d5b..02f93edf8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -101,7 +101,7 @@ public static NMFPackageDescriptor readReceipt(final BufferedReader br) throws I } final DetailsApp details = new DetailsApp(name, - version, timestamp, mainclass, mainJar, maxHeap); + version, timestamp, mainclass, mainJar, maxHeap, null); final NMFPackageDescriptor descriptor = new NMFPackageDescriptor(details); String path; long crc; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index bc1276019..368a45940 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -65,7 +65,7 @@ public static void createPackage() { // Package 1 DetailsApp details = new DetailsApp("TestPackage", "1.0", - timestamp, "noclass", "", "96m"); + timestamp, "noclass", "", "96m", null); NMFPackageCreator.nmfPackageCreator(details, files, newLocations); @@ -74,7 +74,7 @@ public static void createPackage() { // Package 2 DetailsApp details2 = new DetailsApp("TestPackage", "2.0", - timestamp, "noclass", "", "96m"); + timestamp, "noclass", "", "96m", null); NMFPackageCreator.nmfPackageCreator(details2, files, newLocations); Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, @@ -82,7 +82,7 @@ public static void createPackage() { // Package 3 DetailsApp details3 = new DetailsApp("TestPackage", "3.0", - timestamp, "noclass", "", "96m"); + timestamp, "noclass", "", "96m", null); String location = NMFPackageCreator.nmfPackageCreator(details3, files, newLocations); try { diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index ad2231785..16c701ee2 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -168,20 +168,10 @@ public void execute() throws MojoExecutionException { + " tag!\n"); } - final Time time = new Time(System.currentTimeMillis()); - final String timestamp = HelperTime.time2readableString(time); - - // Package - DetailsApp details = new DetailsApp(name, version, - timestamp, mainClass, mainJar, maxHeap); - - Metadata metadata = new Metadata(details.getProperties()); - metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); - NMFPackageCreator.nmfPackageCreator(metadata, inputFiles, locations, "target"); - // Now let's take care of the project dependencies // They must also be packaged as NMF Packages that will be shared libraries getLog().info("------\nGenerating shared libraries...\n"); + ArrayList dependencies = new ArrayList<>(); for (Object unresolvedArtifact : this.project.getArtifacts()) { Artifact artifact = (Artifact) unresolvedArtifact; @@ -205,12 +195,26 @@ public void execute() throws MojoExecutionException { getLog().info(" >> GroupId = " + artifact.getGroupId()); getLog().info(" >> ArtifactId = " + artifact.getArtifactId()); getLog().info(" >> Version = " + artifact.getVersion()); - packageJarDependency(artifact); + dependencies.add(packageJarDependency(artifact)); } } + + getLog().info("------\nGenerating project NMF Package...\n"); + final Time time = new Time(System.currentTimeMillis()); + final String timestamp = HelperTime.time2readableString(time); + + // Package + DetailsApp details = new DetailsApp(name, version, + timestamp, mainClass, mainJar, maxHeap, dependencies); + + Metadata metadata = new Metadata(details.getProperties()); + metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); + NMFPackageCreator.nmfPackageCreator(metadata, inputFiles, locations, "target"); + + } - private void packageJarDependency(Artifact artifact) { + private String packageJarDependency(Artifact artifact) { File file = artifact.getFile(); ArrayList files = new ArrayList<>(); files.add(file.toPath().toString()); @@ -223,8 +227,9 @@ private void packageJarDependency(Artifact artifact) { Metadata metadata = new Metadata(details.getProperties()); metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); ArrayList newLocations = new ArrayList<>(); - newLocations.add("jar-shared-dependencies" + File.separator + file.getName()); + newLocations.add("jars-shared-dependencies" + File.separator + file.getName()); NMFPackageCreator.nmfPackageCreator(metadata, files, newLocations, "target"); + return file.getName(); } private void addFileOrDirectory(String path, String nest) { From 0a0cef86207b58c82c062492d5c6226e5975248e Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 23 Oct 2022 23:15:28 +0200 Subject: [PATCH 095/173] [nmf-package] The dependencies are now also installed & code cleanup --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 7 ++--- .../mo/nmf/nmfpackage/NMFPackageManager.java | 31 +++++++++++++++---- .../nmfpackage/descriptor/package-info.java | 4 --- .../mo/nmf/nmfpackage/metadata/Metadata.java | 2 +- .../NMFPackageDescriptor.java | 3 +- .../nmf/nmfpackage/receipt/ReceiptMaster.java | 1 - .../nmfpackage/receipt/ReceiptVersion1.java | 1 - .../nmfpackage/receipt/ReceiptVersion2.java | 1 - .../nmfpackage/receipt/ReceiptVersion3.java | 1 - .../nmf/nmfpackage/receipt/package-info.java | 4 +++ .../nmfpackage/GenerateNMFPackageMojo.java | 6 ++-- 11 files changed, 36 insertions(+), 25 deletions(-) delete mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/package-info.java rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{descriptor => receipt}/NMFPackageDescriptor.java (98%) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/package-info.java diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 095604886..4d33dfc14 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -87,12 +87,11 @@ public static String nmfPackageCreator(DetailsApp details, ArrayList filesInput, ArrayList newLocationsInput, String destinationFolder) { Metadata metadata = new Metadata(details.getProperties()); - return NMFPackageCreator.nmfPackageCreator(metadata, filesInput, newLocationsInput, destinationFolder); + return NMFPackageCreator.create(metadata, filesInput, newLocationsInput, destinationFolder); } - public static String nmfPackageCreator(Metadata metadata, - ArrayList filesInput, ArrayList newLocationsInput, - String destinationFolder) { + public static String create(Metadata metadata, ArrayList filesInput, + ArrayList newLocationsInput, String destinationFolder) { final ArrayList files = new ArrayList<>(filesInput); final ArrayList newLocations = new ArrayList<>(newLocationsInput); int size = newLocations.size(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 24591788b..416a333c1 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -83,10 +83,10 @@ public static void install(final String packageLocation, // Get the File to be installed NMFPackage pack = new NMFPackage(packageLocation); Metadata metadata = pack.getMetadata(); - int metadataVersion = metadata.getMetadataVersion(); - if (metadataVersion < 3) { - throw new IOException("The package version is deprecated! Version: " + metadataVersion); + if (metadata.getMetadataVersion() < 3) { + throw new IOException("The package version is deprecated! " + + "Version: " + metadata.getMetadataVersion()); } // Verify integrity of the file: Are all the declared files matching their CRCs? @@ -100,6 +100,7 @@ public static void install(final String packageLocation, Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the files to the new locations..."); + installDependencies(metadata, packageLocation, nmfDir); extractFiles(pack, nmfDir); String packageName = metadata.getPackageName(); @@ -230,10 +231,10 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro // Get the Package to be uninstalled NMFPackage newPack = new NMFPackage(packageLocation); Metadata newPackMetadata = newPack.getMetadata(); - int metadataVersion = newPackMetadata.getMetadataVersion(); - if(metadataVersion < 3) { - throw new IOException("The package version is deprecated! Version: " + metadataVersion); + if (newPackMetadata.getMetadataVersion() < 3) { + throw new IOException("The package version is deprecated! " + + "Version: " + newPackMetadata.getMetadataVersion()); } File receiptsFolder = getReceiptsFolder(); @@ -279,6 +280,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the new files to the locations..."); + installDependencies(newPackMetadata, packageLocation, nmfDir); extractFiles(newPack, nmfDir); if (isApp) { @@ -491,6 +493,23 @@ private static String generateFilePathForSystem(final String path) throws IOExce return out.replace('\\', File.separatorChar); } + private static void installDependencies(Metadata metadata, String packageLocation, + File installationDir) throws IOException { + String dependencies = metadata.getAppDependencies(); + String parent = (new File(packageLocation)).getParent(); + + if (dependencies != null && !dependencies.isEmpty()) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "Dependencies are: " + dependencies); + + for (String file : dependencies.split(";")) { + file = file.replace(".jar", ".nmfpack"); + String path = parent + File.separator + file; + extractFiles(new NMFPackage(path), installationDir); + } + } + } + private static void extractFiles(NMFPackage pack, File to) throws IOException { Metadata metadata = pack.getMetadata(); ZipFile zipFile = pack.getZipFile(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/package-info.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/package-info.java deleted file mode 100644 index eed5aee2c..000000000 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Package containing the NMF Package classes for the descriptor of the package. - */ -package esa.mo.nmf.nmfpackage.descriptor; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index cde38bb1d..2d6dc707d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -21,7 +21,7 @@ package esa.mo.nmf.nmfpackage.metadata; import esa.mo.nmf.nmfpackage.NMFPackageManager; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; +import esa.mo.nmf.nmfpackage.receipt.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.File; import java.io.FileNotFoundException; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java similarity index 98% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java index f2cc2e4b0..f3c5a25ca 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/descriptor/NMFPackageDescriptor.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java @@ -18,13 +18,12 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage.descriptor; +package esa.mo.nmf.nmfpackage.receipt; import esa.mo.nmf.nmfpackage.NMFPackageFile; import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; -import esa.mo.nmf.nmfpackage.receipt.ReceiptMaster; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java index 9e2329799..a6482b3b8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptMaster.java @@ -21,7 +21,6 @@ package esa.mo.nmf.nmfpackage.receipt; import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java index 7b2521237..f0584ea50 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java index af6a3a584..041577a38 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 02f93edf8..8a6974bc6 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.descriptor.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/package-info.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/package-info.java new file mode 100644 index 000000000..9de4b84e4 --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/package-info.java @@ -0,0 +1,4 @@ +/** + * Package containing the NMF Package receipts. This package is deprecated. + */ +package esa.mo.nmf.nmfpackage.receipt; diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 16c701ee2..3000cd0aa 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -209,9 +209,7 @@ public void execute() throws MojoExecutionException { Metadata metadata = new Metadata(details.getProperties()); metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); - NMFPackageCreator.nmfPackageCreator(metadata, inputFiles, locations, "target"); - - + NMFPackageCreator.create(metadata, inputFiles, locations, TARGET_FOLDER); } private String packageJarDependency(Artifact artifact) { @@ -228,7 +226,7 @@ private String packageJarDependency(Artifact artifact) { metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); ArrayList newLocations = new ArrayList<>(); newLocations.add("jars-shared-dependencies" + File.separator + file.getName()); - NMFPackageCreator.nmfPackageCreator(metadata, files, newLocations, "target"); + NMFPackageCreator.create(metadata, files, newLocations, TARGET_FOLDER); return file.getName(); } From 42cb92c01647955076f43229c25806525cd26291 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 24 Oct 2022 19:44:16 +0200 Subject: [PATCH 096/173] [ai-service] Adds an AI generic adapter for the Intel Movidius chip using a python script in the backend --- .../provider/adapters/AIMovidiusAdapter.java | 97 ++++++++++--- .../src/main/resources/aiInference.py | 131 ++++++++++++++++++ 2 files changed, 207 insertions(+), 21 deletions(-) create mode 100644 core/mo-services-impl/nmf-platform-generic-impl/src/main/resources/aiInference.py diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index f4cff40ea..c7a53e1d2 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -30,21 +30,23 @@ import java.util.logging.Level; import java.util.logging.Logger; import esa.mo.platform.impl.provider.gen.AIAdapterInterface; -import esa.mo.platform.impl.provider.gen.ArtificialIntelligenceProviderServiceImpl; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.concurrent.TimeUnit; /** * The Artificial Intelligence adapter for the Intel Movidius Neural Compute - * Stick via a python script. Note that this code was not developed for the - * Intel Movidius Neural Compute Stick 2 and therefore this version will not - * work. + * Stick via a python file. Note that this code was not developed for the Intel + * Movidius Neural Compute Stick 2 and therefore will only work with the first + * Intel Movidius Neural Compute Stick. * * @author Cesar Coelho */ public class AIMovidiusAdapter implements AIAdapterInterface { private static final Logger LOGGER = Logger.getLogger(AIMovidiusAdapter.class.getName()); - private static final String PYTHON_FILENAME = "aiInference.py"; - private OSValidator os = new OSValidator(); + private static final String PYTHON_FILENAME = "drivers" + File.separator + "aiInference.py"; + private final OSValidator os = new OSValidator(); private final File setupVarsPath; public AIMovidiusAdapter() throws IOException { @@ -133,20 +135,26 @@ private File findPathToFile(File path, String toBeMatched) { return null; } - private String generateScriptSH(String pathIntelVar, String pythonFile) { + private String generateScriptSH(String pathIntelVar, String pythonCommand) { StringBuilder str = new StringBuilder(); - str.append("#!/bin/bash \n\n"); str.append("source ").append(pathIntelVar); - str.append("\n\n"); - str.append("python3 ").append(pythonFile); + str.append(" ; ").append(pythonCommand); return str.toString(); } private String generateScriptBAT(String pathIntelVar, String pythonFile) { StringBuilder str = new StringBuilder(); - str.append(pathIntelVar); - str.append("\n\n"); - str.append(pythonFile); + str.append(pathIntelVar).append(" & ").append(pythonFile); + return str.toString(); + } + + private String buildPythonCommand(String modelXml, String modelBin, String inputTiles, String outputTiles) { + StringBuilder str = new StringBuilder(); + str.append("python3 ").append(PYTHON_FILENAME); + str.append(" --model_xml ").append(modelXml); + str.append(" --model_bin ").append(modelBin); + str.append(" --input_tiles ").append(inputTiles); + str.append(" --output_tiles ").append(outputTiles); return str.toString(); } @@ -154,24 +162,71 @@ private String generateScriptBAT(String pathIntelVar, String pythonFile) { public void executeInference(String modelPath, String weightsPath, String inputPath, String outputPath) throws IOException { String pathIntelVar = setupVarsPath.getAbsolutePath(); - String script = null; + String pythonCmd = buildPythonCommand(modelPath, weightsPath, inputPath, outputPath); + String cmd = null; if (os.isUnix()) { - script = this.generateScriptSH(pathIntelVar, PYTHON_FILENAME); + cmd = this.generateScriptSH(pathIntelVar, pythonCmd); } if (os.isWindows()) { - script = this.generateScriptBAT(pathIntelVar, PYTHON_FILENAME); + cmd = this.generateScriptBAT(pathIntelVar, pythonCmd); } - if (script == null) { + if (cmd == null) { throw new IOException("Unsupported OS!"); } - + + long timestampCommand = System.currentTimeMillis(); + Logger.getLogger(AIMovidiusAdapter.class.getName()).log( + Level.INFO, "Running command:\n >> " + cmd); + ShellCommander shellCommander = new ShellCommander(); - String out = shellCommander.runCommandAndGetOutputMessage(script); + Process p = shellCommander.runCommand(cmd); + + long timeout = 2; // in minutes + Logger.getLogger(AIMovidiusAdapter.class.getName()).log( + Level.INFO, + "The process is running and it is expected to take some minutes!" + + "\nThe process will timeout after " + timeout + " minutes in " + + "case it is still not finished. Please wait..."); + + try { + boolean terminated = p.waitFor(timeout, TimeUnit.MINUTES); + + if (!terminated) { + Logger.getLogger(AIMovidiusAdapter.class.getName()).log(Level.SEVERE, + "Timeout reached: The process is stuck..." + + "The adapter will kill the process!"); - Logger.getLogger(AIMovidiusAdapter.class.getName()).log(Level.INFO, - "Executed: " + out); + p.destroyForcibly(); + } + } catch (InterruptedException ex) { + Logger.getLogger(AIMovidiusAdapter.class.getName()).log(Level.SEVERE, + "The thread was interrupted while waiting....", ex); + } + + // Get the textual message from the process + BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); + StringBuilder buffer = new StringBuilder(); + String line; + while ((line = br.readLine()) != null) { + buffer.append(line); + buffer.append("\n"); + } + + String message = buffer.toString(); + int exitValue = p.exitValue(); + timestampCommand = System.currentTimeMillis() - timestampCommand; + + Logger.getLogger(AIMovidiusAdapter.class.getName()).log(Level.INFO, + "The execution of the command took " + timestampCommand + " miliseconds!\n" + + "The exit value is: " + exitValue + "\nThe output is:\n" + message); + + if (exitValue != 0) { + Logger.getLogger(AIMovidiusAdapter.class.getName()).log( + Level.SEVERE, "The execution failed!"); + throw new IOException("The execution failed!"); + } } @Override diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/resources/aiInference.py b/core/mo-services-impl/nmf-platform-generic-impl/src/main/resources/aiInference.py new file mode 100644 index 000000000..24e216627 --- /dev/null +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/resources/aiInference.py @@ -0,0 +1,131 @@ +import cv2 +import time +from openvino.inference_engine import IECore +from datetime import datetime +import os +import argparse + +parser = argparse.ArgumentParser(description='Runs AI inference on a Myriad device for a set of tiles') +parser.add_argument('-x','--model_xml', help='The model xml file path', required=True) +parser.add_argument('-b','--model_bin', help='The model bin file path', required=True) +parser.add_argument('-i','--input_tiles', help='The input tiles directory', required=True) +parser.add_argument('-o','--output_tiles', help='The ouput tiles directory', required=True) +args = vars(parser.parse_args()) + +# Model IR files +model_xml = args['model_xml'] +model_bin = args['model_bin'] + +# Input image tiles path +input_tiles_path = args['input_tiles'] + +# Output image tiles path +output_folder = args['output_tiles'] +os.makedirs(output_folder, exist_ok=True) + +# Device to use +device = "MYRIAD" + +print( + "\nConfiguration parameters settings:" + f"\n\t>> model_xml = {model_xml}", + f"\n\t>> model_bin = {model_bin}", + f"\n\t>> input_tiles_path = {input_tiles_path}", + f"\n\t>> device = {device}", +) + +# Create an Inference Engine instance +print("\nCreating Inference Engine...") +ie = IECore() + +# List the available devices +devices = ie.available_devices +print("Available devices: ", devices) + +if len(devices) == 0: + print("There are no available devices! Make sure the MYRIAD device is plugged correctly!") + exit(1) + +# Read the network from IR files +print("\nReading the network...") +net_read_time = time.time() +net = ie.read_network(model=model_xml, weights=model_bin) +net_read_time = time.time() - net_read_time +print(f" >> The network was read in: {net_read_time * 1000:.1f} ms") + +print("Loading the network to the device...") +net_load_time = time.time() +exec_net = ie.load_network(network=net, num_requests=2, device_name=device) +net_load_time = time.time() - net_load_time +print(f" >> The network was loaded to the device in: {net_load_time * 1000:.1f} ms") + +# Store names of input and output blobs +input_blob = next(iter(net.inputs)) +output_blob = next(iter(net.outputs)) + +# Read the input dimensions: n=batch size, c=number of channels, h=height, w=width +n, c, h, w = net.inputs[input_blob].shape + +print(f"Loaded the model into the Inference Engine for the {device} device.", + f"\nModel input dimensions: n={n}, c={c}, h={h}, w={w}") + +# Define the function to load the input image +def load_input_image(input_path): + print("Loading input image...") + # Globals to store input width and height + global input_w, input_h + + # Use OpenCV to load the input image + img = cv2.imread(input_path) + + input_h, input_w, *_ = img.shape + print(" >> Loaded the input image: %s \n >> Input image resolution: %s x %s" % (input_path,input_w,input_h)) + return img + +# Define the function to resize the input image +def resize_input_image(image): + print("Resizing input image...") + # Resize the image dimensions from image to model input w x h + in_frame = cv2.resize(image, (w, h)) + # Change data layout from HWC to CHW + in_frame = in_frame.transpose((2, 0, 1)) + # Reshape to input dimensions + in_frame = in_frame.reshape((n, c, h, w)) + #print(f"Resized the input image to {w}x{h}.") + print(" >> Resized the input image to: %s x %s." % (w,h)) + return in_frame + + +from pathlib import Path +from PIL import Image + +pathlist = Path(input_tiles_path).glob('*') +for path in pathlist: + print("-------------") + # Convert path from object to string & Load the image + path_in_str = str(path) + image = load_input_image(path_in_str) + + # Resize the input image + in_frame = resize_input_image(image) + + # Run the inference + print("Running inference...") + inf_start = time.time() + res = exec_net.infer(inputs={input_blob: in_frame}) + inf_time = time.time() - inf_start + print(f" >> Inference is complete. Run time: {inf_time * 1000:.1f} ms") + #print(' >> Model output_blob has the following shape: %s' % ({res[output_blob].shape})) + + image_outputed = list(res.values())[0] + last = cv2.resize(image, (image_outputed.shape[2], image_outputed.shape[3])) + #print(image_outputed.shape) + #print(last.shape) + + print("Storing image...") + img = Image.fromarray(last, 'RGB') + filename = os.path.basename(path_in_str) + img.save(output_folder + '/' + filename) + print(" >> Stored!") + +print("\nThe python script has finished all tasks... Closing now!") From 6c16b60cb1a2bbd5a9ab58337ad04fee326a07f3 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 24 Oct 2022 23:42:02 +0200 Subject: [PATCH 097/173] Better level of abstraction between the different metadata types --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 2 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 74 +++++------------ .../nmf/nmfpackage/NMFPackagePMBackend.java | 2 +- .../metadata/DetailsDependency.java | 75 ----------------- .../mo/nmf/nmfpackage/metadata/Metadata.java | 45 ++++------ .../nmf/nmfpackage/metadata/MetadataApp.java | 82 +++++++++++++++++++ .../metadata/MetadataDependency.java | 40 +++++++++ .../{metadata => receipt}/DetailsApp.java | 21 +++-- .../receipt/NMFPackageDescriptor.java | 5 +- .../nmfpackage/receipt/ReceiptVersion1.java | 1 - .../nmfpackage/receipt/ReceiptVersion2.java | 1 - .../nmfpackage/receipt/ReceiptVersion3.java | 1 - .../tests/SimpleDemoPackageCreation.java | 2 +- .../nmfpackage/utils/HelperNMFPackage.java | 71 +++++++++++++++- .../nmfpackage/GenerateNMFPackageMojo.java | 14 +--- 15 files changed, 249 insertions(+), 187 deletions(-) delete mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java rename core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/{metadata => receipt}/DetailsApp.java (88%) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 4d33dfc14..ca63aba26 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -22,7 +22,7 @@ import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.misc.Const; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; +import esa.mo.nmf.nmfpackage.receipt.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 416a333c1..5b53a4592 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -23,13 +23,14 @@ import esa.mo.nmf.nmfpackage.utils.LinuxUsersGroups; import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.helpers.HelperMisc; +import esa.mo.helpertools.misc.Const; import esa.mo.helpertools.misc.OSValidator; import esa.mo.nmf.nmfpackage.metadata.Metadata; +import esa.mo.nmf.nmfpackage.metadata.MetadataApp; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -100,11 +101,14 @@ public static void install(final String packageLocation, Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the files to the new locations..."); - installDependencies(metadata, packageLocation, nmfDir); + if(metadata.isApp()){ + installDependencies(metadata.castToApp(), packageLocation, nmfDir); + } + extractFiles(pack, nmfDir); String packageName = metadata.getPackageName(); - if (metadata.isAppPackage()) { + if (metadata.isApp()) { // We can do additional checks... for example: // 1. Are we trying to install more than one App? // 2. Does the app name on the package matches the folder name? @@ -138,7 +142,7 @@ public static void install(final String packageLocation, username = null; } - generateStartSHScript(metadata, installationDir, nmfDir); + HelperNMFPackage.generateStartScript(metadata.castToApp(), installationDir, nmfDir); } createAuxiliaryFiles(installationDir, username); @@ -183,7 +187,7 @@ public static void uninstall(final Metadata packageMetadata, removeFiles(packageMetadata); String packageName = packageMetadata.getPackageName(); - if (packageMetadata.isAppPackage()) { + if (packageMetadata.isApp()) { // This directory should be passed in the method signature: File nmfDir = getInstallationFolder(); File installationDir = new File(nmfDir.getAbsolutePath() @@ -260,7 +264,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro removeFiles(oldPackMetadata); String packageName = oldPackMetadata.getPackageName(); - boolean isApp = oldPackMetadata.isAppPackage(); + boolean isApp = oldPackMetadata.isApp(); if (isApp) { // This directory should be passed in the method signature: @@ -280,7 +284,8 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the new files to the locations..."); - installDependencies(newPackMetadata, packageLocation, nmfDir); + MetadataApp appMetadata = newPackMetadata.castToApp(); + installDependencies(appMetadata, packageLocation, nmfDir); extractFiles(newPack, nmfDir); if (isApp) { @@ -291,7 +296,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro if ((new OSValidator()).isUnix()) { username = generateUsername(packageName); - generateStartSHScript(newPackMetadata, installationDir, nmfDir); + HelperNMFPackage.generateStartScript(appMetadata, installationDir, nmfDir); } createAuxiliaryFiles(installationDir, username); @@ -338,51 +343,13 @@ private static void createAuxiliaryFiles(File installationDir, String username) String providerPath = installationDir.getAbsolutePath() + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; String providerContent = HelperNMFPackage.generateProviderProperties(username); - NMFPackageManager.writeFile(providerPath, providerContent); + HelperNMFPackage.writeFile(providerPath, providerContent); // Generate transport.properties String transportPath = installationDir.getAbsolutePath() + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; String transportContent = HelperNMFPackage.generateTransportProperties(); - NMFPackageManager.writeFile(transportPath, transportContent); - } - - private static void generateStartSHScript(Metadata appDetails, - File installationDir, File nmfDir) throws IOException { - String packageName = appDetails.getPackageName(); - String jarName = appDetails.getAppMainJar(); - - if (jarName.equals("")) { - File jar = HelperNMFPackage.findAppJarInFolder(installationDir); - jarName = jar.getName(); - } - - // The Java version for now will be forced to 8, however in - // the future the package should recommend a version - String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); - String mainClass = appDetails.getAppMainclass(); - String maxHeap = appDetails.getAppMaxHeap(); - String content = HelperNMFPackage.generateLinuxStartAppScript( - javaCMD, mainClass, jarName, maxHeap); - - String path = installationDir.getAbsolutePath() - + File.separator + "start_" + packageName + ".sh"; - - NMFPackageManager.writeFile(path, content); - File startApp = new File(path); - startApp.setExecutable(true, true); - } - - private static void writeFile(String path, String content) { - System.out.println(" >> Creating file on: " + path); - - try (FileWriter writer = new FileWriter(path)) { - writer.write(content); - writer.flush(); - writer.close(); - } catch (IOException e) { - // Handle the exception - } + HelperNMFPackage.writeFile(transportPath, transportContent); } /** @@ -493,7 +460,7 @@ private static String generateFilePathForSystem(final String path) throws IOExce return out.replace('\\', File.separatorChar); } - private static void installDependencies(Metadata metadata, String packageLocation, + private static void installDependencies(MetadataApp metadata, String packageLocation, File installationDir) throws IOException { String dependencies = metadata.getAppDependencies(); String parent = (new File(packageLocation)).getParent(); @@ -503,7 +470,7 @@ private static void installDependencies(Metadata metadata, String packageLocatio Level.INFO, "Dependencies are: " + dependencies); for (String file : dependencies.split(";")) { - file = file.replace(".jar", ".nmfpack"); + file = file.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); String path = parent + File.separator + file; extractFiles(new NMFPackage(path), installationDir); } @@ -568,17 +535,18 @@ private static void removeFiles(Metadata metadata) throws IOException { } private static void removeFile(File file) throws IOException { - System.out.println(" >> Removing: " + file.getCanonicalPath()); + String path = file.getCanonicalPath(); + System.out.println(" >> Removing: " + path); if (!file.exists()) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "Not Found / Does not exist: " + file.getCanonicalPath()); + "Not Found / Does not exist: " + path); return; } if (!file.delete()) { // Remove the file! Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "One of the files could not be deleted: " + file.getCanonicalPath()); + "One of the files could not be deleted: " + path); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index bdb4367ba..3612c4a26 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -108,7 +108,7 @@ public void uninstall(final String packageName, final boolean keepUserData) { ZipFile zipFile = new ZipFile(folderLocation); // Verify integrity of the file: Are all the declared files matching their CRCs? - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, "Reading the metadata file that includes the list of files to be uninstalled..."); Metadata metadata = Metadata.parseZipFile(zipFile); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java deleted file mode 100644 index 2b89e38b1..000000000 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsDependency.java +++ /dev/null @@ -1,75 +0,0 @@ -/* ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework - * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 - * You may not use this file except in compliance with the License. - * - * Except as expressly set forth in this License, the Software is provided to - * You on an "as is" basis and without warranties of any kind, including without - * limitation merchantability, fitness for a particular purpose, absence of - * defects or errors, accuracy or non-infringement of intellectual property rights. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * ---------------------------------------------------------------------------- - */ -package esa.mo.nmf.nmfpackage.metadata; - -import java.util.Properties; - -/** - * - * @author Cesar Coelho - */ -public class DetailsDependency { - - private final String packageName; - private final String version; - private final String timestamp; - private final Properties properties; - - public DetailsDependency(final String packageName, final String version, - final String timestamp) { - this.packageName = packageName; - this.version = version; - this.timestamp = timestamp; - this.properties = null; - } - - public DetailsDependency(final Properties properties) { - this.packageName = null; - this.version = null; - this.timestamp = null; - this.properties = properties; - } - - public Properties getProperties() { - if (properties != null) { - return properties; - } else { - Properties props = new Properties(); - props.put(Metadata.PACKAGE_NAME, packageName); - props.put(Metadata.PACKAGE_VERSION, version); - props.put(Metadata.PACKAGE_TIMESTAMP, timestamp); - return props; - } - } - - public String getPackageName() { - return (properties == null) ? packageName : properties.getProperty(Metadata.PACKAGE_NAME); - } - - public String getVersion() { - return (properties == null) ? version : properties.getProperty(Metadata.PACKAGE_VERSION); - } - - public String getTimestamp() { - return (properties == null) ? timestamp : properties.getProperty(Metadata.PACKAGE_TIMESTAMP); - } - -} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index 2d6dc707d..23b407e1a 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -68,27 +68,18 @@ public class Metadata { public static final String TYPE_UPDATE_MISSION = "mission"; public static final String TYPE_UPDATE_NMF = "nmf"; - public static final String APP_MAINCLASS = "pack.app.mainclass"; - public static final String APP_MAIN_JAR = "pack.app.mainjar"; - public static final String APP_MAX_HEAP = "pack.app.maxheap"; - public static final String APP_MIN_HEAP = "pack.app.minheap"; - public static final String APP_DEPENDENCIES = "pack.app.dependencies"; - public static final String FILE_COUNT = "zipped.file.count"; public static final String FILE_PATH = "zipped.file.path"; public static final String FILE_CRC = "zipped.file.crc"; - private final Properties properties; + protected final Properties properties; private ArrayList files; - public Metadata() { - this(new Properties()); - } - public Metadata(final Properties properties) { this(properties, null); } + @Deprecated public Metadata(Properties properties, ArrayList files) { this.files = files; this.properties = this.newOrderedProperties(); @@ -103,7 +94,6 @@ public Metadata(Properties properties, ArrayList files) { this.properties.put(FILE_PATH + "." + i, file.getPath()); this.properties.put(FILE_CRC + "." + i, String.valueOf(file.getCRC())); } - } } @@ -136,24 +126,11 @@ public String getPackageType() { return properties.getProperty(PACKAGE_TYPE); } - public String getAppMainclass() { - return properties.getProperty(APP_MAINCLASS); - } - - public String getAppMainJar() { - return properties.getProperty(APP_MAIN_JAR); - } - - public String getAppMaxHeap() { - return properties.getProperty(APP_MAX_HEAP); - } - - public String getAppMinHeap() { - return properties.getProperty(APP_MIN_HEAP); - } - - public String getAppDependencies() { - return properties.getProperty(APP_DEPENDENCIES); + public MetadataApp castToApp() { + if (!isApp()) { + return null; + } + return new MetadataApp(this.properties); } public synchronized ArrayList getFiles() { @@ -177,6 +154,7 @@ public void store(OutputStream outStream) throws IOException { properties.store(outStream, "NMF Package Metadata"); } + @Deprecated public void store() throws IOException, FileNotFoundException, IOException { this.store(new FileOutputStream(Metadata.FILENAME)); } @@ -248,7 +226,7 @@ public synchronized Set> entrySet() { }; } - public boolean isAppPackage() { + public boolean isApp() { // Before version 4, all NMF Packages were used to carry Apps // Version 4 is more dynamic and allows NMF Packages to carry other // types of data, such as: NMF updates, NMF Mission updates, JREs, etc @@ -283,6 +261,11 @@ public boolean sameAs(Metadata installedMetadata) { return true; } + /** + * Prints the metadata in a readable string. + * + * @return The metadata as a string. + */ public String print() { StringBuilder str = new StringBuilder(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java new file mode 100644 index 000000000..3c63d7c96 --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java @@ -0,0 +1,82 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage.metadata; + +import java.util.ArrayList; +import java.util.Properties; + +/** + * The MetadataApp class holds the metadata of an App in a NMF Package. + * + * @author Cesar Coelho + */ +public class MetadataApp extends Metadata { + + public static final String APP_MAINCLASS = "pack.app.mainclass"; + public static final String APP_MAIN_JAR = "pack.app.mainjar"; + public static final String APP_MAX_HEAP = "pack.app.maxheap"; + public static final String APP_MIN_HEAP = "pack.app.minheap"; + public static final String APP_DEPENDENCIES = "pack.app.dependencies"; + + public MetadataApp(final String packageName, final String version, + final String timestamp, final String mainclass, final String mainJar, + final String maxHeap, final ArrayList dependencies) { + super(new Properties()); + properties.put(Metadata.PACKAGE_NAME, packageName); + properties.put(Metadata.PACKAGE_VERSION, version); + properties.put(Metadata.PACKAGE_TIMESTAMP, timestamp); + properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); + properties.put(MetadataApp.APP_MAINCLASS, mainclass); + properties.put(MetadataApp.APP_MAIN_JAR, mainJar); + properties.put(MetadataApp.APP_MAX_HEAP, maxHeap); + properties.put(MetadataApp.APP_DEPENDENCIES, dependencies); + } + + MetadataApp(Properties props) { + super(props); + } + + public String getAppMainclass() { + return properties.getProperty(APP_MAINCLASS); + } + + public String getAppMainJar() { + return properties.getProperty(APP_MAIN_JAR); + } + + public String getAppMaxHeap() { + return properties.getProperty(APP_MAX_HEAP); + } + + public String getAppMinHeap() { + return properties.getProperty(APP_MIN_HEAP); + } + + public String getAppDependencies() { + return properties.getProperty(APP_DEPENDENCIES); + } + + public boolean hasDependencies() { + String dependencies = properties.getProperty(APP_DEPENDENCIES); + return (dependencies != null) && (dependencies.equals("")); + } + +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java new file mode 100644 index 000000000..f080cf570 --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java @@ -0,0 +1,40 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage.metadata; + +import java.util.Properties; + +/** + * The MetadataApp class holds the metadata of a Dependency in a NMF Package. + * + * @author Cesar Coelho + */ +public class MetadataDependency extends Metadata { + + public MetadataDependency(String packageName, String version, String timestamp) { + super(new Properties()); + properties.put(Metadata.PACKAGE_NAME, packageName); + properties.put(Metadata.PACKAGE_VERSION, version); + properties.put(Metadata.PACKAGE_TIMESTAMP, timestamp); + properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); + } + +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/DetailsApp.java similarity index 88% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java rename to core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/DetailsApp.java index 0aa61dee9..3574fafd8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/DetailsApp.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/DetailsApp.java @@ -18,8 +18,10 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.nmfpackage.metadata; +package esa.mo.nmf.nmfpackage.receipt; +import esa.mo.nmf.nmfpackage.metadata.Metadata; +import esa.mo.nmf.nmfpackage.metadata.MetadataApp; import java.util.ArrayList; import java.util.Properties; @@ -27,6 +29,7 @@ * * @author Cesar Coelho */ +@Deprecated public class DetailsApp { private final String packageName; @@ -51,6 +54,7 @@ public DetailsApp(final String packageName, final String version, this.properties = null; } + /* public DetailsApp(final Properties properties) { this.packageName = null; this.version = null; @@ -61,6 +65,7 @@ public DetailsApp(final Properties properties) { this.dependencies = null; this.properties = properties; } + */ public Properties getProperties() { if (properties != null) { @@ -70,12 +75,12 @@ public Properties getProperties() { props.put(Metadata.PACKAGE_NAME, packageName); props.put(Metadata.PACKAGE_VERSION, version); props.put(Metadata.PACKAGE_TIMESTAMP, timestamp); - props.put(Metadata.APP_MAINCLASS, mainclass); - props.put(Metadata.APP_MAIN_JAR, mainJar); - props.put(Metadata.APP_MAX_HEAP, maxHeap); + props.put(MetadataApp.APP_MAINCLASS, mainclass); + props.put(MetadataApp.APP_MAIN_JAR, mainJar); + props.put(MetadataApp.APP_MAX_HEAP, maxHeap); if (dependencies != null) { - props.put(Metadata.APP_DEPENDENCIES, generateDependencies()); + props.put(MetadataApp.APP_DEPENDENCIES, generateDependencies()); } return props; @@ -107,14 +112,14 @@ public String getTimestamp() { } public String getMainclass() { - return (properties == null) ? mainclass : properties.getProperty(Metadata.APP_MAINCLASS); + return (properties == null) ? mainclass : properties.getProperty(MetadataApp.APP_MAINCLASS); } public String getMainJar() { - return (properties == null) ? mainJar : properties.getProperty(Metadata.APP_MAIN_JAR); + return (properties == null) ? mainJar : properties.getProperty(MetadataApp.APP_MAIN_JAR); } public String getMaxHeap() { - return (properties == null) ? maxHeap : properties.getProperty(Metadata.APP_MAX_HEAP); + return (properties == null) ? maxHeap : properties.getProperty(MetadataApp.APP_MAX_HEAP); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java index f3c5a25ca..fd23b80c4 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/NMFPackageDescriptor.java @@ -21,7 +21,6 @@ package esa.mo.nmf.nmfpackage.receipt; import esa.mo.nmf.nmfpackage.NMFPackageFile; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import java.io.BufferedReader; @@ -35,6 +34,9 @@ import java.util.zip.ZipFile; /** + * The NMF Package Descriptor holds the information of an App. This class is + * deprecated because NMF Packages are now more flexible and can carry other + * types of information. This class will be removed in a future release. * * @author Cesar Coelho */ @@ -112,6 +114,7 @@ public static NMFPackageDescriptor parseZipFile(final ZipFile zipFile) throws IO } } + @Deprecated public Metadata toMetadata() { Properties props = details.getProperties(); props.put(Metadata.PACKAGE_METADATA_VERSION, descriptorVersion); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java index f0584ea50..152f32044 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion1.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java index 041577a38..629f9c51e 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion2.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java index 8a6974bc6..0393038de 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/receipt/ReceiptVersion3.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.receipt; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.BufferedReader; import java.io.BufferedWriter; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java index 368a45940..12ee957f8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java @@ -22,7 +22,7 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.nmfpackage.NMFPackageCreator; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; +import esa.mo.nmf.nmfpackage.receipt.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import java.io.File; import java.io.IOException; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 391f03fce..f73483752 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -21,10 +21,13 @@ package esa.mo.nmf.nmfpackage.utils; import esa.mo.helpertools.helpers.HelperMisc; +import esa.mo.helpertools.misc.OSValidator; +import esa.mo.nmf.nmfpackage.metadata.MetadataApp; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -75,7 +78,7 @@ private static String getBanner() { } public static String generateLinuxStartAppScript(String javaCommand, - String mainclass, String jarFilename, String maxHeap) throws IOException { + String jarFilename, MetadataApp meta) throws IOException { StringBuilder str = new StringBuilder(); str.append("#!/bin/sh\n"); str.append(getBanner()); @@ -85,8 +88,13 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("# Constants set at installation time:\n"); str.append("JAVA_CMD=").append(javaCommand).append("\n"); str.append("MAIN_JAR_NAME=").append(jarFilename).append("\n"); - str.append("MAIN_CLASS_NAME=").append(mainclass).append("\n"); - str.append("MAX_HEAP=").append(maxHeap).append("\n"); + str.append("MAIN_CLASS_NAME=").append(meta.getAppMainclass()).append("\n"); + + if (meta.hasDependencies()) { + str.append("JAR_DEPENDENCIES=").append(meta.getAppDependencies()).append("\n"); + } + + str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); // The NMF_LIB must be also hard-coded! The following code must be changed: str.append("NMF_LIB=").append("`cd ../../libs > /dev/null; pwd`").append("\n"); str.append("\n"); @@ -110,6 +118,11 @@ public static String generateLinuxStartAppScript(String javaCommand, return str.toString(); } + public static String generateWindowsStartAppScript(String javaCommand, + String jarFilename, MetadataApp meta) throws IOException { + return "To be done..."; + } + public static String generateProviderProperties(String runAs) throws IOException { StringBuilder str = new StringBuilder(); str.append(getBanner()); @@ -316,4 +329,56 @@ public static String findJREPath(File nmfDir, int recommended, int min, int max) return bestJRE; } + + public static void generateStartScript(MetadataApp appDetails, + File appDir, File nmfDir) throws IOException { + String name = appDetails.getPackageName(); + String jarName = appDetails.getAppMainJar(); + + if (jarName.equals("")) { + File jar = HelperNMFPackage.findAppJarInFolder(appDir); + jarName = jar.getName(); + } + + // The Java version for now will be forced to 8, however in + // the future the package should recommend a version + String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); + + OSValidator os = new OSValidator(); + + if (os.isUnix() || os.isMac()) { + String content = HelperNMFPackage.generateLinuxStartAppScript( + javaCMD, jarName, appDetails); + + String path = appDir.getAbsolutePath() + + File.separator + "start_" + name + ".sh"; + + HelperNMFPackage.writeFile(path, content); + File startApp = new File(path); + startApp.setExecutable(true, true); + } + + if (os.isWindows()) { + String content = HelperNMFPackage.generateWindowsStartAppScript( + javaCMD, jarName, appDetails); + + String path = appDir.getAbsolutePath() + + File.separator + "start_" + name + ".bat"; + + HelperNMFPackage.writeFile(path, content); + } + } + + public static void writeFile(String path, String content) { + System.out.println(" >> Creating file on: " + path); + + try (FileWriter writer = new FileWriter(path)) { + writer.write(content); + writer.flush(); + writer.close(); + } catch (IOException e) { + // Handle the exception + } + } + } diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 3000cd0aa..2abdefbff 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -22,9 +22,9 @@ import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.helpertools.helpers.HelperTime; -import esa.mo.nmf.nmfpackage.metadata.DetailsApp; -import esa.mo.nmf.nmfpackage.metadata.DetailsDependency; import esa.mo.nmf.nmfpackage.metadata.Metadata; +import esa.mo.nmf.nmfpackage.metadata.MetadataApp; +import esa.mo.nmf.nmfpackage.metadata.MetadataDependency; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -204,11 +204,8 @@ public void execute() throws MojoExecutionException { final String timestamp = HelperTime.time2readableString(time); // Package - DetailsApp details = new DetailsApp(name, version, + MetadataApp metadata = new MetadataApp(name, version, timestamp, mainClass, mainJar, maxHeap, dependencies); - - Metadata metadata = new Metadata(details.getProperties()); - metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); NMFPackageCreator.create(metadata, inputFiles, locations, TARGET_FOLDER); } @@ -219,11 +216,8 @@ private String packageJarDependency(Artifact artifact) { Time time = new Time(System.currentTimeMillis()); String timestamp = HelperTime.time2readableString(time); - DetailsDependency details = new DetailsDependency( + MetadataDependency metadata = new MetadataDependency( artifact.getArtifactId(), artifact.getVersion(), timestamp); - - Metadata metadata = new Metadata(details.getProperties()); - metadata.addProperty(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); ArrayList newLocations = new ArrayList<>(); newLocations.add("jars-shared-dependencies" + File.separator + file.getName()); NMFPackageCreator.create(metadata, files, newLocations, TARGET_FOLDER); From 990c49a36ade740cf0fad2092ffe88d35338a1c8 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 25 Oct 2022 23:41:33 +0200 Subject: [PATCH 098/173] Fixes the listApp operation. The matching was not occurring for specific App names --- .../AppsLauncherProviderServiceImpl.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index 7fe0d04de..63baa2ab9 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -508,7 +508,6 @@ private void prepareStopApp(final LongList appInstIds, final StopAppInteraction public ListAppResponse listApp(final IdentifierList appNames, final Identifier category, final MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); - ListAppResponse outList = new ListAppResponse(); if (null == appNames) { // Is the input null? throw new IllegalArgumentException("IdentifierList argument must not be null"); @@ -525,19 +524,24 @@ public ListAppResponse listApp(final IdentifierList appNames, final Identifier c } } - LongList ids = new LongList(); + LongList matchedIds = new LongList(); BooleanList runningApps = new BooleanList(); for (int index = 0; index < appNames.size(); index++) { if ("*".equals(appNames.get(index).getValue())) { - ids.clear(); // if the wildcard is in the middle of the input list, we clear the output list and... - ids.addAll(manager.listAll()); + // if the wildcard is in one of the entries of the input list, + // then we clear the output list and... + matchedIds.clear(); + matchedIds.addAll(manager.listAll()); break; } - if (manager.list(appNames.get(index)) == null) { - // The app does not exist... + Long appId = manager.list(appNames.get(index)); + + if (appId == null) { // The app does not exist... unkIndexList.add(new UInteger(index)); // Throw an UNKNOWN error + }else{ + matchedIds.add(appId); } } @@ -547,14 +551,11 @@ public ListAppResponse listApp(final IdentifierList appNames, final Identifier c ); } - for (Long id : ids) { // Is the app running? + for (Long id : matchedIds) { // Is the app running? runningApps.add(manager.isAppRunning(id)); } - outList.setBodyElement0(ids); - outList.setBodyElement1(runningApps); - - return outList; + return new ListAppResponse(matchedIds, runningApps); } @Override From c6fabd7db639f7550165ebbc6fb0420ea140fd56 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 25 Oct 2022 23:43:35 +0200 Subject: [PATCH 099/173] [nmf-packge] Adds the dependencies on the startApp.sh file & During uninstall/update tries to stop the App in case it is running --- .../NanoSatMOSupervisor.java | 4 + .../NanosatMOSupervisorBasicImpl.java | 6 +- core/nmf-package-lib/pom.xml | 4 +- .../esa/mo/nmf/nmfpackage/Deployment.java | 60 ++++ .../mo/nmf/nmfpackage/NMFPackageManager.java | 277 ++++++++++-------- .../nmf/nmfpackage/NMFPackagePMBackend.java | 25 +- .../mo/nmf/nmfpackage/metadata/Metadata.java | 5 + .../nmf/nmfpackage/metadata/MetadataApp.java | 63 +++- .../metadata/MetadataDependency.java | 5 +- .../tests/SimpleDemoPackageInstallation.java | 7 +- .../nmfpackage/utils/HelperNMFPackage.java | 52 ++-- .../nmfpackage/GenerateNMFPackageMojo.java | 19 +- 12 files changed, 340 insertions(+), 187 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index e67984c84..579183611 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -266,6 +266,10 @@ public final void closeGracefully(final ObjectId source) { System.exit(0); } } + + public AppsLauncherProviderServiceImpl getAppsLauncherService() { + return appsLauncherService; + } @Override public void init(MissionPlanningNMFAdapter mpAdapter) { diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java index ea88566d1..55a83457e 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java @@ -84,7 +84,11 @@ protected void startStatusTracking() { @Override public void init(MonitorAndControlNMFAdapter mcAdapter) { - init(mcAdapter, new PlatformServicesConsumer(), new NMFPackagePMBackend("packages")); + init(mcAdapter, + new PlatformServicesConsumer(), + new NMFPackagePMBackend("packages", this.getAppsLauncherService()) + ); + this.startStatusTracking(); } diff --git a/core/nmf-package-lib/pom.xml b/core/nmf-package-lib/pom.xml index c71e94388..ac0eb65fe 100644 --- a/core/nmf-package-lib/pom.xml +++ b/core/nmf-package-lib/pom.xml @@ -53,8 +53,8 @@ nmf-software-management - int.esa.nmf.core.moservices.impl - ccsds-com + org.xerial + sqlite-jdbc diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java new file mode 100644 index 000000000..69769703e --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -0,0 +1,60 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package esa.mo.nmf.nmfpackage; + +import java.io.File; + +/** + * + * @author Cesar Coelho + */ +public class Deployment { + + public static final String DIR_APPS = "apps"; + public static final String DIR_DRIVERS = "drivers"; + public static final String DIR_ETC = "etc"; + public static final String DIR_JARS_MISSION = "jars-mission"; + public static final String DIR_JARS_NMF = "jars-nmf"; + public static final String DIR_JARS_SHARED = "jars-shared-dependencies"; + public static final String DIR_JAVA = "java"; + public static final String DIR_LOGS = "logs"; + public static final String DIR_PACKAGES = "packages"; + public static final String DIR_PUBLIC = "public"; + + private static final String DIR_RECEIPTS = "installation_receipts"; + + private static final String INSTALLED_RECEIPTS_FOLDER_PROPERTY = "esa.mo.nmf.nmfpackage.receipts"; + + @Deprecated + private static final String INSTALLATION_FOLDER_PROPERTY = "esa.mo.nmf.nmfpackage.installationFolder"; + + public static File getReceiptsFolder() { + // Default location of the folder + File folder = new File(DIR_ETC + File.separator + DIR_RECEIPTS); + + // Read the Property of the folder to install the packages + if (System.getProperty(INSTALLED_RECEIPTS_FOLDER_PROPERTY) != null) { + folder = new File(System.getProperty(INSTALLED_RECEIPTS_FOLDER_PROPERTY)); + } + + return folder; + } + + @Deprecated + public static File getInstallationFolder() { + // Default location of the folder + File folder = new File(""); + + // Read the Property of the folder to install the packages + if (System.getProperty(INSTALLATION_FOLDER_PROPERTY) != null) { + folder = new File(System.getProperty(INSTALLATION_FOLDER_PROPERTY)); + } + + return folder; + } + + +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 5b53a4592..dfda6582e 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -27,6 +27,7 @@ import esa.mo.helpertools.misc.OSValidator; import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.metadata.MetadataApp; +import esa.mo.sm.impl.provider.AppsLauncherProviderServiceImpl; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -38,6 +39,12 @@ import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.LongList; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; /** * The NMFPackageManager class allows the install, uninstall and upgrade an NMF @@ -47,11 +54,6 @@ */ public class NMFPackageManager { - @Deprecated - private static final String INSTALLATION_FOLDER_PROPERTY = "esa.mo.nmf.nmfpackage.installationFolder"; - - private static final String INSTALLED_RECEIPTS_FOLDER_PROPERTY = "esa.mo.nmf.nmfpackage.receipts"; - private static final String RECEIPT_ENDING = ".receipt"; // This must match the group_nmf_apps value in the fresh_install.sh file @@ -63,9 +65,15 @@ public class NMFPackageManager { private static final String SEPARATOR = "--------------\n"; - private static final String FOLDER_APPS = "apps"; + private AppsLauncherProviderServiceImpl appsLauncher; - private static final String FOLDER_RECEIPTS = "installation_receipts"; + public NMFPackageManager(AppsLauncherProviderServiceImpl appsLauncher) { + this.appsLauncher = appsLauncher; + } + + public void setAppsLauncher(AppsLauncherProviderServiceImpl appsLauncher) { + this.appsLauncher = appsLauncher; + } /** * Installs an NMF Package on the specified NMF root folder. @@ -75,7 +83,7 @@ public class NMFPackageManager { * @throws FileNotFoundException if the file was not found * @throws IOException if there was a problem with the NMF Package */ - public static void install(final String packageLocation, + public void install(final String packageLocation, final File nmfDir) throws FileNotFoundException, IOException { System.out.printf(SEPARATOR); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, @@ -101,22 +109,16 @@ public static void install(final String packageLocation, Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the files to the new locations..."); - if(metadata.isApp()){ + if (metadata.isApp()) { installDependencies(metadata.castToApp(), packageLocation, nmfDir); } - + extractFiles(pack, nmfDir); String packageName = metadata.getPackageName(); if (metadata.isApp()) { - // We can do additional checks... for example: - // 1. Are we trying to install more than one App? - // 2. Does the app name on the package matches the folder name? - // -------------------------------------------------------------------- - - // This directory should be passed in the method signature: - File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + FOLDER_APPS + File appDir = new File(nmfDir.getAbsolutePath() + + File.separator + Deployment.DIR_APPS + File.separator + packageName); String username = null; @@ -141,25 +143,24 @@ public static void install(final String packageLocation, "The User could not be created: " + username, ex); username = null; } - - HelperNMFPackage.generateStartScript(metadata.castToApp(), installationDir, nmfDir); } - createAuxiliaryFiles(installationDir, username); + HelperNMFPackage.generateStartScript(metadata.castToApp(), appDir, nmfDir); + createAuxiliaryFiles(appDir, username); if ((new OSValidator()).isUnix()) { - // Change Group owner of the installationDir + // Change Group owner of the appDir if (username != null) { - LinuxUsersGroups.chgrp(true, username, installationDir.getAbsolutePath()); + LinuxUsersGroups.chgrp(true, username, appDir.getAbsolutePath()); } // chmod the installation directory with recursive - LinuxUsersGroups.chmod(false, true, "750", installationDir.getAbsolutePath()); + LinuxUsersGroups.chmod(false, true, "750", appDir.getAbsolutePath()); } } // Store a copy of the newReceipt to know that it has been installed! - File receiptsFolder = getReceiptsFolder(); + File receiptsFolder = Deployment.getReceiptsFolder(); String receiptFilename = packageName + RECEIPT_ENDING; String receiptPath = receiptsFolder.getCanonicalPath() + File.separator + receiptFilename; File receiptFile = new File(receiptPath); @@ -178,34 +179,27 @@ public static void install(final String packageLocation, * @param keepUserData A flag that sets if the user data is kept * @throws IOException if there was a problem during the uninstallation */ - public static void uninstall(final Metadata packageMetadata, + public void uninstall(final Metadata packageMetadata, final boolean keepUserData) throws IOException { System.out.printf(SEPARATOR); + String packageName = packageMetadata.getPackageName(); + + if (packageMetadata.isApp()) { // If the App is running, then stop it! + this.stopAppIfRunning(packageName); + } + Logger.getLogger(NMFPackageManager.class.getName()).log( Level.INFO, "Removing the files..."); - removeFiles(packageMetadata); - String packageName = packageMetadata.getPackageName(); - if (packageMetadata.isApp()) { // This directory should be passed in the method signature: - File nmfDir = getInstallationFolder(); + File nmfDir = Deployment.getInstallationFolder(); File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + FOLDER_APPS + + File.separator + Deployment.DIR_APPS + File.separator + packageName); removeAuxiliaryFiles(installationDir, packageName); - String receiptsPath = getReceiptsFolder().getCanonicalPath(); - String receiptFilename = packageName + RECEIPT_ENDING; - File receiptFile = new File(receiptsPath + File.separator + receiptFilename); - - if (!receiptFile.delete()) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "The receipt file could not be deleted from: " + receiptsPath); - } - // --------------------------------------- - if ((new OSValidator()).isUnix()) { if (!keepUserData) { String username = generateUsername(packageName); @@ -214,6 +208,17 @@ public static void uninstall(final Metadata packageMetadata, } } + removeFiles(packageMetadata); + + String receiptsPath = Deployment.getReceiptsFolder().getCanonicalPath(); + String receiptFilename = packageName + RECEIPT_ENDING; + File receiptFile = new File(receiptsPath + File.separator + receiptFilename); + + if (!receiptFile.delete()) { + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, + "The receipt file could not be deleted from: " + receiptsPath); + } + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully uninstalled: " + packageName); @@ -227,8 +232,9 @@ public static void uninstall(final Metadata packageMetadata, * @param nmfDir The NMF root directory * @throws IOException if the package could not be upgraded */ - public static void upgrade(final String packageLocation, final File nmfDir) throws IOException { + public void upgrade(final String packageLocation, final File nmfDir) throws IOException { System.out.printf(SEPARATOR); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Reading the receipt file that includes the list of files to be upgraded..."); @@ -241,7 +247,7 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro + "Version: " + newPackMetadata.getMetadataVersion()); } - File receiptsFolder = getReceiptsFolder(); + File receiptsFolder = Deployment.getReceiptsFolder(); String receiptFilename = newPackMetadata.getPackageName() + RECEIPT_ENDING; File oldReceiptFile = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); @@ -258,27 +264,31 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro + " (timestamp: " + newPackMetadata.getPackageTimestamp() + ")" ); - Logger.getLogger(NMFPackageManager.class.getName()).log( - Level.INFO, "Removing the previous files..."); - - removeFiles(oldPackMetadata); - String packageName = oldPackMetadata.getPackageName(); boolean isApp = oldPackMetadata.isApp(); + if (isApp) { // If the App is running, then stop it! + this.stopAppIfRunning(packageName); + } + + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "Removing the previous files..."); + if (isApp) { // This directory should be passed in the method signature: File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + FOLDER_APPS + + File.separator + Deployment.DIR_APPS + File.separator + packageName); removeAuxiliaryFiles(installationDir, packageName); + } - if (!oldReceiptFile.delete()) { // The file could not be deleted... - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "The receipt file could not be deleted from: " - + oldReceiptFile.getCanonicalPath()); - } + removeFiles(oldPackMetadata); + + if (!oldReceiptFile.delete()) { // The file could not be deleted... + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, + "The receipt file could not be deleted from: " + + oldReceiptFile.getCanonicalPath()); } Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, @@ -291,19 +301,19 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro if (isApp) { String username = null; File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + FOLDER_APPS + + File.separator + Deployment.DIR_APPS + File.separator + packageName); if ((new OSValidator()).isUnix()) { username = generateUsername(packageName); - HelperNMFPackage.generateStartScript(appMetadata, installationDir, nmfDir); } + HelperNMFPackage.generateStartScript(appMetadata, installationDir, nmfDir); createAuxiliaryFiles(installationDir, username); if ((new OSValidator()).isUnix()) { String path = installationDir.getAbsolutePath(); - // Change Group owner of the installationDir + // Change Group owner of the appDir if (username != null) { LinuxUsersGroups.chgrp(true, username, path); } @@ -322,36 +332,6 @@ public static void upgrade(final String packageLocation, final File nmfDir) thro System.out.printf(SEPARATOR); } - private static void removeAuxiliaryFiles(File installationDir, String appName) throws IOException { - String providerPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; - String transportPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; - String startPath = installationDir.getAbsolutePath() - + File.separator + "start_" + appName + ".sh"; - - // Remove the provider.properties - // Remove the transport.properties - // Remove the start_myAppName.sh - NMFPackageManager.removeFile(new File(providerPath)); - NMFPackageManager.removeFile(new File(transportPath)); - NMFPackageManager.removeFile(new File(startPath)); - } - - private static void createAuxiliaryFiles(File installationDir, String username) throws IOException { - // Generate provider.properties - String providerPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; - String providerContent = HelperNMFPackage.generateProviderProperties(username); - HelperNMFPackage.writeFile(providerPath, providerContent); - - // Generate transport.properties - String transportPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; - String transportContent = HelperNMFPackage.generateTransportProperties(); - HelperNMFPackage.writeFile(transportPath, transportContent); - } - /** * Checks if a certain NMF package is installed. Based on the name, goes to * the receipts folder and checks. @@ -359,7 +339,7 @@ private static void createAuxiliaryFiles(File installationDir, String username) * @param packageLocation The package location. * @return If it is installed or not. */ - public static boolean isPackageInstalled(final String packageLocation) { + public boolean isPackageInstalled(final String packageLocation) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, "Verifying if the package is installed..."); @@ -376,7 +356,7 @@ public static boolean isPackageInstalled(final String packageLocation) { return false; } - File temp = getReceiptsFolder(); + File temp = Deployment.getReceiptsFolder(); String packageName = metadata.getPackageName(); String receiptFilename = packageName + RECEIPT_ENDING; File receiptFile; @@ -425,31 +405,6 @@ public static boolean isPackageInstalled(final String packageLocation) { return true; } - private static File getReceiptsFolder() { - // Default location of the folder - File folder = new File(FOLDER_RECEIPTS); - - // Read the Property of the folder to install the packages - if (System.getProperty(INSTALLED_RECEIPTS_FOLDER_PROPERTY) != null) { - folder = new File(System.getProperty(INSTALLED_RECEIPTS_FOLDER_PROPERTY)); - } - - return folder; - } - - @Deprecated - private static File getInstallationFolder() { - // Default location of the folder - File folder = new File(""); - - // Read the Property of the folder to install the packages - if (System.getProperty(INSTALLATION_FOLDER_PROPERTY) != null) { - folder = new File(System.getProperty(INSTALLATION_FOLDER_PROPERTY)); - } - - return folder; - } - private static String generateFilePathForSystem(final String path) throws IOException { // Sanitize the path to prevent a ZipSlip attack: if (path.contains("..")) { @@ -460,20 +415,22 @@ private static String generateFilePathForSystem(final String path) throws IOExce return out.replace('\\', File.separatorChar); } - private static void installDependencies(MetadataApp metadata, String packageLocation, - File installationDir) throws IOException { - String dependencies = metadata.getAppDependencies(); + private static void installDependencies(MetadataApp metadata, + String packageLocation, File installationDir) throws IOException { + if (!metadata.hasDependencies()) { + return; + } + + ArrayList dependencies = metadata.getAppDependencies(); String parent = (new File(packageLocation)).getParent(); - if (dependencies != null && !dependencies.isEmpty()) { - Logger.getLogger(NMFPackageManager.class.getName()).log( - Level.INFO, "Dependencies are: " + dependencies); + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "Dependencies are: " + dependencies.toString()); - for (String file : dependencies.split(";")) { - file = file.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); - String path = parent + File.separator + file; - extractFiles(new NMFPackage(path), installationDir); - } + for (String file : dependencies) { + file = file.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); + String path = parent + File.separator + file; + extractFiles(new NMFPackage(path), installationDir); } } @@ -521,8 +478,40 @@ private static void extractFiles(NMFPackage pack, File to) throws IOException { } } + private static void removeAuxiliaryFiles(File installationDir, String appName) throws IOException { + String providerPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; + String transportPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; + File linux = new File(installationDir.getAbsolutePath() + + File.separator + "start_" + appName + ".sh"); + File windows = new File(installationDir.getAbsolutePath() + + File.separator + "start_" + appName + ".sh"); + + // Remove the provider.properties + // Remove the transport.properties + // Remove the start_myAppName.sh + NMFPackageManager.removeFile(new File(providerPath)); + NMFPackageManager.removeFile(new File(transportPath)); + NMFPackageManager.removeFile(windows.exists() ? windows : linux); + } + + private static void createAuxiliaryFiles(File installationDir, String username) throws IOException { + // Generate provider.properties + String providerPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; + String providerContent = HelperNMFPackage.generateProviderProperties(username); + HelperNMFPackage.writeFile(providerPath, providerContent); + + // Generate transport.properties + String transportPath = installationDir.getAbsolutePath() + + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; + String transportContent = HelperNMFPackage.generateTransportProperties(); + HelperNMFPackage.writeFile(transportPath, transportContent); + } + private static void removeFiles(Metadata metadata) throws IOException { - File folder = getInstallationFolder(); + File folder = Deployment.getInstallationFolder(); File file; // Do the files actually match the descriptor? @@ -569,4 +558,40 @@ private static String generateUsername(String appName) { return USER_NMF_APP_PREFIX + appName; } + private void stopAppIfRunning(String name) { + if (appsLauncher == null) { + return; + } + + try { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "Checking if " + name + " App is running..."); + + IdentifierList myApp = new IdentifierList(); + myApp.add(new Identifier(name)); + Identifier cat = new Identifier("*"); + ListAppResponse response = appsLauncher.listApp(myApp, cat, null); + LongList runningApp = new LongList(); + + for (int i = 0; i < response.getBodyElement0().size(); i++) { + if (response.getBodyElement1().get(i)) { + Long appId = response.getBodyElement0().get(i); + runningApp.add(appId); + } + } + + if (!runningApp.isEmpty()) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "Stopping the " + name + " App..."); + + appsLauncher.stopApp(runningApp, null); + } + } catch (MALInteractionException ex) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "The " + name + " App was not found!"); + } catch (MALException ex) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.SEVERE, "(2) Something went wrong...", ex); + } + } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index 3612c4a26..7763aae4b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -22,8 +22,9 @@ import esa.mo.helpertools.misc.Const; import esa.mo.nmf.nmfpackage.metadata.Metadata; -import java.io.File; +import esa.mo.sm.impl.provider.AppsLauncherProviderServiceImpl; import esa.mo.sm.impl.util.PMBackend; +import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; @@ -37,7 +38,8 @@ */ public class NMFPackagePMBackend implements PMBackend { - private final File packagesFolder; // Location of the folder + private final File packagesFolder; // Location of the packages folder + private final NMFPackageManager manager; /** * Initializes a backend for NMF Packages. The backend will look for @@ -45,8 +47,13 @@ public class NMFPackagePMBackend implements PMBackend { * * @param folder The folder to look for packages */ + public NMFPackagePMBackend(String folder, AppsLauncherProviderServiceImpl appsLauncherService) { + this.packagesFolder = new File(folder); + this.manager = new NMFPackageManager(appsLauncherService); + } + public NMFPackagePMBackend(String folder) { - packagesFolder = new File(folder); + this(folder, null); } @Override @@ -90,7 +97,7 @@ public void install(final String packageName) { + "\nPackage location: " + packageLocation); try { - NMFPackageManager.install(packageLocation, destination); + manager.install(packageLocation, destination); } catch (IOException ex) { Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, "The package '" + packageName + "' could not be installed!", ex); @@ -112,7 +119,7 @@ public void uninstall(final String packageName, final boolean keepUserData) { "Reading the metadata file that includes the list of files to be uninstalled..."); Metadata metadata = Metadata.parseZipFile(zipFile); - NMFPackageManager.uninstall(metadata, keepUserData); + manager.uninstall(metadata, keepUserData); } catch (IOException ex) { Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.SEVERE, "The package '" + packageName + "' could not be uninstalled!", ex); @@ -129,7 +136,7 @@ public void upgrade(final String packageName) { File destination = getNMFDir(); try { - NMFPackageManager.upgrade(packageLocation, destination); + manager.upgrade(packageLocation, destination); } catch (IOException ex) { Logger.getLogger(NMFPackagePMBackend.class.getName()).log( Level.SEVERE, "The package could not be upgraded!", ex); @@ -145,7 +152,7 @@ public String getPublicKey(final String packageName) { @Override public boolean isPackageInstalled(final String packageName) { String folderLocation = this.getFolderLocation(packageName); - return NMFPackageManager.isPackageInstalled(folderLocation); + return manager.isPackageInstalled(folderLocation); } @Override @@ -162,4 +169,8 @@ private File getNMFDir() { return new File(""); } + public void setAppsLauncher(AppsLauncherProviderServiceImpl appsLauncherService) { + manager.setAppsLauncher(appsLauncherService); + } + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index 23b407e1a..aaa3a2515 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -20,6 +20,7 @@ */ package esa.mo.nmf.nmfpackage.metadata; +import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.nmfpackage.NMFPackageManager; import esa.mo.nmf.nmfpackage.receipt.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.NMFPackageFile; @@ -43,6 +44,7 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import org.ccsds.moims.mo.mal.structures.Time; /** * The Metadata class holds the metadata of a NMF Package. @@ -83,6 +85,9 @@ public Metadata(final Properties properties) { public Metadata(Properties properties, ArrayList files) { this.files = files; this.properties = this.newOrderedProperties(); + final Time time = new Time(System.currentTimeMillis()); + final String timestamp = HelperTime.time2readableString(time); + this.properties.put(Metadata.PACKAGE_TIMESTAMP, timestamp); this.properties.put(PACKAGE_METADATA_VERSION, METADATA_VERSION_LATEST); this.properties.putAll(properties); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java index 3c63d7c96..411ae4ef2 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java @@ -20,8 +20,12 @@ */ package esa.mo.nmf.nmfpackage.metadata; +import esa.mo.helpertools.helpers.HelperTime; +import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Properties; +import org.ccsds.moims.mo.mal.structures.Time; /** * The MetadataApp class holds the metadata of an App in a NMF Package. @@ -36,18 +40,34 @@ public class MetadataApp extends Metadata { public static final String APP_MIN_HEAP = "pack.app.minheap"; public static final String APP_DEPENDENCIES = "pack.app.dependencies"; + /** + * + * @param packageName The name of the package. + * @param version + * @param timestamp + * @param mainclass + * @param mainJar + * @param maxHeap + * @param dependencies + */ public MetadataApp(final String packageName, final String version, - final String timestamp, final String mainclass, final String mainJar, - final String maxHeap, final ArrayList dependencies) { + final String mainclass, final String mainJar, final String maxHeap, + final ArrayList dependencies) { super(new Properties()); + properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); properties.put(Metadata.PACKAGE_NAME, packageName); properties.put(Metadata.PACKAGE_VERSION, version); - properties.put(Metadata.PACKAGE_TIMESTAMP, timestamp); - properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); properties.put(MetadataApp.APP_MAINCLASS, mainclass); properties.put(MetadataApp.APP_MAIN_JAR, mainJar); properties.put(MetadataApp.APP_MAX_HEAP, maxHeap); - properties.put(MetadataApp.APP_DEPENDENCIES, dependencies); + + if (dependencies != null && !dependencies.isEmpty()) { + StringBuilder str = new StringBuilder(); + for (String dep : dependencies) { + str.append(dep).append(";"); + } + properties.put(APP_DEPENDENCIES, removeLastChar(str.toString())); + } } MetadataApp(Properties props) { @@ -70,13 +90,40 @@ public String getAppMinHeap() { return properties.getProperty(APP_MIN_HEAP); } - public String getAppDependencies() { - return properties.getProperty(APP_DEPENDENCIES); + public ArrayList getAppDependencies() { + String d = properties.getProperty(APP_DEPENDENCIES); + if (d == null) { + return new ArrayList<>(); + } + + ArrayList deps = new ArrayList<>(); + deps.addAll(Arrays.asList(d.split(";"))); + return deps; + } + + public String getAppDependenciesFullPaths(File sharedLibsFolder) { + String d = properties.getProperty(APP_DEPENDENCIES); + if (d == null) { + return ""; + } + + StringBuilder out = new StringBuilder(); + String absolutePath = sharedLibsFolder.getAbsolutePath(); + String[] splits = d.split(";"); + for (String split : splits) { + out.append(absolutePath).append(File.separator).append(split).append(":"); + } + + return removeLastChar(out.toString()); } public boolean hasDependencies() { String dependencies = properties.getProperty(APP_DEPENDENCIES); - return (dependencies != null) && (dependencies.equals("")); + return (dependencies != null) && !(dependencies.equals("")); + } + + private String removeLastChar(String input) { + return input.substring(0, input.length() - 1); // Removes last: ";" } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java index f080cf570..c7d4c18f3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java @@ -29,12 +29,11 @@ */ public class MetadataDependency extends Metadata { - public MetadataDependency(String packageName, String version, String timestamp) { + public MetadataDependency(String packageName, String version) { super(new Properties()); + properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); properties.put(Metadata.PACKAGE_NAME, packageName); properties.put(Metadata.PACKAGE_VERSION, version); - properties.put(Metadata.PACKAGE_TIMESTAMP, timestamp); - properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java index f8b3a1702..556874da3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java @@ -6,7 +6,7 @@ * ---------------------------------------------------------------------------- * System : ESA NanoSat MO Framework * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 * You may not use this file except in compliance with the License. * * Except as expressly set forth in this License, the Software is provided to @@ -44,9 +44,10 @@ public static void main(final String[] args) { public static void installPackage() { String packagePath = "TBD"; String destinationFolder = "TBD"; - + NMFPackageManager manager = new NMFPackageManager(null); + try { - NMFPackageManager.install(packagePath, new File(destinationFolder)); + manager.install(packagePath, new File(destinationFolder)); } catch (IOException ex) { Logger.getLogger(SimpleDemoPackageInstallation.class.getName()).log(Level.SEVERE, "The package could not be installed!", ex); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index f73483752..87e11fda9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -22,6 +22,7 @@ import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.misc.OSValidator; +import esa.mo.nmf.nmfpackage.Deployment; import esa.mo.nmf.nmfpackage.metadata.MetadataApp; import java.io.BufferedInputStream; import java.io.File; @@ -82,37 +83,43 @@ public static String generateLinuxStartAppScript(String javaCommand, StringBuilder str = new StringBuilder(); str.append("#!/bin/sh\n"); str.append(getBanner()); - str.append("cd ${0%/*}\n"); - str.append("\n"); + str.append("cd ${0%/*}\n\n"); - str.append("# Constants set at installation time:\n"); - str.append("JAVA_CMD=").append(javaCommand).append("\n"); - str.append("MAIN_JAR_NAME=").append(jarFilename).append("\n"); - str.append("MAIN_CLASS_NAME=").append(meta.getAppMainclass()).append("\n"); + str.append("# Java Runtime Environment:\n"); + str.append("JAVA_CMD=").append(javaCommand).append("\n\n"); + str.append("# App-related constants:\n"); + str.append("MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); + str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); + str.append("MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); + + str.append("# Jars from: App, NMF, and shared dependencies:\n"); + str.append("JAR_APP=").append(jarFilename).append("\n"); + // The following code must be changed: + str.append("JARS_NMF=").append("`cd ../../libs > /dev/null; pwd`").append("\n"); + String shared = ""; if (meta.hasDependencies()) { - str.append("JAR_DEPENDENCIES=").append(meta.getAppDependencies()).append("\n"); + String nmf = Deployment.getInstallationFolder().getAbsolutePath(); + File sharedLibs = new File(nmf + File.separator + Deployment.DIR_JARS_SHARED); + String paths = meta.getAppDependenciesFullPaths(sharedLibs); + str.append("JARS_SHARED=").append(paths); + shared = ":$JARS_SHARED"; } - - str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); - // The NMF_LIB must be also hard-coded! The following code must be changed: - str.append("NMF_LIB=").append("`cd ../../libs > /dev/null; pwd`").append("\n"); - str.append("\n"); + str.append("\n\nJARS_ALL=$JAR_APP:$JARS_NMF/*").append(shared); + str.append("\n\n"); str.append("if [ -z \"$JAVA_OPTS\" ] ; then\n"); str.append(" JAVA_OPTS=\"-Xms32m -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); - str.append("fi\n"); - str.append("\n"); + str.append("fi\n\n"); str.append("export JAVA_OPTS\n"); - str.append("export NMF_LIB\n"); - str.append("\n"); + str.append("export NMF_LIB\n\n"); // The command "exec" spawns the execution in a different process // str.append("exec "); str.append("$JAVA_CMD $JAVA_OPTS \\\n"); - str.append(" -classpath \"$NMF_LIB/*:$MAIN_JAR_NAME\" \\\n"); - str.append(" \"$MAIN_CLASS_NAME\" \\\n"); + str.append(" -classpath \"$JARS_ALL\" \\\n"); + str.append(" \"$MAIN_CLASS\" \\\n"); str.append(" \"$@\"\n"); return str.toString(); @@ -345,14 +352,13 @@ public static void generateStartScript(MetadataApp appDetails, String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); OSValidator os = new OSValidator(); + String path = appDir.getAbsolutePath() + File.separator; if (os.isUnix() || os.isMac()) { String content = HelperNMFPackage.generateLinuxStartAppScript( javaCMD, jarName, appDetails); - String path = appDir.getAbsolutePath() - + File.separator + "start_" + name + ".sh"; - + path += "start_" + name + ".sh"; HelperNMFPackage.writeFile(path, content); File startApp = new File(path); startApp.setExecutable(true, true); @@ -362,9 +368,7 @@ public static void generateStartScript(MetadataApp appDetails, String content = HelperNMFPackage.generateWindowsStartAppScript( javaCMD, jarName, appDetails); - String path = appDir.getAbsolutePath() - + File.separator + "start_" + name + ".bat"; - + path += "start_" + name + ".bat"; HelperNMFPackage.writeFile(path, content); } } diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 2abdefbff..8fb853c9e 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -21,8 +21,6 @@ package esa.mo.nmf.nmfpackage; import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; -import esa.mo.helpertools.helpers.HelperTime; -import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.metadata.MetadataApp; import esa.mo.nmf.nmfpackage.metadata.MetadataDependency; import java.io.File; @@ -39,7 +37,6 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; -import org.ccsds.moims.mo.mal.structures.Time; /** * Generates the NMF Package for the NMF App @@ -116,7 +113,7 @@ public enum Privilege { @Override public void execute() throws MojoExecutionException { getLog().info("Generating NMF Package..."); - appPath = "apps" + File.separator + name + File.separator; + appPath = Deployment.DIR_APPS + File.separator + name + File.separator; String mainJar = ""; try { @@ -200,12 +197,10 @@ public void execute() throws MojoExecutionException { } getLog().info("------\nGenerating project NMF Package...\n"); - final Time time = new Time(System.currentTimeMillis()); - final String timestamp = HelperTime.time2readableString(time); - + // Package MetadataApp metadata = new MetadataApp(name, version, - timestamp, mainClass, mainJar, maxHeap, dependencies); + mainClass, mainJar, maxHeap, dependencies); NMFPackageCreator.create(metadata, inputFiles, locations, TARGET_FOLDER); } @@ -214,12 +209,10 @@ private String packageJarDependency(Artifact artifact) { ArrayList files = new ArrayList<>(); files.add(file.toPath().toString()); - Time time = new Time(System.currentTimeMillis()); - String timestamp = HelperTime.time2readableString(time); - MetadataDependency metadata = new MetadataDependency( - artifact.getArtifactId(), artifact.getVersion(), timestamp); + String id = artifact.getArtifactId(); + MetadataDependency metadata = new MetadataDependency(id, artifact.getVersion()); ArrayList newLocations = new ArrayList<>(); - newLocations.add("jars-shared-dependencies" + File.separator + file.getName()); + newLocations.add(Deployment.DIR_JARS_SHARED + File.separator + file.getName()); NMFPackageCreator.create(metadata, files, newLocations, TARGET_FOLDER); return file.getName(); } From 1f5d22b740c8cdc969e5d8e1f7f35ed19c14fd59 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 09:15:59 +0200 Subject: [PATCH 100/173] Added Licence to the Header of the file --- .../esa/mo/nmf/nmfpackage/Deployment.java | 23 +++++++++++++++---- .../nmfpackage/utils/HelperNMFPackage.java | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index 69769703e..259a79dbc 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -1,7 +1,22 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this zipFile except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- */ package esa.mo.nmf.nmfpackage; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 87e11fda9..28e765045 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -92,7 +92,7 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); str.append("MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); - str.append("# Jars from: App, NMF, and shared dependencies:\n"); + str.append("# Jars from: App, NMF, and Shared dependencies:\n"); str.append("JAR_APP=").append(jarFilename).append("\n"); // The following code must be changed: str.append("JARS_NMF=").append("`cd ../../libs > /dev/null; pwd`").append("\n"); From 97aae8a638bd1ec9187ba967db74c0fa7314a4c6 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 09:20:12 +0200 Subject: [PATCH 101/173] Reduced the logging messages --- .../mc/impl/provider/AggregationProviderServiceImpl.java | 8 +++----- .../mo/mc/impl/provider/ParameterProviderServiceImpl.java | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java index 91f77b704..bbe5e5a21 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java @@ -161,11 +161,9 @@ public synchronized void init(COMServicesProvider comServices, ParameterManager periodicReportingManager.init(); // Initialize the Periodic Reporting Manager periodicSamplingManager.init(); // Initialize the Periodic Sampling Manager - storeAggregationsInCOMArchive = Boolean.parseBoolean(System.getProperty( - MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, "true")); - String msg = MessageFormat.format("{0} = {1}", MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, - storeAggregationsInCOMArchive); - Logger.getLogger(AggregationProviderServiceImpl.class.getName()).log(Level.INFO, msg); + storeAggregationsInCOMArchive = Boolean.parseBoolean(System.getProperty(MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, "true")); + String msg = MessageFormat.format("{0} = {1}", MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, storeAggregationsInCOMArchive); + Logger.getLogger(AggregationProviderServiceImpl.class.getName()).log(Level.FINE, msg); initialiased = true; Logger.getLogger(AggregationProviderServiceImpl.class.getName()).info("Aggregation service READY"); diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java index 6b1e8dc81..185e21e8c 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java @@ -163,11 +163,9 @@ public synchronized void init(ParameterManager parameterManager) throws MALExcep groupService.init(manager.getArchiveService()); - storeParametersInCOMArchive = Boolean.parseBoolean(System.getProperty( - MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, "true")); - String msg = MessageFormat.format("{0} = {1}", MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, - storeParametersInCOMArchive); - Logger.getLogger(ParameterProviderServiceImpl.class.getName()).log(Level.INFO, msg); + storeParametersInCOMArchive = Boolean.parseBoolean(System.getProperty(MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, "true")); + String msg = MessageFormat.format("{0} = {1}", MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, storeParametersInCOMArchive); + Logger.getLogger(ParameterProviderServiceImpl.class.getName()).log(Level.FINE, msg); initialiased = true; Logger.getLogger(ParameterProviderServiceImpl.class.getName()).info("Parameter service READY"); From 59f8ca8b0b5c72a3b6234f94955cbab07230c519 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 09:33:38 +0200 Subject: [PATCH 102/173] Better logging messages in the COM Archive --- .../archive/db/TransactionsProcessor.java | 46 +++++++++---------- .../mo/com/impl/provider/ArchiveManager.java | 8 ++-- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java index dcbec11fc..f111bb9d7 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/TransactionsProcessor.java @@ -20,6 +20,8 @@ */ package esa.mo.com.impl.archive.db; +import esa.mo.com.impl.archive.entities.COMObjectEntity; +import esa.mo.com.impl.provider.ArchiveManager; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; @@ -36,15 +38,11 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; - import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; import org.ccsds.moims.mo.com.archive.structures.QueryFilter; import org.ccsds.moims.mo.mal.structures.IntegerList; import org.ccsds.moims.mo.mal.structures.LongList; -import esa.mo.com.impl.archive.entities.COMObjectEntity; -import esa.mo.com.impl.provider.ArchiveManager; - /** * The Transactions Processor is responsible for executing the transactions with * the database. It has one general executor with 2 threads for flushing the @@ -87,12 +85,6 @@ public void submitExternalTaskDBTransactions(final Runnable task) { dbTransactionsExecutor.execute(task); } - public Future submitExternalTransactionExecutorTask(final Callable task) { - this.sequencialStoring.set(false); - - return dbTransactionsExecutor.submit(task); - } - /** * Resizes the database file to match its contents. */ @@ -107,7 +99,8 @@ public void vacuum() { } } - public COMObjectEntity getCOMObject(final Integer objTypeId, final Integer domainId, final Long objId) { + public COMObjectEntity getCOMObject(final Integer objTypeId, final Integer domainId, + final Long objId) { this.sequencialStoring.set(false); // Sequential stores can no longer happen otherwise we break order LongList ids = new LongList(); @@ -194,7 +187,7 @@ public void insert(final ArrayList perObjs, final Runnable publ } catch (InterruptedException ex) { Logger.getLogger(ArchiveManager.class.getName()).log(Level.SEVERE, "Something went wrong...", ex); } - + dbTransactionsExecutor.execute(new RunnableInsert(this, publishEvents)); } @@ -211,12 +204,13 @@ public void update(final ArrayList newObjs, final Runnable publ dbTransactionsExecutor.execute(new RunnableUpdate(this, publishEvents, newObjs)); } - public ArrayList query(final IntegerList objTypeIds, final ArchiveQuery archiveQuery, - final IntegerList domainIds, final Integer providerURIId, final Integer networkId, - final SourceLinkContainer sourceLink, final QueryFilter filter) { + public ArrayList query(final IntegerList objTypeIds, + final ArchiveQuery archiveQuery, final IntegerList domainIds, + final Integer providerURIId, final Integer networkId, + final SourceLinkContainer sourceLink, final QueryFilter filter) { this.sequencialStoring.set(false); // Sequential stores can no longer happen otherwise we break order - final CallableSelectQuery task = new CallableSelectQuery(this, objTypeIds, archiveQuery, domainIds, - providerURIId, networkId, sourceLink, filter); + final CallableSelectQuery task = new CallableSelectQuery(this, objTypeIds, archiveQuery, + domainIds, providerURIId, networkId, sourceLink, filter); Future> future = dbTransactionsExecutor.submit(task); @@ -229,12 +223,13 @@ public ArrayList query(final IntegerList objTypeIds, final Arch return null; } - public int delete(final IntegerList objTypeIds, final ArchiveQuery archiveQuery, final IntegerList domainIds, - final Integer providerURIId, final Integer networkId, final SourceLinkContainer sourceLink, - final QueryFilter filter) { + public int delete(final IntegerList objTypeIds, + final ArchiveQuery archiveQuery, final IntegerList domainIds, + final Integer providerURIId, final Integer networkId, + final SourceLinkContainer sourceLink, final QueryFilter filter) { this.sequencialStoring.set(false); // Sequential stores can no longer happen otherwise we break order - final CallableDeleteQuery task = new CallableDeleteQuery(this, objTypeIds, archiveQuery, domainIds, - providerURIId, networkId, sourceLink, filter); + final CallableDeleteQuery task = new CallableDeleteQuery(this, objTypeIds, archiveQuery, + domainIds, providerURIId, networkId, sourceLink, filter); Future future = dbTransactionsExecutor.submit(task); @@ -282,13 +277,16 @@ static class DBThreadFactory implements ThreadFactory { DBThreadFactory(String prefix) { SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); + group = (s != null) ? s.getThreadGroup() + : Thread.currentThread().getThreadGroup(); namePrefix = prefix + "-thread-"; } @Override public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); + Thread t = new Thread(group, r, + namePrefix + threadNumber.getAndIncrement(), + 0); if (t.isDaemon()) { t.setDaemon(false); } diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java index 3aece9dde..f6b694b06 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java @@ -133,14 +133,16 @@ public synchronized void init() { this.dbProcessor.submitExternalTaskDBTransactions(() -> { synchronized (manager) { + Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, + "Starting Archive Backend..."); this.dbBackend.startBackendDatabase(this.dbProcessor); - Logger.getLogger(ArchiveManager.class.getName()).log(Level.FINE, - "Initializing Fast classes!"); + Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, + "Archive Backend started! Initializing Fast classes..."); fastDomain.init(); fastObjectType.init(); fastNetwork.init(); fastProviderURI.init(); - Logger.getLogger(ArchiveManager.class.getName()).log(Level.FINE, + Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, "The Fast classes are initialized!"); } }); From d87f62a1bb50fbbe8264e34bbcc38fd80ab6142a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 10:21:59 +0200 Subject: [PATCH 103/173] Reduced log verbosity --- .../mo/platform/impl/provider/adapters/AIMovidiusAdapter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index c7a53e1d2..371bedbee 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -61,7 +61,7 @@ public AIMovidiusAdapter() throws IOException { + " The command returned: " + out); } - LOGGER.log(Level.INFO, "The Python3 version is: " + splits[1]); + LOGGER.log(Level.FINE, "The Python3 version is: " + splits[1]); String[] subVersions = splits[1].split("\\."); if (Integer.valueOf(subVersions[1]) < 6) { @@ -104,7 +104,7 @@ private File crawlOptions(String[] options, String filename) throws IOException File path = this.findPathToFile(folder, filename); if (path != null) { // Found! - LOGGER.log(Level.INFO, "The file was found on path:\n" + LOGGER.log(Level.FINE, "The file was found on path:\n" + " >> " + path.getAbsolutePath()); return path; } From af9779c1b70092daa0044d3caf4e9815ce70377b Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 10:25:03 +0200 Subject: [PATCH 104/173] Better Archive startup parallelization --- .../com/impl/archive/db/DatabaseBackend.java | 7 +-- .../mo/com/impl/provider/ArchiveManager.java | 47 ++++++++++++------- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java index 5d1fecd9f..9bb4e869a 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/archive/db/DatabaseBackend.java @@ -37,6 +37,7 @@ * @author Cesar Coelho */ public class DatabaseBackend { + public static final Logger LOGGER = Logger.getLogger(ArchiveManager.class.getName()); private static final String DRIVER_CLASS_NAME = "org.sqlite.JDBC"; // SQLite JDBC Driver @@ -140,11 +141,7 @@ public void startBackendDatabase(final TransactionsProcessor dbProcessor) { isPostgres = true; } Statement query = serverConnection.createStatement(); - query.execute( - "CREATE TABLE IF NOT EXISTS COMObjectEntity (objectTypeId INTEGER NOT NULL, objId BIGINT NOT NULL, domainId INTEGER NOT NULL, network INTEGER, objBody " + - blobType + - ", providerURI INTEGER, relatedLink BIGINT, sourceLinkDomainId INTEGER, sourceLinkObjId BIGINT, sourceLinkObjectTypeId INTEGER, timestampArchiveDetails BIGINT, PRIMARY KEY (objectTypeId, objId, domainId))"); - ; + query.execute("CREATE TABLE IF NOT EXISTS COMObjectEntity (objectTypeId INTEGER NOT NULL, objId BIGINT NOT NULL, domainId INTEGER NOT NULL, network INTEGER, objBody " + blobType + ", providerURI INTEGER, relatedLink BIGINT, sourceLinkDomainId INTEGER, sourceLinkObjId BIGINT, sourceLinkObjectTypeId INTEGER, timestampArchiveDetails BIGINT, PRIMARY KEY (objectTypeId, objId, domainId))"); } catch (SQLException ex) { Logger.getLogger(DatabaseBackend.class.getName()).log(Level.SEVERE, null, ex); } diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java index f6b694b06..6069493ea 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java @@ -77,7 +77,7 @@ * @author Cesar Coelho */ public class ArchiveManager { - + public static final Logger LOGGER = Logger.getLogger(ArchiveManager.class.getName()); private final DatabaseBackend dbBackend; @@ -92,7 +92,8 @@ public class ArchiveManager { private EventProviderServiceImpl eventService; /** - * Should generate COM Archive events: ObjectStored, ObjectUpdated, ObjectDeleted + * Should generate COM Archive events: ObjectStored, ObjectUpdated, + * ObjectDeleted */ private boolean globalGenerateEvents; @@ -104,19 +105,18 @@ public class ArchiveManager { public ArchiveManager(EventProviderServiceImpl eventService) { this.eventService = eventService; - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) != null && - MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION).getServiceByName( - ArchiveHelper.ARCHIVE_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) != null + && MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) + .getServiceByName(ArchiveHelper.ARCHIVE_SERVICE_NAME) == null) { try { ArchiveHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - catch (MALException ex) { + } catch (MALException ex) { LOGGER.log(Level.SEVERE, "Unexpectedly ArchiveHelper already initialized!?", ex); } } this.globalGenerateEvents = Boolean.parseBoolean(System.getProperty(Const.ARCHIVE_GENERATE_EVENTS_PROPERTY, - Const.ARCHIVE_GENERATE_EVENTS_DEFAULT)); + Const.ARCHIVE_GENERATE_EVENTS_DEFAULT)); this.dbBackend = new DatabaseBackend(); this.dbProcessor = new TransactionsProcessor(dbBackend); @@ -133,17 +133,28 @@ public synchronized void init() { this.dbProcessor.submitExternalTaskDBTransactions(() -> { synchronized (manager) { + long timestamp = System.currentTimeMillis(); Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, "Starting Archive Backend..."); this.dbBackend.startBackendDatabase(this.dbProcessor); + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, - "Archive Backend started! Initializing Fast classes..."); + "Archive Backend started in " + timestamp + " ms! " + + "Initializing Fast classes..."); + } + }); + + this.dbProcessor.submitExternalTaskDBTransactions(() -> { + synchronized (manager) { + long timestamp = System.currentTimeMillis(); fastDomain.init(); fastObjectType.init(); fastNetwork.init(); fastProviderURI.init(); + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, - "The Fast classes are initialized!"); + "The Fast classes were initialized in " + timestamp + " ms"); + dbBackend.getAvailability().release(); } }); } @@ -245,8 +256,9 @@ private List convert2ArchivePersistenceObjects(final L return null; } - return comEntities.stream().map(entity -> entity == null ? null : convert2ArchivePersistenceObject(entity, - domain, entity.getObjectId())).collect(Collectors.toList()); + return comEntities.stream() + .map(entity -> entity == null ? null : convert2ArchivePersistenceObject(entity, domain, entity.getObjectId())) + .collect(Collectors.toList()); } private ArchivePersistenceObject convert2ArchivePersistenceObject(final COMObjectEntity comEntity, @@ -371,8 +383,7 @@ public void updateEntries(final ObjectType objType, final IdentifierList domain, } public void updateEntries(final ObjectType objType, final IdentifierList domain, - final ArchiveDetailsList lArchiveDetails, final ElementList objects, final MALInteraction interaction, - boolean generateEvents) { + final ArchiveDetailsList lArchiveDetails, final ElementList objects, final MALInteraction interaction, boolean generateEvents) { final int domainId = this.fastDomain.getDomainId(domain); final Integer objTypeId = this.fastObjectType.getObjectTypeId(objType); final ArrayList newObjs = new ArrayList<>(); @@ -440,8 +451,8 @@ public ArrayList query(final ObjectType objType, final return outs; } - public int deleteCOMObjectEntities(final ObjectType objType, final ArchiveQuery archiveQuery, - final QueryFilter filter) { + public int deleteCOMObjectEntities(final ObjectType objType, + final ArchiveQuery archiveQuery, final QueryFilter filter) { final IntegerList objTypeIds = this.fastObjectType.getObjectTypeIds(objType); if (null != objTypeIds && !objTypeIds.isEmpty()) { @@ -532,8 +543,8 @@ public ArrayList queryCOMObjectEntity(final ObjectTypeList objT } } - return this.dbProcessor.query(objTypeIds, archiveQuery, domainIds, providerURIId, networkId, sourceLink, - filter); + return this.dbProcessor.query(objTypeIds, archiveQuery, domainIds, + providerURIId, networkId, sourceLink, filter); } else { return new ArrayList<>(); } From a8ad39f16951137562ddb3ac45edc090f650afbf Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 11:57:55 +0200 Subject: [PATCH 105/173] Fixes the MP test --- .../test/java/esa/mo/mp/impl/com/TestCOMArchiveManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/mo-services-impl/ccsds-mp-impl/src/test/java/esa/mo/mp/impl/com/TestCOMArchiveManager.java b/core/mo-services-impl/ccsds-mp-impl/src/test/java/esa/mo/mp/impl/com/TestCOMArchiveManager.java index 79cfbb3e8..6e3fbd741 100644 --- a/core/mo-services-impl/ccsds-mp-impl/src/test/java/esa/mo/mp/impl/com/TestCOMArchiveManager.java +++ b/core/mo-services-impl/ccsds-mp-impl/src/test/java/esa/mo/mp/impl/com/TestCOMArchiveManager.java @@ -59,10 +59,8 @@ public static void setup() throws MALException { COMServicesProvider comServices = new COMServicesProvider(); comServices.init(); - ArchiveProviderServiceImpl archiveService = new ArchiveProviderServiceImpl(); - archiveService.init(null); + ArchiveProviderServiceImpl archiveService = comServices.getArchiveService(); archiveService.wipe(); - comServices.setArchiveService(archiveService); MPConfiguration configuration = new MPConfiguration(); archiveManager = new COMTestArchiveManager(comServices, configuration); From c8d7804059fb493bbfeeba26decee4246d0b2e90 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 12:04:59 +0200 Subject: [PATCH 106/173] [com-archive] Updates the backend startup and better logging for wipe() operation --- .../mo/com/impl/provider/ArchiveManager.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java index 6069493ea..3ff9c2b96 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java @@ -141,19 +141,15 @@ public synchronized void init() { Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, "Archive Backend started in " + timestamp + " ms! " + "Initializing Fast classes..."); - } - }); - this.dbProcessor.submitExternalTaskDBTransactions(() -> { - synchronized (manager) { - long timestamp = System.currentTimeMillis(); + long timestamp2 = System.currentTimeMillis(); fastDomain.init(); fastObjectType.init(); fastNetwork.init(); fastProviderURI.init(); - timestamp = System.currentTimeMillis() - timestamp; + timestamp2 = System.currentTimeMillis() - timestamp2; Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, - "The Fast classes were initialized in " + timestamp + " ms"); + "The Fast classes were initialized in " + timestamp2 + " ms"); dbBackend.getAvailability().release(); } }); @@ -195,9 +191,11 @@ public Void call() { * */ public synchronized void wipe() { - LOGGER.info("Reset table triggered!"); + LOGGER.info("(0) Reset table requested!"); this.dbProcessor.resetMainTable(() -> { + Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, + "(1) Starting to reset the table..."); try { dbBackend.getAvailability().acquire(); } catch (InterruptedException ex) { @@ -211,12 +209,18 @@ public synchronized void wipe() { Logger.getLogger(TransactionsProcessor.class.getName()).log(Level.SEVERE, null, ex); } + Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, + "(2) Reset done for the COM table! Reseting Fast classes..."); + fastObjId.resetFastIDs(); fastDomain.resetTable(); fastNetwork.resetTable(); fastProviderURI.resetTable(); dbBackend.getAvailability().release(); + Logger.getLogger(ArchiveManager.class.getName()).log(Level.INFO, + "(3) Reset done for all Fast classes!"); + return null; }); } From 8270612d25a6149b35531c1ff02c88a89a7322dc Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 13:07:59 +0200 Subject: [PATCH 107/173] [archive-sync] Code cleanup --- .../ArchiveSyncProviderServiceImpl.java | 182 ++++++++---------- 1 file changed, 78 insertions(+), 104 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java index cbe8e4510..da54ae059 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java @@ -30,6 +30,15 @@ import esa.mo.helpertools.connections.SingleConnectionDetails; import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.Const; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; import org.ccsds.moims.mo.com.COMHelper; import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; @@ -48,24 +57,12 @@ import org.ccsds.moims.mo.mal.structures.*; import org.ccsds.moims.mo.mal.transport.MALMessageHeader; -import java.io.IOException; -import java.net.MalformedURLException; -import java.text.MessageFormat; -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - /** * Archive Sync service Provider. */ public class ArchiveSyncProviderServiceImpl extends ArchiveSyncInheritanceSkeleton { - private static final Logger LOGGER = Logger.getLogger(ArchiveSyncProviderServiceImpl.class.getName()); - private static final String UNEXPECTED_EXCEPTION_0 = "Unexpected exception! {0}"; + private static final Logger LOGGER = Logger.getLogger(ArchiveSyncProviderServiceImpl.class.getName()); private static final long DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS = 600000L; //10 minutes @@ -107,40 +104,34 @@ public ArchiveSyncProviderServiceImpl(SingleConnectionDetails connectionToArchiv this(connectionToArchiveService, null, null); } - public ArchiveSyncProviderServiceImpl(SingleConnectionDetails connectionToArchiveService, Blob authenticationId, - String localNamePrefix) { + public ArchiveSyncProviderServiceImpl(SingleConnectionDetails connectionToArchiveService, + Blob authenticationId, String localNamePrefix) { this.latestSync = new FineTime(0); - try { - this.archive = new ArchiveConsumerServiceImpl(connectionToArchiveService, authenticationId, - localNamePrefix); - } catch (MALException | MalformedURLException ex) - { - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + try { + this.archive + = new ArchiveConsumerServiceImpl(connectionToArchiveService, authenticationId, localNamePrefix); + } catch (MALException | MalformedURLException ex) { + LOGGER.log(Level.SEVERE, "", ex); } timerName = getTimerName(); - dispatchersCleanupTimer = new Timer(timerName); - - String msg = MessageFormat.format("Dispatchers cleanup timer created {0}", timerName); - LOGGER.log(Level.FINE, msg); + LOGGER.log(Level.FINE, "Dispatchers cleanup timer created " + timerName); try { - objectsLimit = Integer.parseInt(System.getProperty(Const.ARCHIVESYNC_OBJECTS_LIMIT_PROPERTY, - Const.ARCHIVESYNC_OBJECTS_LIMIT_DEFAULT)); - msg = MessageFormat.format("{0} = {1}", Const.ARCHIVESYNC_OBJECTS_LIMIT_PROPERTY, objectsLimit); - LOGGER.log(Level.FINE, msg); + objectsLimit = Integer.parseInt(System.getProperty(Const.ARCHIVESYNC_OBJECTS_LIMIT_PROPERTY, Const.ARCHIVESYNC_OBJECTS_LIMIT_DEFAULT)); + LOGGER.log(Level.FINE, "The object limits is: " + objectsLimit); if (objectsLimit >= 90000) { - msg = "Using a large objects limit may cause the archive sync to fail due to too long data transfer. " + - "Consider changing the limit to a smaller amount"; + String msg = "Using a large objects limit may cause the archive sync to fail due to too long data transfer. " + + "Consider changing the limit to a smaller amount"; LOGGER.log(Level.WARNING, msg); } } catch (NumberFormatException ex) { objectsLimit = 30000; - msg = MessageFormat.format("Error when parsing {0} property. Using the default value of 30000", - Const.ARCHIVESYNC_OBJECTS_LIMIT_PROPERTY); + String msg = "Error when parsing " + Const.ARCHIVESYNC_OBJECTS_LIMIT_PROPERTY + + " property. Using the default value of 30000"; LOGGER.log(Level.WARNING, msg); } } @@ -150,17 +141,19 @@ private static synchronized String getTimerName() { } /** - * Set the quota. Should only be used when STD limits are used for the archive. + * Set the quota. Should only be used when STD limits are used for the + * archive. * - * @param quota The same Quota object that is passed to the AppsLauncherProviderServiceImpl using its setStdPerApp - * method. + * @param quota The same Quota object that is passed to the + * AppsLauncherProviderServiceImpl using its setStdPerApp method. */ public void setStdQuota(Quota quota) { this.stdQuota = quota; } /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread * * @param manager the Archive Manager * @throws MALException if initialization error. @@ -175,8 +168,8 @@ public synchronized void init(ArchiveManager manager) throws MALException { COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION).getServiceByName( - ArchiveSyncHelper.ARCHIVESYNC_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) + .getServiceByName(ArchiveSyncHelper.ARCHIVESYNC_SERVICE_NAME) == null) { ArchiveSyncHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -189,7 +182,7 @@ public synchronized void init(ArchiveManager manager) throws MALException { } archiveSyncServiceProvider = connection.startService(ArchiveSyncHelper.ARCHIVESYNC_SERVICE_NAME.toString(), - ArchiveSyncHelper.ARCHIVESYNC_SERVICE, false, this); + ArchiveSyncHelper.ARCHIVESYNC_SERVICE, false, this); initialiased = true; LOGGER.info("ArchiveSync service READY"); } @@ -200,11 +193,9 @@ public synchronized void init(ArchiveManager manager) throws MALException { public void close() { try { dispatchersCleanupTimer.cancel(); - dispatchersCleanupTimer = new Timer(timerName); - final String msg = MessageFormat.format("Dispatchers cleanup timer re-created {0}", timerName); - + final String msg = "Dispatchers cleanup timer re-created " + timerName; LOGGER.log(Level.FINE, msg); if (null != archiveSyncServiceProvider) { @@ -212,11 +203,9 @@ public void close() { } manager.close(); - connection.closeAll(); } catch (MALException ex) { - LOGGER.log(Level.WARNING, MessageFormat.format("Exception during close down of the provider {0}", ex - .getMessage()), ex); + LOGGER.log(Level.WARNING, "Exception during close down of the provider!", ex); } } @@ -229,17 +218,17 @@ public GetTimeResponse getTime(final MALInteraction interaction) throws MALInter @Override public void retrieveRange(FineTime from, FineTime until, ObjectTypeList objectTypes, Identifier compression, - RetrieveRangeInteraction interaction) throws MALInteractionException, MALException { + RetrieveRangeInteraction interaction) throws MALInteractionException, MALException { final Dispatcher dispatcher = new Dispatcher(interaction, archive); long interactionTicket = interaction.getInteraction().getMessageHeader().getTransactionId(); dispatchers.put(interactionTicket, dispatcher); final TimerTask timerTask = new CleaningTimerTask(interactionTicket); timerTasks.put(interactionTicket, timerTask); dispatchersCleanupTimer.schedule(timerTask, DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS); - final String msg = MessageFormat.format( - "Dispatcher cleaning task created and scheduled in timer for transaction {0}, it will be triggered in {1} seconds.", - interactionTicket, DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS / 1000); - LOGGER.log(Level.FINE, msg); + + LOGGER.log(Level.FINE, "Dispatcher cleaning task created and scheduled in timer for transaction" + + interactionTicket + " , it will be triggered in " + + DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS / 1000 + " seconds."); interaction.sendAcknowledgement(interactionTicket); @@ -271,7 +260,8 @@ public void retrieveRange(FineTime from, FineTime until, ObjectTypeList objectTy @Override public void retrieveRangeAgain(final Long transactionTicket, final UIntegerList missingIndexes, - final RetrieveRangeAgainInteraction interaction) throws MALInteractionException, MALException { + final RetrieveRangeAgainInteraction interaction) + throws MALInteractionException, MALException { final Dispatcher dispatcher = dispatchers.get(transactionTicket); if (null == dispatcher) { @@ -281,10 +271,8 @@ public void retrieveRangeAgain(final Long transactionTicket, final UIntegerList TimerTask timerTask = timerTasks.get(transactionTicket); if (null == timerTask) { - final String msg = MessageFormat.format( - "Dispatcher cleaning timer task not found for transaction {0} ! Trying to continue...", - transactionTicket); - LOGGER.log(Level.WARNING, msg); + LOGGER.log(Level.WARNING, "Dispatcher cleaning timer task not found for " + + "transaction " + transactionTicket + " ! Trying to continue..."); } else { cleanTimerTask(transactionTicket, timerTask); } @@ -293,10 +281,9 @@ public void retrieveRangeAgain(final Long transactionTicket, final UIntegerList timerTasks.put(transactionTicket, timerTask); dispatchersCleanupTimer.schedule(timerTask, DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS); - final String msg = MessageFormat.format( - "Dispatcher cleaning task re-created and scheduled in timer for transaction {0}, it will be triggered in {1} seconds.", - transactionTicket, DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS / 1000); - LOGGER.log(Level.FINE, msg); + LOGGER.log(Level.FINE, "Dispatcher cleaning task re-created and scheduled in " + + "timer for transaction " + transactionTicket + ", it will be triggered in " + + DISPATCHERS_CLEANUP_INTERVAL_IN_MILISECONDS / 1000 + " seconds."); interaction.sendAcknowledgement(); @@ -312,7 +299,7 @@ public void retrieveRangeAgain(final Long transactionTicket, final UIntegerList interaction.sendUpdate(new Blob(chunk), new UInteger(i)); } } catch (IOException ex) { - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + LOGGER.log(Level.SEVERE, "", ex); } } else { for (UInteger missingIndex : missingIndexes) { @@ -329,14 +316,13 @@ private void cleanTimerTask(Long transactionTicket, TimerTask timerTask) { dispatchersCleanupTimer.purge(); timerTasks.remove(transactionTicket); - final String msg = MessageFormat.format("Dispatcher cleaning task for transaction {0} removed.", - transactionTicket); + final String msg = "Dispatcher cleaning task for transaction: " + transactionTicket; LOGGER.log(Level.FINE, msg); } @Override - public StringList getDictionary(IntegerList wordIds, MALInteraction interaction) throws MALInteractionException, - MALException { + public StringList getDictionary(IntegerList wordIds, MALInteraction interaction) + throws MALInteractionException, MALException { StringList output = new StringList(); for (Integer wordId : wordIds) { @@ -345,7 +331,7 @@ public StringList getDictionary(IntegerList wordIds, MALInteraction interaction) word = dictionary.getWord(wordId); } catch (Exception ex) { word = null; - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + LOGGER.log(Level.SEVERE, "The word was not found!", ex); } output.add(word); @@ -359,8 +345,8 @@ public void free(Long transactionTicket, MALInteraction interaction) throws MALI final Dispatcher dispatcher = dispatchers.get(transactionTicket); if (null == dispatcher) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, - "Can't find a dispatcher!")); + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, "Can't find a dispatcher!")); } final TimerTask timerTask = timerTasks.get(transactionTicket); @@ -374,21 +360,18 @@ public void free(Long transactionTicket, MALInteraction interaction) throws MALI Long lastSyncTime = syncTimes.get(transactionTicket); if (null == lastSyncTime) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, - "Can't find a last sync time!")); + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, "Can't find a last sync time!")); } lastSync.set(lastSyncTime); - - final String msg = MessageFormat.format("Last sync time for transaction {0} is set.", transactionTicket); - LOGGER.log(Level.FINE, msg); + LOGGER.log(Level.FINE, "Last sync time is set. For transaction : " + transactionTicket); } private void cleanDispatcher(Long transactionTicket, Dispatcher dispatcher) { dispatcher.clear(); dispatchers.remove(transactionTicket); - final String msg = MessageFormat.format("Dispatcher for transaction {0} removed.", transactionTicket); - LOGGER.log(Level.FINE, msg); + LOGGER.log(Level.FINE, "Dispatcher removed for transaction: " + transactionTicket); } private class CleaningTimerTask extends TimerTask { @@ -404,10 +387,7 @@ public CleaningTimerTask(Long transactionTicket) { */ @Override public void run() { - final String msg = MessageFormat.format("Dispatcher cleaning task for transaction {0} started.", - transactionTicket); - LOGGER.log(Level.FINE, msg); - + LOGGER.log(Level.FINE, "Dispatcher cleaning task started for transaction: " + transactionTicket); final Dispatcher dispatcher = dispatchers.get(this.transactionTicket); if (null != dispatcher) { @@ -415,14 +395,12 @@ public void run() { } cleanTimerTask(this.transactionTicket, this); - - final String msg1 = MessageFormat.format("Dispatcher cleaning task for transaction {0} ended.", - transactionTicket); - LOGGER.log(Level.FINE, msg1); + LOGGER.log(Level.FINE, "Dispatcher cleaning task ended for transaction: ", transactionTicket); } } private class Dispatcher { + private final RetrieveRangeInteraction interaction; // These chunks are already compressed! @@ -448,15 +426,14 @@ private class Dispatcher { try { this.chunkSize = Integer.parseInt(chunkSizeParam); } catch (NumberFormatException e) { - Logger.getLogger(Dispatcher.class.getName()).log(Level.WARNING, MessageFormat.format( - "Unexpected NumberFormatException on {0} ! {1}", Const.ARCHIVESYNC_CHUNK_SIZE_PROPERTY, e - .getMessage()), e); + Logger.getLogger(Dispatcher.class.getName()).log(Level.WARNING, + "Unexpected NumberFormatException on " + Const.ARCHIVESYNC_CHUNK_SIZE_PROPERTY, e); } - final String msg = MessageFormat.format("{0} = {1}", Const.ARCHIVESYNC_CHUNK_SIZE_PROPERTY, this.chunkSize); - Logger.getLogger(Dispatcher.class.getName()).log(Level.FINE, msg); + Logger.getLogger(Dispatcher.class.getName()).log(Level.FINE, + Const.ARCHIVESYNC_CHUNK_SIZE_PROPERTY + " = " + this.chunkSize); this.purgeArchive = Boolean.parseBoolean(System.getProperty(Const.ARCHIVESYNC_PURGE_ARCHIVE_PROPERTY, - Const.ARCHIVESYNC_PURGE_ARCHIVE_DEFAULT)); + Const.ARCHIVESYNC_PURGE_ARCHIVE_DEFAULT)); } private void clear() { @@ -500,17 +477,15 @@ public void flushData() { try { interaction.sendResponse(new UInteger(numberOfChunks)); } catch (MALInteractionException | MALException ex) { - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + LOGGER.log(Level.SEVERE, "Unexpected exception!", ex); } - final String msg = MessageFormat.format("Objects were successfully flushed! {0} chunks in total!", - numberOfChunks); - LOGGER.log(Level.INFO, msg); + LOGGER.log(Level.INFO, "Objects were successfully flushed! " + + numberOfChunks + "{0} chunks in total!"); // This block cleans up the archive after sync if the option is enabled if (purgeArchive) { - ArchiveQuery archiveQuery = new ArchiveQuery(null, null, null, 0L, null, new FineTime(0), latestSync, - null, null); + ArchiveQuery archiveQuery = new ArchiveQuery(null, null, null, 0L, null, new FineTime(0), latestSync, null, null); // Iterate over constant set of types to purge until the latest synchronised object for (ToDelete type : ToDelete.values()) { int removed = manager.deleteCOMObjectEntities(type.getType(), archiveQuery, null); @@ -524,7 +499,7 @@ public void sendUpdateToConsumer(int index, byte[] aChunk) { try { interaction.sendUpdate(new Blob(aChunk), new UInteger(index)); } catch (MALInteractionException | MALException ex) { - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + LOGGER.log(Level.SEVERE, "Unexpected exception!", ex); } } @@ -543,7 +518,7 @@ public ObjectsReceivedAdapter(ArchiveConsumerServiceImpl archive, ObjectType typ @Override public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { super.queryUpdateReceived(msgHeader, objType, domain, objDetails, objBodies, qosProperties); if (objDetails != null) { queryResults.addAll(objDetails); @@ -553,7 +528,7 @@ public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, @Override public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { super.queryResponseReceived(msgHeader, objType, domain, objDetails, objBodies, qosProperties); if (null == objType || null == domain || null == objDetails || null == objBodies) { return; @@ -563,10 +538,9 @@ public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType queryResults.addAll(objDetails); Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Received response!"); - if (objType.equals(ToDelete.STDERR_VALUE.getType()) || objType.equals(ToDelete.STDOUT_VALUE - .getType())) { - objDetails.stream().map(detail -> detail.getDetails().getSource().getKey().getInstId()).forEach( - x -> clearedIds.add(x)); + if (objType.equals(ToDelete.STDERR_VALUE.getType()) || objType.equals(ToDelete.STDOUT_VALUE.getType())) { + objDetails.stream().map(detail -> detail.getDetails().getSource().getKey().getInstId()) + .forEach(x -> clearedIds.add(x)); } List ids = queryResults.stream().map(detail -> detail.getInstId()).collect(Collectors.toList()); @@ -581,9 +555,9 @@ public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType stdQuota.clean(clearedIds); } } catch (MALInteractionException | MALException ex) { - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + LOGGER.log(Level.SEVERE, "Unexpected exception!", ex); } catch (InterruptedException ex) { - LOGGER.log(Level.SEVERE, MessageFormat.format(UNEXPECTED_EXCEPTION_0, ex.getMessage()), ex); + LOGGER.log(Level.SEVERE, "Unexpected exception!", ex); Thread.currentThread().interrupt(); } From ab03d885fb21fb1be73150da2bc33533d7acc790 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 13:41:39 +0200 Subject: [PATCH 108/173] Code cleanup --- .../NanoSatMOSupervisor.java | 165 +++++++----------- 1 file changed, 65 insertions(+), 100 deletions(-) diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index 579183611..ce4614607 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -64,6 +64,7 @@ * @author Cesar Coelho */ public abstract class NanoSatMOSupervisor extends NMFProvider { + private static final Logger LOGGER = Logger.getLogger(NanoSatMOSupervisor.class.getName()); private static final String PDU_CHANNEL_PARAMETER = "PDU1952"; private static final Duration PDU_CHANNEL_REPORTING_PERIOD = new Duration(10); @@ -157,48 +158,24 @@ public void run() { Level.INFO, "Done!"); } }); + + // Are the dynamic changes enabled? + if ("true".equals(System.getProperty(Const.DYNAMIC_CHANGES_PROPERTY))) { + LOGGER.log(Level.INFO, "Loading previous configurations..."); - final String primaryURI = this.directoryService.getConnection().getPrimaryConnectionDetails().getProviderURI() - .toString(); - - final SingleConnectionDetails det = this.directoryService.getConnection().getSecondaryConnectionDetails(); - final String secondaryURI = (det != null) ? det.getProviderURI().toString() : null; - this.writeCentralDirectoryServiceURI(primaryURI, secondaryURI); - LOGGER.log(Level.INFO, "NanoSat MO Supervisor initialized in " + (((float) (System.currentTimeMillis() - - super.startTime)) / 1000) + " seconds!"); - LOGGER.log(Level.INFO, "URI: {0}\n", primaryURI); - - //Once all services are loaded and configured, enable status parameter and subscribe to it - Identifier identifier = new Identifier(PDU_CHANNEL_PARAMETER); - IdentifierList identifierList = new IdentifierList(); - identifierList.add(identifier); - ParameterDefinitionDetails details = new ParameterDefinitionDetails("PowerStatusChecks", Union.USHORT_SHORT_FORM - .byteValue(), "N/A", true, PDU_CHANNEL_REPORTING_PERIOD, null, null); - - ParameterCreationRequest request = new ParameterCreationRequest(identifier, details); - ParameterCreationRequestList reqList = new ParameterCreationRequestList(); - reqList.add(request); - try { - ObjectInstancePairList objInstPairList = mcServices.getParameterService().addParameter(reqList, null); - // check that the parameter was added successfully - if (objInstPairList.isEmpty() || objInstPairList.get(0).getObjIdentityInstanceId() == null) { - LOGGER.log(Level.SEVERE, "Error creating request with parameter to fetch in the supervisor"); - } - } catch (MALException e) { - LOGGER.log(Level.SEVERE, "Error creating request with parameter to fetch in the supervisor", e); - } catch (MALInteractionException e) { - if (e.getStandardError().getErrorNumber() == COMHelper.DUPLICATE_ERROR_NUMBER) { - // Parameter already exists - ignore it - } else { - LOGGER.log(Level.SEVERE, "Error creating request with parameter to fetch in the supervisor", e); - } - } - this.startStatusTracking(); - } + // Activate the previous configuration + final ObjectId confId = new ObjectId(ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, + new ObjectKey(ConfigurationProviderSingleton.getDomain(), + DEFAULT_PROVIDER_CONFIGURATION_OBJID)); - @Override - public void init(MissionPlanningNMFAdapter mpAdapter) { - // Not implemented. MP services are accessible only from connector. + super.providerConfiguration = new PersistProviderConfiguration(this, confId, + comServices.getArchiveService()); + + try { + super.providerConfiguration.loadPreviousConfigurations(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } } @Override @@ -206,64 +183,52 @@ public void setCloseAppListener(final CloseAppListener closeAppAdapter) { this.closeAppAdapter = closeAppAdapter; } - /** - * It closes the App gracefully. - * - * @param source The source of the triggering. Can be null - */ - @Override - public final void closeGracefully(final ObjectId source) { - try { - AppShutdownGuard.start(); - long timestamp = System.currentTimeMillis(); - - // Acknowledge the reception of the request to close (Closing...) - Long eventId = this.getCOMServices().getEventService().generateAndStoreEvent( - AppsLauncherHelper.STOPPING_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), null, null, source, - null); - - final URI uri = this.getCOMServices().getEventService().getConnectionProvider().getConnectionDetails() - .getProviderURI(); - - try { - this.getCOMServices().getEventService().publishEvent(uri, eventId, - AppsLauncherHelper.STOPPING_OBJECT_TYPE, null, source, null); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - - // Close the app... - // Make a call on the app layer to close nicely... - if (this.closeAppAdapter != null) { - LOGGER.log(Level.INFO, "Triggering the closeAppAdapter of the app business logic..."); - this.closeAppAdapter.onClose(); // Time to sleep, boy! - } - - Long eventId2 = this.getCOMServices().getEventService().generateAndStoreEvent( - AppsLauncherHelper.STOPPED_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), null, null, source, - null); - - try { - this.getCOMServices().getEventService().publishEvent(uri, eventId2, - AppsLauncherHelper.STOPPED_OBJECT_TYPE, null, source, null); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - - // Should close them safely as well... - // provider.getMCServices().closeServices(); - // provider.getCOMServices().closeServices(); - this.getCOMServices().closeAll(); - - // Exit the Java application - LOGGER.log(Level.INFO, "Success! The currently running Java Virtual Machine will now terminate. " + - "(NanoSat MO Supervisor closed in: " + (System.currentTimeMillis() - timestamp) + " ms)\n"); - - } catch (NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - - System.exit(0); + // Populate the Directory service with the entries from the URIs File + LOGGER.log(Level.INFO, "Populating Directory service..."); + directoryService.loadURIs(Const.NANOSAT_MO_SUPERVISOR_NAME); + + String primaryURI + = directoryService.getConnection().getPrimaryConnectionDetails().getProviderURI().toString(); + + SingleConnectionDetails det + = directoryService.getConnection().getSecondaryConnectionDetails(); + String secondaryURI = (det != null) ? det.getProviderURI().toString() : null; + writeCentralDirectoryServiceURI(primaryURI, secondaryURI); + + LOGGER.log(Level.INFO, "NanoSat MO Supervisor initialized in " + + (((float) (System.currentTimeMillis() - super.startTime)) / 1000) + + " seconds!"); + LOGGER.log(Level.INFO, "URI: {0}\n", primaryURI); + + //Once all services are loaded and configured, enable status parameter and subscribe to it + Identifier identifier = new Identifier(PDU_CHANNEL_PARAMETER); + IdentifierList identifierList = new IdentifierList(); + identifierList.add(identifier); + ParameterDefinitionDetails details = new ParameterDefinitionDetails("PowerStatusChecks", + Union.USHORT_SHORT_FORM.byteValue(), "N/A", true, PDU_CHANNEL_REPORTING_PERIOD, + null, null); + + ParameterCreationRequest request = new ParameterCreationRequest(identifier, details); + ParameterCreationRequestList reqList = new ParameterCreationRequestList(); + reqList.add(request); + try { + ObjectInstancePairList objInstPairList = mcServices.getParameterService().addParameter(reqList, null); + // check that the parameter was added successfully + if (objInstPairList.size() < 0 + || objInstPairList.get(0).getObjIdentityInstanceId() == null) { + LOGGER.log(Level.SEVERE, + "Error creating request with parameter to fetch in the supervisor"); + } + } catch (MALException e) { + LOGGER.log(Level.SEVERE, + "Error creating request with parameter to fetch in the supervisor", e); + } catch (MALInteractionException e) { + if (e.getStandardError().getErrorNumber() == COMHelper.DUPLICATE_ERROR_NUMBER) { + // Parameter already exists - ignore it + } else { + LOGGER.log(Level.SEVERE, + "Error creating request with parameter to fetch in the supervisor", e); + } } } @@ -340,10 +305,10 @@ public final void closeGracefully(final ObjectId source) { this.getCOMServices().closeAll(); // Exit the Java application + long duration = System.currentTimeMillis() - timestamp; LOGGER.log(Level.INFO, "Success! The currently running Java Virtual Machine will now terminate. " - + "(NanoSat MO Supervisor closed in: " + (System.currentTimeMillis() - timestamp) + " ms)\n"); - + + "(NanoSat MO Supervisor closed in: " + duration + " ms)\n"); } catch (NMFException ex) { LOGGER.log(Level.SEVERE, null, ex); } From 2be6b1a0c3d6e7353aa15442a091bbd48b58e9ca Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 18:20:30 +0200 Subject: [PATCH 109/173] Code cleanup --- .../AggregationProviderServiceImpl.java | 2 + .../ParameterProviderServiceImpl.java | 2 + .../provider/adapters/AIMovidiusAdapter.java | 8 ++-- .../HeartbeatProviderServiceImpl.java | 15 +++---- .../NanoSatMOConnectorImpl.java | 5 ++- .../NanoSatMOSupervisor.java | 39 +---------------- .../NanosatMOSupervisorBasicImpl.java | 43 +++++++++++++++++++ 7 files changed, 61 insertions(+), 53 deletions(-) diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java index bbe5e5a21..c4c89ed91 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java @@ -161,9 +161,11 @@ public synchronized void init(COMServicesProvider comServices, ParameterManager periodicReportingManager.init(); // Initialize the Periodic Reporting Manager periodicSamplingManager.init(); // Initialize the Periodic Sampling Manager + /* storeAggregationsInCOMArchive = Boolean.parseBoolean(System.getProperty(MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, "true")); String msg = MessageFormat.format("{0} = {1}", MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, storeAggregationsInCOMArchive); Logger.getLogger(AggregationProviderServiceImpl.class.getName()).log(Level.FINE, msg); + */ initialiased = true; Logger.getLogger(AggregationProviderServiceImpl.class.getName()).info("Aggregation service READY"); diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java index 185e21e8c..02a1e93c4 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java @@ -163,9 +163,11 @@ public synchronized void init(ParameterManager parameterManager) throws MALExcep groupService.init(manager.getArchiveService()); + /* storeParametersInCOMArchive = Boolean.parseBoolean(System.getProperty(MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, "true")); String msg = MessageFormat.format("{0} = {1}", MCServicesHelper.STORE_IN_ARCHIVE_PROPERTY, storeParametersInCOMArchive); Logger.getLogger(ParameterProviderServiceImpl.class.getName()).log(Level.FINE, msg); + */ initialiased = true; Logger.getLogger(ParameterProviderServiceImpl.class.getName()).info("Parameter service READY"); diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index 371bedbee..f3ab9f46f 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -148,7 +148,8 @@ private String generateScriptBAT(String pathIntelVar, String pythonFile) { return str.toString(); } - private String buildPythonCommand(String modelXml, String modelBin, String inputTiles, String outputTiles) { + private String buildPythonCommand(String modelXml, String modelBin, + String inputTiles, String outputTiles) { StringBuilder str = new StringBuilder(); str.append("python3 ").append(PYTHON_FILENAME); str.append(" --model_xml ").append(modelXml); @@ -210,8 +211,7 @@ public void executeInference(String modelPath, String weightsPath, StringBuilder buffer = new StringBuilder(); String line; while ((line = br.readLine()) != null) { - buffer.append(line); - buffer.append("\n"); + buffer.append(line).append("\n"); } String message = buffer.toString(); @@ -232,6 +232,6 @@ public void executeInference(String modelPath, String weightsPath, @Override public void doComputerVision(String jsonPath) throws IOException { throw new UnsupportedOperationException("The operation needs to be " - + "extended for AI specific applications that do Computer Vision!"); + + "extended for specific AI applications that do Computer Vision!"); } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java index c7d4fb425..cba1408fb 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java @@ -63,7 +63,6 @@ public class HeartbeatProviderServiceImpl extends HeartbeatInheritanceSkeleton { private BeatPublisher publisher; private boolean initialiased = false; private boolean isRegistered = false; - private final Object lock = new Object(); private boolean running = false; private final ConnectionProvider connection = new ConnectionProvider(); private Timer timer; @@ -143,15 +142,13 @@ public void close() { } } - private void publishHeartbeat() { + private synchronized void publishHeartbeat() { try { - synchronized (lock) { - if (!isRegistered) { - final EntityKeyList lst = new EntityKeyList(); - lst.add(new EntityKey(new Identifier("*"), 0L, 0L, 0L)); - publisher.register(lst, new PublishInteractionListener()); - isRegistered = true; - } + if (!isRegistered) { + final EntityKeyList lst = new EntityKeyList(); + lst.add(new EntityKey(new Identifier("*"), 0L, 0L, 0L)); + publisher.register(lst, new PublishInteractionListener()); + isRegistered = true; } final UpdateHeaderList hdrlst = new UpdateHeaderList(1); diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 030654049..71bde7da6 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -306,8 +306,9 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { mcAdapter.restoreParameterValuesFromArchive(); } - LOGGER.log(Level.INFO, "NanoSat MO Connector initialized in " + (((float) (System.currentTimeMillis() - - super.startTime)) / 1000) + " seconds!"); + LOGGER.log(Level.INFO, "NanoSat MO Connector initialized in " + + (((float) (System.currentTimeMillis() - super.startTime)) / 1000) + + " seconds!"); final String uri = directoryService.getConnection().getPrimaryConnectionDetails().getProviderURI().toString(); LOGGER.log(Level.INFO, "URI: {0}\n", uri); diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index ce4614607..e2be627a3 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -43,17 +43,12 @@ import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; -import org.ccsds.moims.mo.com.COMHelper; import org.ccsds.moims.mo.com.structures.ObjectId; import org.ccsds.moims.mo.com.structures.ObjectKey; import org.ccsds.moims.mo.common.configuration.ConfigurationHelper; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; import org.ccsds.moims.mo.mal.structures.*; -import org.ccsds.moims.mo.mc.parameter.structures.ParameterCreationRequest; -import org.ccsds.moims.mo.mc.parameter.structures.ParameterCreationRequestList; -import org.ccsds.moims.mo.mc.parameter.structures.ParameterDefinitionDetails; -import org.ccsds.moims.mo.mc.structures.ObjectInstancePairList; import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; @@ -66,8 +61,7 @@ public abstract class NanoSatMOSupervisor extends NMFProvider { private static final Logger LOGGER = Logger.getLogger(NanoSatMOSupervisor.class.getName()); - private static final String PDU_CHANNEL_PARAMETER = "PDU1952"; - private static final Duration PDU_CHANNEL_REPORTING_PERIOD = new Duration(10); + private final PackageManagementProviderServiceImpl packageManagementService = new PackageManagementProviderServiceImpl(); private final AppsLauncherProviderServiceImpl appsLauncherService @@ -199,37 +193,6 @@ public void setCloseAppListener(final CloseAppListener closeAppAdapter) { + (((float) (System.currentTimeMillis() - super.startTime)) / 1000) + " seconds!"); LOGGER.log(Level.INFO, "URI: {0}\n", primaryURI); - - //Once all services are loaded and configured, enable status parameter and subscribe to it - Identifier identifier = new Identifier(PDU_CHANNEL_PARAMETER); - IdentifierList identifierList = new IdentifierList(); - identifierList.add(identifier); - ParameterDefinitionDetails details = new ParameterDefinitionDetails("PowerStatusChecks", - Union.USHORT_SHORT_FORM.byteValue(), "N/A", true, PDU_CHANNEL_REPORTING_PERIOD, - null, null); - - ParameterCreationRequest request = new ParameterCreationRequest(identifier, details); - ParameterCreationRequestList reqList = new ParameterCreationRequestList(); - reqList.add(request); - try { - ObjectInstancePairList objInstPairList = mcServices.getParameterService().addParameter(reqList, null); - // check that the parameter was added successfully - if (objInstPairList.size() < 0 - || objInstPairList.get(0).getObjIdentityInstanceId() == null) { - LOGGER.log(Level.SEVERE, - "Error creating request with parameter to fetch in the supervisor"); - } - } catch (MALException e) { - LOGGER.log(Level.SEVERE, - "Error creating request with parameter to fetch in the supervisor", e); - } catch (MALInteractionException e) { - if (e.getStandardError().getErrorNumber() == COMHelper.DUPLICATE_ERROR_NUMBER) { - // Parameter already exists - ignore it - } else { - LOGGER.log(Level.SEVERE, - "Error creating request with parameter to fetch in the supervisor", e); - } - } } public AppsLauncherProviderServiceImpl getAppsLauncherService() { diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java index 55a83457e..becc4cf25 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanosatMOSupervisorBasicImpl.java @@ -31,7 +31,17 @@ import esa.mo.platform.impl.util.PlatformServicesProviderSoftSim; import java.util.logging.Level; import java.util.logging.Logger; +import org.ccsds.moims.mo.com.COMHelper; import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.structures.Duration; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.Union; +import org.ccsds.moims.mo.mc.parameter.structures.ParameterCreationRequest; +import org.ccsds.moims.mo.mc.parameter.structures.ParameterCreationRequestList; +import org.ccsds.moims.mo.mc.parameter.structures.ParameterDefinitionDetails; +import org.ccsds.moims.mo.mc.structures.ObjectInstancePairList; /** * This is a specific implementation of the NMF supervisor which is currently @@ -45,6 +55,8 @@ public class NanosatMOSupervisorBasicImpl extends NanoSatMOSupervisor { private static final Logger LOGGER = Logger.getLogger(NanosatMOSupervisorBasicImpl.class.getName()); + private static final String PDU_CHANNEL_PARAMETER = "PDU1952"; + private static final Duration PDU_CHANNEL_REPORTING_PERIOD = new Duration(10); private PlatformServicesProviderInterface platformServicesProvider; private ConnectionConsumer connectionConsumer; @@ -89,6 +101,37 @@ public void init(MonitorAndControlNMFAdapter mcAdapter) { new NMFPackagePMBackend("packages", this.getAppsLauncherService()) ); + //Once all services are loaded and configured, enable status parameter and subscribe to it + Identifier identifier = new Identifier(PDU_CHANNEL_PARAMETER); + IdentifierList identifierList = new IdentifierList(); + identifierList.add(identifier); + ParameterDefinitionDetails details = new ParameterDefinitionDetails("PowerStatusChecks", + Union.USHORT_SHORT_FORM.byteValue(), "N/A", true, PDU_CHANNEL_REPORTING_PERIOD, + null, null); + + ParameterCreationRequest request = new ParameterCreationRequest(identifier, details); + ParameterCreationRequestList reqList = new ParameterCreationRequestList(); + reqList.add(request); + try { + ObjectInstancePairList objInstPairList = mcServices.getParameterService().addParameter(reqList, null); + // check that the parameter was added successfully + if (objInstPairList.size() < 0 + || objInstPairList.get(0).getObjIdentityInstanceId() == null) { + LOGGER.log(Level.SEVERE, + "Error creating request with parameter to fetch in the supervisor"); + } + } catch (MALException e) { + LOGGER.log(Level.SEVERE, + "Error creating request with parameter to fetch in the supervisor", e); + } catch (MALInteractionException e) { + if (e.getStandardError().getErrorNumber() == COMHelper.DUPLICATE_ERROR_NUMBER) { + // Parameter already exists - ignore it + } else { + LOGGER.log(Level.SEVERE, + "Error creating request with parameter to fetch in the supervisor", e); + } + } + this.startStatusTracking(); } From 29fbc8cf150f273e8b853e1c3144d5e12035c5c3 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 19:38:14 +0200 Subject: [PATCH 110/173] [ai-service] Adds the frontend interface operation doComputerVision --- ...ficialIntelligenceProviderServiceImpl.java | 42 +++++++++++++++++++ .../main/resources/xml/ServiceDefPLATFORM.xml | 34 +++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index 8d58fc0a4..f85067a4c 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -39,7 +39,14 @@ import java.util.ArrayList; import java.util.Date; import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.platform.artificialintelligence.provider.DoComputerVisionInteraction; +/** + * The ArtificialIntelligenceProviderServiceImpl class has the implementation of + * the AI service. + * + * @author Cesar Coelho + */ public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelligenceInheritanceSkeleton { private static final Logger LOGGER = Logger.getLogger(ArtificialIntelligenceProviderServiceImpl.class.getName()); @@ -183,4 +190,39 @@ public String doInference(Long modelId, String inputTilesPath, throw new MALException("The inference could not be performed!"); } + + @Override + public void doComputerVision(String jsonPath, DoComputerVisionInteraction interaction) throws MALInteractionException, MALException { + if (jsonPath == null) { + throw new MALException("The jsonPath cannot be null!"); + } + + if (!jsonPath.endsWith(".json")) { + throw new MALException("The file does not end with the file extension: .json"); + } + + File path = new File(jsonPath); + + if (!path.exists()) { + String msg = "The file does not exist in path: " + path; + throw new MALInteractionException( + new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, msg) + ); + } + + if (interaction != null) { + interaction.sendAcknowledgement(); + } + + boolean success = true; + try { + adapter.doComputerVision(jsonPath); + } catch (IOException ex) { + success = false; + } + + if (interaction != null) { + interaction.sendResponse(success); + } + } } diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index 9bea9a3d7..8473a70cc 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2225,14 +2225,12 @@ comment="The modelId field holds the id of the model to be used for inference." name="modelId"> - + - + @@ -2244,6 +2242,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 3d370e5360bf30e3899941a2c4e25415f1a415b3 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 22:10:30 +0200 Subject: [PATCH 111/173] [nmf-package] Adds Apps installation support for Windows --- .../nmfpackage/utils/HelperNMFPackage.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 28e765045..fea9acd96 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -127,7 +127,29 @@ public static String generateLinuxStartAppScript(String javaCommand, public static String generateWindowsStartAppScript(String javaCommand, String jarFilename, MetadataApp meta) throws IOException { - return "To be done..."; + StringBuilder str = new StringBuilder(); + str.append("@echo off\n\n"); + str.append(":: Java Runtime Environment:\n"); + str.append("set JAVA_CMD=").append(javaCommand).append("\n\n"); + + str.append(":: App-related constants:\n"); + str.append("set MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); + str.append("set MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); + str.append("set MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); + + str.append(":: Jars from: App, NMF, and Shared dependencies:\n"); + str.append("set JAR_APP=").append(jarFilename).append("\n"); + + str.append("set BASEDIR=%~dp0\\..\\..\\..").append("\n"); + str.append("set JARS_NMF=").append("%BASEDIR%\\lib\\*").append("\n"); + + str.append("\n\nset JARS_ALL=\"%JAR_APP%;%JARS_NMF%\""); + str.append("\n\n"); + + str.append("%JAVA_CMD% %JAVA_OPTS% -classpath %JARS_ALL%"); + str.append(" -Dapp.name=\"").append(meta.getPackageName()); + str.append("\" ").append(meta.getAppMainclass()); + return str.toString(); } public static String generateProviderProperties(String runAs) throws IOException { From dd58e55750b6f5ce18b41cf214bbbfe91b8b2288 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 26 Oct 2022 23:14:30 +0200 Subject: [PATCH 112/173] Adds a default value for the DummyValuesProvider class --- .../nanosat-mo-supervisor/.gitignore | 2 + .../parameter/OBSWParameterManager.java | 89 ++++++++++--------- 2 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 core/nmf-composites/nanosat-mo-supervisor/.gitignore diff --git a/core/nmf-composites/nanosat-mo-supervisor/.gitignore b/core/nmf-composites/nanosat-mo-supervisor/.gitignore new file mode 100644 index 000000000..9cf1fe8f9 --- /dev/null +++ b/core/nmf-composites/nanosat-mo-supervisor/.gitignore @@ -0,0 +1,2 @@ +_OPS-SAT-* +platformsim.properties \ No newline at end of file diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java index d0a4be39a..2d7451086 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java @@ -50,49 +50,52 @@ * @author Tanguy Soto */ public class OBSWParameterManager { - /** - * The logger - */ - private static final Logger LOGGER = Logger.getLogger(OBSWParameterManager.class.getName()); - - /** - * Default OBSW parameter report interval (seconds) - */ - private static final int DEFAULT_REPORT_INTERVAL = 5; - - /** - * Helper to read the OBSW parameter from datapool. - */ - private final ParameterLister parameterLister; - - /** - * Maps each parameter proxy (object instance id of the ParameterIdentity in the supervisor) to - * the OBSW parameter it represents. - */ - private Map proxyIdsToOBSWParams; - - /** - * Provides the OBSW parameter values - */ - private OBSWParameterValuesProvider valuesProvider; - - public OBSWParameterManager(InputStream datapool) throws IOException, JAXBException, XMLStreamException { - // Read from provided inputstreams - parameterLister = new ParameterLister(datapool); - - // Initialize the parameters proxies to OBSW parameter maps - proxyIdsToOBSWParams = new HashMap<>(); - - // Instantiate the value provider - HashMap parameterMap = parameterLister.getParameters(); - String valuesProviderClass = System.getProperty("nmf.supervisor.parameter.valuesprovider.impl"); - try { - Constructor c = Class.forName(valuesProviderClass).getConstructor(parameterMap.getClass()); - valuesProvider = (OBSWParameterValuesProvider) c.newInstance(new Object[]{parameterMap}); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, "Error initializing the values provider. Using dummy values provider.", e); - valuesProvider = new DummyValuesProvider(parameterMap); - } + /** + * The logger + */ + private static final Logger LOGGER = Logger.getLogger(OBSWParameterManager.class.getName()); + + /** + * Default OBSW parameter report interval (seconds) + */ + private static final int DEFAULT_REPORT_INTERVAL = 5; + + /** + * Helper to read the OBSW parameter from datapool. + */ + private final ParameterLister parameterLister; + + /** + * Maps each parameter proxy (object instance id of the ParameterIdentity in the supervisor) to + * the OBSW parameter it represents. + */ + private Map proxyIdsToOBSWParams; + + /** + * Provides the OBSW parameter values + */ + private OBSWParameterValuesProvider valuesProvider; + + public OBSWParameterManager(InputStream datapool) + throws IOException, JAXBException, XMLStreamException { + // Read from provided inputstreams + parameterLister = new ParameterLister(datapool); + + // Initialize the parameters proxies to OBSW parameter maps + proxyIdsToOBSWParams = new HashMap<>(); + + // Instantiate the value provider + HashMap parameterMap = parameterLister.getParameters(); + String defaultClass = "esa.mo.nmf.nanosatmosupervisor.parameter.DummyValuesProvider"; + String valuesProviderClass = System.getProperty("nmf.supervisor.parameter.valuesprovider.impl", defaultClass); + + try { + Constructor c = Class.forName(valuesProviderClass).getConstructor(parameterMap.getClass()); + valuesProvider = (OBSWParameterValuesProvider) c.newInstance(new Object[] {parameterMap}); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, + "Error initializing the values provider. Using dummy values provider.", e); + valuesProvider = new DummyValuesProvider(parameterMap); } /** From 9dbec270e18dcc26b926ad24f1687de6fc6520f8 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 27 Oct 2022 15:29:07 +0200 Subject: [PATCH 113/173] [ai-service] Disables the checking of the setupvars.sh for testng purposes --- .../mo/platform/impl/provider/adapters/AIMovidiusAdapter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index f3ab9f46f..866b09da2 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -76,7 +76,8 @@ public AIMovidiusAdapter() throws IOException { "/opt/intel" }; - setupVarsPath = this.crawlOptions(options, "setupvars.sh"); + //setupVarsPath = this.crawlOptions(options, "setupvars.sh"); + setupVarsPath = new File(""); // Temporary hardcoding it to avoid problems return; } From ab18f2851d5acded25105cc8866d323c5340c73f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 27 Oct 2022 16:55:58 +0200 Subject: [PATCH 114/173] [ai-service] Better handling when the setupvars.sh file is not found --- .../impl/provider/adapters/AIMovidiusAdapter.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index 866b09da2..feaa53513 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -76,8 +76,15 @@ public AIMovidiusAdapter() throws IOException { "/opt/intel" }; - //setupVarsPath = this.crawlOptions(options, "setupvars.sh"); - setupVarsPath = new File(""); // Temporary hardcoding it to avoid problems + File file; + try{ + file = this.crawlOptions(options, "setupvars.sh"); + }catch(IOException ex){ + LOGGER.log(Level.WARNING, "The setupvars.sh was not found!"); + file = new File(""); + } + + setupVarsPath = file; return; } @@ -91,8 +98,6 @@ public AIMovidiusAdapter() throws IOException { }; setupVarsPath = this.crawlOptions(options, "setupvars.bat"); - - // Please install version: 2020.2 return; } From 1647700aa8cc8ce7755e0e03c7623b9e73a927c4 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 28 Oct 2022 11:43:18 +0200 Subject: [PATCH 115/173] Refactors the GPS service to remove dependencies to Orekit on the generic implementation --- .../nmf-platform-generic-impl/pom.xml | 5 - .../provider/gen/GPSAdapterInterface.java | 10 +- .../impl/provider/gen/GPSNMEAonlyAdapter.java | 1 - .../provider/gen/GPSProviderServiceImpl.java | 423 ++++++++++-------- .../nmfpackage/utils/HelperNMFPackage.java | 3 +- .../simulator/platform-services-impl/pom.xml | 5 + .../GPSProviderServiceWithTLEImpl.java | 263 +++++++++++ .../provider/softsim/GPSSoftSimAdapter.java | 10 +- .../util/PlatformServicesProviderSoftSim.java | 14 +- 9 files changed, 509 insertions(+), 225 deletions(-) create mode 100644 mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java diff --git a/core/mo-services-impl/nmf-platform-generic-impl/pom.xml b/core/mo-services-impl/nmf-platform-generic-impl/pom.xml index e23bf1495..8addec315 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/pom.xml +++ b/core/mo-services-impl/nmf-platform-generic-impl/pom.xml @@ -64,11 +64,6 @@ int.esa.nmf.core.moservices.impl ccsds-com - - int.esa.nmf.sdk - orekit-resources - ${project.version} - junit junit diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSAdapterInterface.java index 3372bfac2..e5e09093c 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSAdapterInterface.java @@ -24,9 +24,9 @@ import org.ccsds.moims.mo.platform.gps.structures.Position; import org.ccsds.moims.mo.platform.gps.structures.SatelliteInfoList; -import org.orekit.propagation.analytical.tle.TLE; /** + * The GPS interface for adapters. * * @author Cesar Coelho */ @@ -62,14 +62,6 @@ public interface GPSAdapterInterface { */ SatelliteInfoList getSatelliteInfoList(); - /** - * Requests the current two line element set - * - * @return The current two line element set - * @throws IOException if TLE can't be read - */ - TLE getTLE(); - /** * Requests the BESTXYZ NMEA sentence * diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java index bdff893bb..2a8a7e268 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSNMEAonlyAdapter.java @@ -21,7 +21,6 @@ package esa.mo.platform.impl.provider.gen; import esa.mo.helpertools.misc.Const; -import esa.mo.platform.impl.provider.gen.GPSAdapterInterface; import esa.mo.platform.impl.util.HelperGPS; import java.io.IOException; import java.util.logging.Level; diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java index 39b824580..458c735ee 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java @@ -26,9 +26,7 @@ import esa.mo.helpertools.connections.ConnectionProvider; import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.helpers.HelperTime; -import esa.mo.helpertools.misc.Const; import esa.mo.helpertools.misc.TaskScheduler; -import esa.mo.nmf.sdk.OrekitResources; import esa.mo.platform.impl.util.HelperGPS; import esa.mo.platform.impl.util.PositionsCalculator; import esa.mo.reconfigurable.service.ConfigurationChangeListener; @@ -87,84 +85,74 @@ import org.ccsds.moims.mo.platform.gps.structures.*; import org.ccsds.moims.mo.platform.structures.VectorD3D; import org.ccsds.moims.mo.platform.structures.VectorF3D; -import org.hipparchus.geometry.euclidean.threed.Vector3D; -import org.hipparchus.util.FastMath; -import org.orekit.bodies.GeodeticPoint; -import org.orekit.bodies.OneAxisEllipsoid; -import org.orekit.data.DataProvidersManager; -import org.orekit.frames.Frame; -import org.orekit.frames.FramesFactory; -import org.orekit.propagation.SpacecraftState; -import org.orekit.propagation.analytical.tle.TLE; -import org.orekit.propagation.analytical.tle.TLEPropagator; -import org.orekit.time.AbsoluteDate; -import org.orekit.time.TimeScalesFactory; -import org.orekit.utils.Constants; -import org.orekit.utils.IERSConventions; /** * GPS service Provider. */ -public class GPSProviderServiceImpl extends GPSInheritanceSkeleton implements ReconfigurableService { - private static final Logger LOGGER = Logger.getLogger(GPSProviderServiceImpl.class.getName()); - private MALProvider gpsServiceProvider; - private boolean initialiased = false; - private boolean running = false; - private NearbyPositionPublisher publisher; - private boolean isRegistered = false; - private final Object lock = new Object(); - private GPSManager manager; - private PeriodicCurrentPosition periodicCurrentPosition; - private final ConnectionProvider connection = new ConnectionProvider(); - private GPSAdapterInterface adapter; - private ConfigurationChangeListener configurationAdapter; - - private final Object MUTEX = new Object(); - private Position currentPosition = null; - private VectorD3D currentCartesianPosition = null; - private VectorF3D currentCartesianPositionDeviation = null; - private VectorD3D currentCartesianVelocity = null; - private VectorF3D currentCartesianVelocityDeviation = null; - private long timeOfCurrentPosition; - private long timeOfCurrentPositionAndVelocity; - - private Boolean isTLEFallbackEnabled = Boolean.parseBoolean(System.getProperty( - Const.PLATFORM_GNSS_FALLBACK_TO_TLE_PROPERTY, Const.PLATFORM_GNSS_FALLBACK_TO_TLE_DEFAULT)); - - private static final int NANOSECONDS_IN_MILLISECOND = 1000000; - private Double utcOffset = Double.parseDouble(System.getProperty(Const.PLATFORM_GNSS_UTC_OFFSET_PROPERTY, - Const.PLATFORM_GNSS_UTC_OFFSET_DEFAULT)); - private static boolean isOrekitDataInitialized = false; - - /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread - * - * @param comServices - * @param adapter - * @throws MALException On initialisation error. - */ - public synchronized void init(final COMServicesProvider comServices, final GPSAdapterInterface adapter) - throws MALException { - if (!initialiased) { - - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) == - null) { - PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { - COMHelper.init(MALContextFactory.getElementFactoryRegistry()); - } +public class GPSProviderServiceImpl extends GPSInheritanceSkeleton + implements ReconfigurableService +{ + protected static final Logger LOGGER = Logger.getLogger(GPSProviderServiceImpl.class.getName()); + private MALProvider gpsServiceProvider; + private boolean initialiased = false; + private boolean running = false; + private NearbyPositionPublisher publisher; + private boolean isRegistered = false; + private final Object lock = new Object(); + private GPSManager manager; + private PeriodicCurrentPosition periodicCurrentPosition; + private final ConnectionProvider connection = new ConnectionProvider(); + protected GPSAdapterInterface adapter; + private ConfigurationChangeListener configurationAdapter; + + protected final Object MUTEX = new Object(); + protected Position currentPosition = null; + protected VectorD3D currentCartesianPosition = null; + protected VectorF3D currentCartesianPositionDeviation = null; + protected VectorD3D currentCartesianVelocity = null; + protected VectorF3D currentCartesianVelocityDeviation = null; + + protected long timeOfCurrentPosition; + protected long timeOfCurrentPositionAndVelocity; + + /** + * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * + * @param comServices + * @param adapter + * @throws MALException On initialisation error. + */ + public synchronized void init(final COMServicesProvider comServices, + final GPSAdapterInterface adapter) throws MALException + { + if (!initialiased) { + + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, + MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { + PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, + COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(GPSHelper.GPS_SERVICE_NAME) == null) { + GPSHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + } - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(GPSHelper.GPS_SERVICE_NAME) == null) { - GPSHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - } + publisher = createNearbyPositionPublisher(ConfigurationProviderSingleton.getDomain(), + ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), QoSLevel.BESTEFFORT, null, + new UInteger(0)); publisher = createNearbyPositionPublisher(ConfigurationProviderSingleton.getDomain(), ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton @@ -259,15 +247,27 @@ public void getNMEASentence(String sentenceIdentifier, GetNMEASentenceInteractio null)); } - interaction.sendAcknowledgement(); - - try { - String nmeaSentence = adapter.getNMEASentence(sanitizeNMEARequest(sentenceIdentifier)); - interaction.sendResponse(nmeaSentence); - } catch (IOException ex) { - LOGGER.log(Level.FINE, "getNMEASentence error", ex); - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, null)); - } + Position position = updateCurrentPosition(useTLEpropagation); + if (position == null) { + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendResponse(position); + } + + @Override + public void getSatellitesInfo(GetSatellitesInfoInteraction interaction) + throws MALInteractionException, MALException + { + if (!adapter.isUnitAvailable()) { + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendAcknowledgement(); + SatelliteInfoList sats = adapter.getSatelliteInfoList(); + if (sats == null) { + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } @Override @@ -423,10 +423,51 @@ public LongList addNearbyPosition(final NearbyPositionDefinitionList nearbyPosit } } - // Errors - if (!dupIndexList.isEmpty()) { // requirement: 3.4.10.3.1 - throw new MALInteractionException(new MALStandardError(COMHelper.DUPLICATE_ERROR_NUMBER, dupIndexList)); - } + double elapsedTime = (System.currentTimeMillis() - startTime) / 1000; // convert from milli to sec + + return new GetLastKnownPositionAndVelocityResponse(position, positionDeviation, velocity, + velocityDeviation, new Duration(elapsedTime)); + } + + @Override + public void getPositionAndVelocity(GetPositionAndVelocityInteraction interaction) throws + MALInteractionException, MALException + { + boolean useTLEpropagation = false; + try{ + useTLEpropagation = useTLEPropagation(); + }catch (MALException | MALInteractionException e){ + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendAcknowledgement(); + try{ + updateCurrentPositionAndVelocity(useTLEpropagation); + }catch(IOException | NumberFormatException e){ + interaction + .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + final VectorD3D position; + final VectorF3D positionDeviation; + final VectorD3D velocity; + final VectorF3D velocityDeviation; + + synchronized (MUTEX) { + position = currentCartesianPosition; + positionDeviation = currentCartesianPositionDeviation; + velocity = currentCartesianVelocity; + velocityDeviation = currentCartesianVelocityDeviation; + } + interaction.sendResponse(position, positionDeviation, velocity, velocityDeviation); + } + + @Override + public void getTLE(GetTLEInteraction interaction) throws MALInteractionException, MALException { + throw new UnsupportedOperationException("Not supported yet."); + } + + public static final class PublishInteractionListener implements MALPublishInteractionListener + { if (!invIndexList.isEmpty()) { // requirement: 3.4.10.3.2 throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); @@ -739,36 +780,23 @@ public void start() { active = true; } - public void pause() { - active = false; - } - - public void init() { - timer.scheduleTask(new Thread(() -> { - if (active) { - boolean useTLEpropagation = false; - try { - useTLEpropagation = useTLEPropagation(); - } catch (MALException | MALInteractionException ignored) { - } - final Position pos = updateCurrentPosition(useTLEpropagation); - try { - updateCurrentPositionAndVelocity(useTLEpropagation); - } catch (IOException | NumberFormatException ignored) { - } - - // Compare with all the available definitions and raise - // NearbyPositionAlerts in case something has changed - LongList ids = manager.listAll(); - - for (int i = 0; i < ids.size(); i++) { - Long objId = ids.get(i); - NearbyPositionDefinition def = manager.get(objId); - Boolean previousState = manager.getPreviousStatus(objId); - - try { - double distance = PositionsCalculator.deltaDistanceFrom2Points(def.getPosition(), pos); - boolean isInside = (distance < def.getDistanceBoundary()); + @Override + public void getBestXYZSentence(GetBestXYZSentenceInteraction interaction) + throws MALInteractionException, MALException + { + if (!adapter.isUnitAvailable()) { // Is the unit available? + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendAcknowledgement(); + try { + interaction.sendResponse(adapter.getBestXYZSentence()); + } catch (IOException e) { + interaction + .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + LOGGER.log(Level.SEVERE, e.getMessage()); + } + } if (previousState == null) { // Maybe it's the first run... manager.setPreviousStatus(objId, isInside); @@ -788,89 +816,92 @@ public void init() { }), 0, PERIOD, TimeUnit.MILLISECONDS, true); } } - - @Override - public void getBestXYZSentence(GetBestXYZSentenceInteraction interaction) throws MALInteractionException, - MALException { - if (!adapter.isUnitAvailable()) { // Is the unit available? - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); - } - interaction.sendAcknowledgement(); - try { - interaction.sendResponse(adapter.getBestXYZSentence()); - } catch (IOException e) { - interaction.sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - e.printStackTrace(); - } + interaction.sendAcknowledgement(); + try { + interaction.sendResponse(adapter.getTIMEASentence()); + } catch (IOException e) { + interaction + .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + LOGGER.log(Level.SEVERE, e.getMessage()); } - @Override - public void getTIMEASentence(GetTIMEASentenceInteraction interaction) throws MALInteractionException, MALException { - if (!adapter.isUnitAvailable()) { // Is the unit available? - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); - } - interaction.sendAcknowledgement(); - try { - interaction.sendResponse(adapter.getTIMEASentence()); - } catch (IOException e) { - interaction.sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - e.printStackTrace(); - } + public boolean useTLEPropagation() throws MALInteractionException, MALException { + return false; + } + + /** + * Updates the current position/velocity + * @param useTLEpropagation + */ + public void updateCurrentPositionAndVelocity(boolean useTLEpropagation) + throws IOException, NumberFormatException + { + try { + final VectorD3D position; + final VectorF3D positionDeviation; + final VectorD3D velocity; + final VectorF3D velocityDeviation; + + String bestxyz = adapter.getBestXYZSentence(); + + String[] fields = HelperGPS.getDataFieldsFromBestXYZ(bestxyz); + + position = new VectorD3D( + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PX]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PY]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PZ]) + ); + + positionDeviation = new VectorF3D( + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PX_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PY_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PZ_DEVIATION]) + ); + + velocity = new VectorD3D( + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VX]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VY]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VZ]) + ); + + velocityDeviation = new VectorF3D( + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VX_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VY_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VZ_DEVIATION]) + ); + + synchronized (MUTEX) { // Store the latest Position + currentCartesianPosition = position; + currentCartesianPositionDeviation = positionDeviation; + currentCartesianVelocity = velocity; + currentCartesianVelocityDeviation = velocityDeviation; + timeOfCurrentPositionAndVelocity = System.currentTimeMillis(); + } + } catch (IOException | NumberFormatException e) { + LOGGER.log(Level.SEVERE, e.getMessage()); + throw e; } - - /** - * Checks the fixQquality on the GNSS position. - * @return true if a fixed position has been established, false otherwise - */ - private boolean isPositionFixed() { - boolean isFixed = false; - try { - if (adapter.getCurrentPosition().getExtraDetails().getFixQuality() > 0) { - isFixed = true; - } - } catch (NullPointerException e) { - LOGGER.warning("Could not receive a fixed position: " + e.getMessage()); - } - return isFixed; + } + + /** + * Updates the current position using TLE if useTLEpropagation is true, + * or the GPS adapter if useTLEpropagation is false + * @param useTLEpropagation + * @return the updated position, or null if the methods that get latest position fail + */ + public Position updateCurrentPosition(boolean useTLEpropagation) + { + Position position = adapter.getCurrentPosition(); + if (position == null) { + return null; } - private Position getTLEPropagatedPosition() { - Calendar targetDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - SpacecraftState state = getSpacecraftState(targetDate); - - // Converting to geodetic lat/lon/alt - Frame ecf = FramesFactory.getITRF(IERSConventions.IERS_2010, true); - OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, - Constants.WGS84_EARTH_FLATTENING, ecf); - GeodeticPoint satLatLonAlt = earth.transform(state.getPVCoordinates().getPosition(), FramesFactory.getEME2000(), - state.getDate()); - - PositionExtraDetails extraDetails = new PositionExtraDetails(new Time(targetDate.getTimeInMillis()), 0, 0, 0.0f, - 0.0f, PositionSourceType.TLE); - - return new Position((float) FastMath.toDegrees(satLatLonAlt.getLatitude()), (float) FastMath.toDegrees( - satLatLonAlt.getLongitude()), (float) satLatLonAlt.getAltitude(), extraDetails); - } - - private SpacecraftState getSpacecraftState(Calendar targetDate) { - - if (!isOrekitDataInitialized) { - //setup orekit if not yet initialized - DataProvidersManager manager = DataProvidersManager.getInstance(); - if (manager.getProviders().isEmpty()) { - manager.addProvider(OrekitResources.getOrekitData()); - } - isOrekitDataInitialized = true; - } - - TLE tle = adapter.getTLE(); - TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle); - - return propagator.propagate(new AbsoluteDate(targetDate.get(Calendar.YEAR), targetDate.get(Calendar.MONTH) + 1, - targetDate.get(Calendar.DAY_OF_MONTH), targetDate.get(Calendar.HOUR_OF_DAY), targetDate.get( - Calendar.MINUTE), targetDate.get(Calendar.SECOND), TimeScalesFactory.getUTC())); + synchronized (MUTEX) { // Store the latest Position + currentPosition = position; + timeOfCurrentPosition = System.currentTimeMillis(); } + return position; + } + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index fea9acd96..0e56490a3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -377,8 +377,7 @@ public static void generateStartScript(MetadataApp appDetails, String path = appDir.getAbsolutePath() + File.separator; if (os.isUnix() || os.isMac()) { - String content = HelperNMFPackage.generateLinuxStartAppScript( - javaCMD, jarName, appDetails); + String content = generateLinuxStartAppScript(javaCMD, jarName, appDetails); path += "start_" + name + ".sh"; HelperNMFPackage.writeFile(path, content); diff --git a/mission/simulator/platform-services-impl/pom.xml b/mission/simulator/platform-services-impl/pom.xml index be2195dfd..e658572c4 100644 --- a/mission/simulator/platform-services-impl/pom.xml +++ b/mission/simulator/platform-services-impl/pom.xml @@ -69,6 +69,11 @@ image-debayer 2.1.0-SNAPSHOT + + int.esa.nmf.sdk + orekit-resources + ${project.version} + junit junit diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java new file mode 100644 index 000000000..68e437f32 --- /dev/null +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java @@ -0,0 +1,263 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.platform.impl.provider.softsim; + +import esa.mo.helpertools.misc.Const; +import esa.mo.nmf.sdk.OrekitResources; +import esa.mo.platform.impl.provider.gen.GPSProviderServiceImpl; +import esa.mo.platform.impl.util.HelperGPS; +import java.io.IOException; +import java.util.Calendar; +import java.util.TimeZone; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.mal.structures.Time; +import org.ccsds.moims.mo.platform.PlatformHelper; +import org.ccsds.moims.mo.platform.gps.provider.GetTLEInteraction; +import org.ccsds.moims.mo.platform.gps.structures.Position; +import org.ccsds.moims.mo.platform.gps.structures.PositionExtraDetails; +import org.ccsds.moims.mo.platform.gps.structures.PositionSourceType; +import org.ccsds.moims.mo.platform.gps.structures.TwoLineElementSet; +import org.ccsds.moims.mo.platform.structures.VectorD3D; +import org.ccsds.moims.mo.platform.structures.VectorF3D; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.bodies.OneAxisEllipsoid; +import org.orekit.data.DataProvidersManager; +import org.orekit.frames.Frame; +import org.orekit.frames.FramesFactory; +import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.analytical.tle.TLE; +import org.orekit.propagation.analytical.tle.TLEPropagator; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.TimeScalesFactory; +import org.orekit.utils.Constants; +import org.orekit.utils.IERSConventions; + +/** + * GPS service Provider with TLE support. + */ +public class GPSProviderServiceWithTLEImpl extends GPSProviderServiceImpl { + + private static final int NANOSECONDS_IN_MILLISECOND = 1000000; + + private final Boolean isTLEFallbackEnabled = + Boolean.parseBoolean(System.getProperty(Const.PLATFORM_GNSS_FALLBACK_TO_TLE_PROPERTY, + Const.PLATFORM_GNSS_FALLBACK_TO_TLE_DEFAULT)); + + private final Double utcOffset = Double.parseDouble(System.getProperty(Const.PLATFORM_GNSS_UTC_OFFSET_PROPERTY, + Const.PLATFORM_GNSS_UTC_OFFSET_DEFAULT)); + private static boolean isOrekitDataInitialized = false; + + private final GPSSoftSimAdapter adapterCast = (GPSSoftSimAdapter) adapter; + + /** + * Updates the current position/velocity + * @param useTLEpropagation + */ + @Override + public void updateCurrentPositionAndVelocity(boolean useTLEpropagation) + throws IOException, NumberFormatException + { + try { + final VectorD3D position; + final VectorF3D positionDeviation; + final VectorD3D velocity; + final VectorF3D velocityDeviation; + + if(useTLEpropagation) + { + Calendar targetDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + SpacecraftState state = getSpacecraftState(targetDate); + Vector3D pos = state.getPVCoordinates().getPosition(); + position = new VectorD3D(pos.getX(), pos.getY(), pos.getZ()); + + positionDeviation = new VectorF3D(0f, 0f, 0f); + + Vector3D velocity3D = state.getPVCoordinates().getVelocity(); + velocity = new VectorD3D(velocity3D.getX(), velocity3D.getY(), velocity3D.getZ()); + + velocityDeviation = new VectorF3D(0f, 0f, 0f); + } + else { + String bestxyz = adapter.getBestXYZSentence(); + + String[] fields = HelperGPS.getDataFieldsFromBestXYZ(bestxyz); + + position = new VectorD3D( + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PX]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PY]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PZ]) + ); + + positionDeviation = new VectorF3D( + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PX_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PY_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PZ_DEVIATION]) + ); + + velocity = new VectorD3D( + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VX]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VY]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VZ]) + ); + + velocityDeviation = new VectorF3D( + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VX_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VY_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VZ_DEVIATION]) + ); + } + synchronized (MUTEX) { // Store the latest Position + currentCartesianPosition = position; + currentCartesianPositionDeviation = positionDeviation; + currentCartesianVelocity = velocity; + currentCartesianVelocityDeviation = velocityDeviation; + timeOfCurrentPositionAndVelocity = System.currentTimeMillis(); + } + } catch (IOException | NumberFormatException e) { + e.printStackTrace(); + throw e; + } + } + + @Override + public void getTLE(GetTLEInteraction interaction) throws MALInteractionException, MALException + { + if (!adapter.isUnitAvailable() && isTLEFallbackEnabled == false) { // Is the unit available? + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendAcknowledgement(); + TLE tle = adapterCast.getTLE(); + + interaction.sendResponse(new TwoLineElementSet(tle.getSatelliteNumber(), "" + tle.getClassification(), + tle.getLaunchYear(), tle.getLaunchNumber(), tle.getLaunchPiece(), + tle.getDate().getComponents(0).getDate().getYear(), + tle.getDate().getComponents(0).getDate().getDayOfYear(), + tle.getDate().getComponents(0).getTime().getSecondsInUTCDay(), + tle.getMeanMotionFirstDerivative(), tle.getMeanMotionSecondDerivative(), + tle.getBStar(), tle.getElementNumber(), tle.getI(), tle.getRaan(), tle.getE(), + tle.getPerigeeArgument(), tle.getMeanAnomaly(), tle.getMeanMotion(), + tle.getRevolutionNumberAtEpoch())); + } + + private Position getTLEPropagatedPosition() + { + Calendar targetDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + SpacecraftState state = getSpacecraftState(targetDate); + + // Converting to geodetic lat/lon/alt + Frame ecf = FramesFactory.getITRF(IERSConventions.IERS_2010,true); + OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING, ecf); + GeodeticPoint satLatLonAlt = earth.transform(state.getPVCoordinates().getPosition(), FramesFactory.getEME2000(), + state.getDate()); + + PositionExtraDetails extraDetails = new PositionExtraDetails(new Time(targetDate.getTimeInMillis()), + 0, 0, 0.0f,0.0f, PositionSourceType.TLE); + + return new Position((float) FastMath.toDegrees(satLatLonAlt.getLatitude()), (float) FastMath.toDegrees(satLatLonAlt.getLongitude()), + (float) satLatLonAlt.getAltitude(), extraDetails); + } + + private SpacecraftState getSpacecraftState(Calendar targetDate) { + + if(!isOrekitDataInitialized) { + //setup orekit if not yet initialized + DataProvidersManager manager = DataProvidersManager.getInstance(); + if(manager.getProviders().isEmpty()) + { + manager.addProvider(OrekitResources.getOrekitData()); + } + isOrekitDataInitialized = true; + } + + TLE tle = adapterCast.getTLE(); + TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle); + + return propagator.propagate(new AbsoluteDate(targetDate.get(Calendar.YEAR), + targetDate.get(Calendar.MONTH) + 1, + targetDate.get(Calendar.DAY_OF_MONTH), targetDate.get(Calendar.HOUR_OF_DAY), targetDate.get(Calendar.MINUTE), + targetDate.get(Calendar.SECOND), TimeScalesFactory.getUTC())); + } + + /** + * Checks if TLE propagation should be used + * @return true if TLE propagation should be used, false otherwise + */ + @Override + public boolean useTLEPropagation() throws MALInteractionException, MALException { + boolean useTLEpropagation = false; + if (!adapter.isUnitAvailable()) { + if(isTLEFallbackEnabled) { + useTLEpropagation = true; + } else { + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + } + else if(!isPositionFixed()){ + useTLEpropagation = true; + } + return useTLEpropagation; + } + + /** + * Updates the current position using TLE if useTLEpropagation is true, + * or the GPS adapter if useTLEpropagation is false + * @param useTLEpropagation + * @return the updated position, or null if the methods that get latest position fail + */ + @Override + public Position updateCurrentPosition(boolean useTLEpropagation) + { + Position position = useTLEpropagation ? getTLEPropagatedPosition() : adapter.getCurrentPosition(); + if (position == null) { + return null; + } + + synchronized (MUTEX) { // Store the latest Position + currentPosition = position; + timeOfCurrentPosition = System.currentTimeMillis(); + } + return position; + } + + /** + * Checks the fixQquality on the GNSS position. + * @return true if a fixed position has been established, false otherwise + */ + private boolean isPositionFixed() { + boolean isFixed = false; + try { + if(adapter.getCurrentPosition().getExtraDetails().getFixQuality() > 0){ + isFixed = true; + } + } catch (NullPointerException e) + { + LOGGER.warning("Could not receive a fixed position: " + e.getMessage()); + } + return isFixed; + } + +} diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSSoftSimAdapter.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSSoftSimAdapter.java index 73b905f95..93205fad3 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSSoftSimAdapter.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSSoftSimAdapter.java @@ -34,8 +34,8 @@ */ public class GPSSoftSimAdapter extends GPSNMEAonlyAdapter implements SimulatorAdapter { - private final ESASimulator instrumentsSimulator; - private PowerControlAdapterInterface pcAdapter; + private final ESASimulator instrumentsSimulator; + private final PowerControlAdapterInterface pcAdapter; public GPSSoftSimAdapter(ESASimulator instrumentsSimulator, PowerControlAdapterInterface pcAdapter) { this.instrumentsSimulator = instrumentsSimulator; @@ -80,9 +80,9 @@ public boolean isUnitAvailable() { return pcAdapter.isDeviceEnabled(DeviceType.GNSS); } - @Override - public TLE getTLE() { - TLE tle = this.instrumentsSimulator.getSimulatorNode().getTLE(); + public TLE getTLE() + { + TLE tle = this.instrumentsSimulator.getSimulatorNode().getTLE(); return tle; } diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index d640811d5..5154654ea 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -68,13 +68,14 @@ public class PlatformServicesProviderSoftSim implements PlatformServicesProvider private final ArtificialIntelligenceProviderServiceImpl aiService = new ArtificialIntelligenceProviderServiceImpl(); private final AutonomousADCSProviderServiceImpl autonomousADCSService = new AutonomousADCSProviderServiceImpl(); private final CameraProviderServiceImpl cameraService = new CameraProviderServiceImpl(); - private final GPSProviderServiceImpl gpsService = new GPSProviderServiceImpl(); + private final GPSProviderServiceWithTLEImpl gpsService = new GPSProviderServiceWithTLEImpl(); private final OpticalDataReceiverProviderServiceImpl opticalDataReceiverService = new OpticalDataReceiverProviderServiceImpl(); private final SoftwareDefinedRadioProviderServiceImpl sdrService = new SoftwareDefinedRadioProviderServiceImpl(); private final PowerControlProviderServiceImpl powerService = new PowerControlProviderServiceImpl(); private PowerControlAdapterInterface pcAdapter; private final ClockProviderServiceImpl clockService = new ClockProviderServiceImpl(); + @Override public void init(COMServicesProvider comServices) throws MALException { // Check if hybrid setup is used CameraAdapterInterface camAdapter; @@ -288,7 +289,7 @@ public void init(COMServicesProvider comServices) throws MALException { aiAdapter = new AIMovidiusAdapter(); } catch (IOException ex) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log( - Level.SEVERE, "The AI adapter could not be started!", ex); + Level.INFO, "The AI adapter could not be started!", ex); aiAdapter = null; } @@ -341,9 +342,8 @@ public SoftwareDefinedRadioInheritanceSkeleton getSoftwareDefinedRadioService() return this.sdrService; } - @Override - public ArtificialIntelligenceInheritanceSkeleton getAIService() { - throw new UnsupportedOperationException("Not supported yet."); - } - + @Override + public ArtificialIntelligenceInheritanceSkeleton getAIService() { + throw new UnsupportedOperationException("Not supported yet."); + } } From e0549df739b760e071ec562be6049089094ef0e2 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 28 Oct 2022 11:55:12 +0200 Subject: [PATCH 116/173] Moved the Orekit resources to the Simulator mission --- {sdk => mission/simulator}/orekit-resources/pom.xml | 0 .../main/java/esa/mo/nmf/sdk/OrekitResources.java | 0 .../src/main/resources/orekit-data.zip | Bin mission/simulator/pom.xml | 1 + sdk/pom.xml | 1 - 5 files changed, 1 insertion(+), 1 deletion(-) rename {sdk => mission/simulator}/orekit-resources/pom.xml (100%) rename {sdk => mission/simulator}/orekit-resources/src/main/java/esa/mo/nmf/sdk/OrekitResources.java (100%) rename {sdk => mission/simulator}/orekit-resources/src/main/resources/orekit-data.zip (100%) diff --git a/sdk/orekit-resources/pom.xml b/mission/simulator/orekit-resources/pom.xml similarity index 100% rename from sdk/orekit-resources/pom.xml rename to mission/simulator/orekit-resources/pom.xml diff --git a/sdk/orekit-resources/src/main/java/esa/mo/nmf/sdk/OrekitResources.java b/mission/simulator/orekit-resources/src/main/java/esa/mo/nmf/sdk/OrekitResources.java similarity index 100% rename from sdk/orekit-resources/src/main/java/esa/mo/nmf/sdk/OrekitResources.java rename to mission/simulator/orekit-resources/src/main/java/esa/mo/nmf/sdk/OrekitResources.java diff --git a/sdk/orekit-resources/src/main/resources/orekit-data.zip b/mission/simulator/orekit-resources/src/main/resources/orekit-data.zip similarity index 100% rename from sdk/orekit-resources/src/main/resources/orekit-data.zip rename to mission/simulator/orekit-resources/src/main/resources/orekit-data.zip diff --git a/mission/simulator/pom.xml b/mission/simulator/pom.xml index 5ce0e0e7e..faf43751b 100644 --- a/mission/simulator/pom.xml +++ b/mission/simulator/pom.xml @@ -50,6 +50,7 @@ true + orekit-resources platform-services-impl nanosat-monolithic opssat-gps-simulator diff --git a/sdk/pom.xml b/sdk/pom.xml index b38772d14..c5cc3b2fa 100644 --- a/sdk/pom.xml +++ b/sdk/pom.xml @@ -67,6 +67,5 @@ examples tools sdk-package - orekit-resources \ No newline at end of file From a611b6552773b53710dc9285dd4ebd9ca378678a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 28 Oct 2022 11:57:01 +0200 Subject: [PATCH 117/173] Updates the name of the project --- mission/simulator/orekit-resources/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/simulator/orekit-resources/pom.xml b/mission/simulator/orekit-resources/pom.xml index 0466020ea..b425005a3 100644 --- a/mission/simulator/orekit-resources/pom.xml +++ b/mission/simulator/orekit-resources/pom.xml @@ -26,7 +26,7 @@ orekit-resources jar - ESA NMF SDK - Orekit Resources + ESA NMF - Orekit Resources Jar containing the Orekit-Data that is needed as a resource for most of the Orekit applications using it http://www.esa.int From eded1040e808004b30e51b54730a22a885e0fef9 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 28 Oct 2022 14:04:54 +0200 Subject: [PATCH 118/173] Updates the relativePath of the parent pom --- mission/simulator/orekit-resources/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/simulator/orekit-resources/pom.xml b/mission/simulator/orekit-resources/pom.xml index b425005a3..26cbfec39 100644 --- a/mission/simulator/orekit-resources/pom.xml +++ b/mission/simulator/orekit-resources/pom.xml @@ -19,7 +19,7 @@ int.esa.nmf parent 2.1.0-SNAPSHOT - ../../parent/pom.xml + ../../../parent/pom.xml int.esa.nmf.sdk From 3a80531ff7fb25596c2bfa1f938a1312e11dfa88 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 28 Oct 2022 22:09:09 +0200 Subject: [PATCH 119/173] [nmf-package] Refactors the classes --- .../esa/mo/nmf/nmfpackage/Deployment.java | 43 +++++---- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 47 +++++++++- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 2 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 92 +++---------------- .../mo/nmf/nmfpackage/metadata/Metadata.java | 22 +++-- .../nmf/nmfpackage/metadata/MetadataApp.java | 2 - .../nmfpackage/utils/HelperNMFPackage.java | 28 ++++-- 7 files changed, 116 insertions(+), 120 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index 259a79dbc..cdd1c947b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -27,49 +27,54 @@ * @author Cesar Coelho */ public class Deployment { - + + public static final String DIR_NMF = "nanosat-mo-framework"; + public static final String DIR_APPS = "apps"; public static final String DIR_DRIVERS = "drivers"; public static final String DIR_ETC = "etc"; public static final String DIR_JARS_MISSION = "jars-mission"; public static final String DIR_JARS_NMF = "jars-nmf"; - public static final String DIR_JARS_SHARED = "jars-shared-dependencies"; + public static final String DIR_JARS_SHARED = "jars-shared-libraries"; public static final String DIR_JAVA = "java"; public static final String DIR_LOGS = "logs"; public static final String DIR_PACKAGES = "packages"; public static final String DIR_PUBLIC = "public"; - private static final String DIR_RECEIPTS = "installation_receipts"; + private static final String DIR_INSTALLATIONS_TRACKER = "installations-tracker"; - private static final String INSTALLED_RECEIPTS_FOLDER_PROPERTY = "esa.mo.nmf.nmfpackage.receipts"; + private static final String PROPERTY_INSTALLED_RECEIPTS_FOLDER = "esa.mo.nmf.nmfpackage.receipts"; - @Deprecated - private static final String INSTALLATION_FOLDER_PROPERTY = "esa.mo.nmf.nmfpackage.installationFolder"; - - public static File getReceiptsFolder() { + private static String pathNMF = null; + + public static File getInstallationsTrackerDir() { // Default location of the folder - File folder = new File(DIR_ETC + File.separator + DIR_RECEIPTS); + File folder = new File(DIR_ETC + File.separator + DIR_INSTALLATIONS_TRACKER); // Read the Property of the folder to install the packages - if (System.getProperty(INSTALLED_RECEIPTS_FOLDER_PROPERTY) != null) { - folder = new File(System.getProperty(INSTALLED_RECEIPTS_FOLDER_PROPERTY)); + if (System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER) != null) { + folder = new File(System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER)); } return folder; } - @Deprecated - public static File getInstallationFolder() { - // Default location of the folder - File folder = new File(""); + public static File getNMFRootDir() { + if (pathNMF != null) { + return new File(pathNMF); + } - // Read the Property of the folder to install the packages - if (System.getProperty(INSTALLATION_FOLDER_PROPERTY) != null) { - folder = new File(System.getProperty(INSTALLATION_FOLDER_PROPERTY)); + File folder = new File((new File("")).getAbsolutePath()); + String currentFolder = folder.getName(); + + // Default location of the folder + if (DIR_NMF.equals(currentFolder) || "supervisor".equals(currentFolder)) { + pathNMF = folder.getAbsolutePath(); + return new File(pathNMF); } + // We need additional logic to make sure we are in the right directory! return folder; } - } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index b8b0deba3..83a349034 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -22,6 +22,8 @@ import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import esa.mo.nmf.nmfpackage.metadata.Metadata; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -42,10 +44,6 @@ public NMFPackage(String filepath) throws IOException { this.zipFile = new ZipFile(filepath); } - public ZipFile getZipFile() { - return zipFile; - } - public synchronized Metadata getMetadata() throws IOException { if (metadata != null) { return metadata; @@ -105,4 +103,45 @@ public void verifyPackageIntegrity() throws IOException { } } } + + public void extractFiles(File to) throws IOException { + File newFile; + byte[] buffer = new byte[1024]; + + // Iterate through the files, unpack them into the right folders + ArrayList files = metadata.getFiles(); + + for (int i = 0; i < files.size(); i++) { + NMFPackageFile file = files.get(i); + ZipEntry entry = this.getZipFileEntry(file.getPath()); + + String path = HelperNMFPackage.generateFilePathForSystem(entry.getName()); + newFile = new File(to.getCanonicalPath() + File.separator + path); + File parent = new File(newFile.getParent()); + + if (!parent.exists()) { + new File(newFile.getParent()).mkdirs(); + } + + System.out.println(" >> Copying file to: " + newFile.getCanonicalPath()); + + FileOutputStream fos = new FileOutputStream(newFile); + InputStream zis = zipFile.getInputStream(entry); + int len; + + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + + fos.close(); + + long crc = HelperNMFPackage.calculateCRCFromFile(newFile.getCanonicalPath()); + + // We will also need to double check the CRCs again against the real files! + // Just to double-check.. better safe than sorry! + if (file.getCRC() != crc) { + throw new IOException("The CRC does not match!"); + } + } + } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index ca63aba26..367d338e3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -70,7 +70,7 @@ private static void zipFiles(String outputPath, ArrayList from, origin.close(); } out.close(); - } catch (Exception ex) { + } catch (IOException ex) { Logger.getLogger(NMFPackageCreator.class.getName()).log( Level.SEVERE, "The Files could not be zipped!", ex); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index dfda6582e..ad5c50ff3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -31,14 +31,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; import org.ccsds.moims.mo.mal.structures.Identifier; @@ -113,7 +109,7 @@ public void install(final String packageLocation, installDependencies(metadata.castToApp(), packageLocation, nmfDir); } - extractFiles(pack, nmfDir); + pack.extractFiles(nmfDir); String packageName = metadata.getPackageName(); if (metadata.isApp()) { @@ -160,7 +156,7 @@ public void install(final String packageLocation, } // Store a copy of the newReceipt to know that it has been installed! - File receiptsFolder = Deployment.getReceiptsFolder(); + File receiptsFolder = Deployment.getInstallationsTrackerDir(); String receiptFilename = packageName + RECEIPT_ENDING; String receiptPath = receiptsFolder.getCanonicalPath() + File.separator + receiptFilename; File receiptFile = new File(receiptPath); @@ -193,7 +189,7 @@ public void uninstall(final Metadata packageMetadata, if (packageMetadata.isApp()) { // This directory should be passed in the method signature: - File nmfDir = Deployment.getInstallationFolder(); + File nmfDir = Deployment.getNMFRootDir(); File installationDir = new File(nmfDir.getAbsolutePath() + File.separator + Deployment.DIR_APPS + File.separator + packageName); @@ -210,7 +206,7 @@ public void uninstall(final Metadata packageMetadata, removeFiles(packageMetadata); - String receiptsPath = Deployment.getReceiptsFolder().getCanonicalPath(); + String receiptsPath = Deployment.getInstallationsTrackerDir().getCanonicalPath(); String receiptFilename = packageName + RECEIPT_ENDING; File receiptFile = new File(receiptsPath + File.separator + receiptFilename); @@ -247,17 +243,12 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx + "Version: " + newPackMetadata.getMetadataVersion()); } - File receiptsFolder = Deployment.getReceiptsFolder(); + File receiptsFolder = Deployment.getInstallationsTrackerDir(); String receiptFilename = newPackMetadata.getPackageName() + RECEIPT_ENDING; File oldReceiptFile = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); + Metadata oldPackMetadata = Metadata.load(oldReceiptFile); - // Get the text out of that file and parse it into a NMFPackageDescriptor object - InputStream stream2 = new FileInputStream(oldReceiptFile); - Metadata oldPackMetadata = Metadata.load(stream2); - stream2.close(); - - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Upgrading..." + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Upgrading..." + "\n >> From version: " + oldPackMetadata.getPackageVersion() + " (timestamp: " + oldPackMetadata.getPackageTimestamp() + ")" + "\n >> To version: " + newPackMetadata.getPackageVersion() @@ -296,7 +287,7 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx MetadataApp appMetadata = newPackMetadata.castToApp(); installDependencies(appMetadata, packageLocation, nmfDir); - extractFiles(newPack, nmfDir); + newPack.extractFiles(nmfDir); if (isApp) { String username = null; @@ -356,7 +347,7 @@ public boolean isPackageInstalled(final String packageLocation) { return false; } - File temp = Deployment.getReceiptsFolder(); + File temp = Deployment.getInstallationsTrackerDir(); String packageName = metadata.getPackageName(); String receiptFilename = packageName + RECEIPT_ENDING; File receiptFile; @@ -405,16 +396,6 @@ public boolean isPackageInstalled(final String packageLocation) { return true; } - private static String generateFilePathForSystem(final String path) throws IOException { - // Sanitize the path to prevent a ZipSlip attack: - if (path.contains("..")) { - throw new IOException("Warning! A ZipSlip attack was detected!"); - } - - String out = path.replace('/', File.separatorChar); - return out.replace('\\', File.separatorChar); - } - private static void installDependencies(MetadataApp metadata, String packageLocation, File installationDir) throws IOException { if (!metadata.hasDependencies()) { @@ -430,51 +411,8 @@ private static void installDependencies(MetadataApp metadata, for (String file : dependencies) { file = file.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); String path = parent + File.separator + file; - extractFiles(new NMFPackage(path), installationDir); - } - } - - private static void extractFiles(NMFPackage pack, File to) throws IOException { - Metadata metadata = pack.getMetadata(); - ZipFile zipFile = pack.getZipFile(); - - File newFile; - byte[] buffer = new byte[1024]; - - // Iterate through the files, unpack them into the right folders - ArrayList files = metadata.getFiles(); - - for (int i = 0; i < files.size(); i++) { - NMFPackageFile file = files.get(i); - ZipEntry entry = pack.getZipFileEntry(file.getPath()); - - String path = generateFilePathForSystem(entry.getName()); - newFile = new File(to.getCanonicalPath() + File.separator + path); - File parent = new File(newFile.getParent()); - - if (!parent.exists()) { - new File(newFile.getParent()).mkdirs(); - } - - System.out.println(" >> Copying file to: " + newFile.getCanonicalPath()); - - FileOutputStream fos = new FileOutputStream(newFile); - InputStream zis = zipFile.getInputStream(entry); - int len; - - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); - } - - fos.close(); - - long crc = HelperNMFPackage.calculateCRCFromFile(newFile.getCanonicalPath()); - - // We will also need to double check the CRCs again against the real files! - // Just to double-check.. better safe than sorry! - if (file.getCRC() != crc) { - throw new IOException("The CRC does not match!"); - } + NMFPackage pack = new NMFPackage(path); + pack.extractFiles(installationDir); } } @@ -511,13 +449,13 @@ private static void createAuxiliaryFiles(File installationDir, String username) } private static void removeFiles(Metadata metadata) throws IOException { - File folder = Deployment.getInstallationFolder(); + File folder = Deployment.getNMFRootDir(); File file; // Do the files actually match the descriptor? for (int i = 0; i < metadata.getFiles().size(); i++) { NMFPackageFile packageFile = metadata.getFiles().get(i); - String path = generateFilePathForSystem(packageFile.getPath()); + String path = HelperNMFPackage.generateFilePathForSystem(packageFile.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); NMFPackageManager.removeFile(file); } @@ -569,8 +507,8 @@ private void stopAppIfRunning(String name) { IdentifierList myApp = new IdentifierList(); myApp.add(new Identifier(name)); - Identifier cat = new Identifier("*"); - ListAppResponse response = appsLauncher.listApp(myApp, cat, null); + Identifier category = new Identifier("*"); + ListAppResponse response = appsLauncher.listApp(myApp, category, null); LongList runningApp = new LongList(); for (int i = 0; i < response.getBodyElement0().size(); i++) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index aaa3a2515..f69262999 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -25,6 +25,7 @@ import esa.mo.nmf.nmfpackage.receipt.NMFPackageDescriptor; import esa.mo.nmf.nmfpackage.NMFPackageFile; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -69,6 +70,7 @@ public class Metadata { public static final String TYPE_UPDATE_JAVA = "java"; public static final String TYPE_UPDATE_MISSION = "mission"; public static final String TYPE_UPDATE_NMF = "nmf"; + public static final String TYPE_DELTA = "delta"; public static final String FILE_COUNT = "zipped.file.count"; public static final String FILE_PATH = "zipped.file.path"; @@ -102,10 +104,6 @@ public Metadata(Properties properties, ArrayList files) { } } - public String getProperty(String key) { - return properties.getProperty(key); - } - public void addProperty(String key, String value) { properties.put(key, value); } @@ -212,6 +210,14 @@ public static Metadata load(InputStream inStream) throws IOException { return new Metadata(props); } + public static Metadata load(File file) throws IOException { + Metadata loadedMetadata; + try (InputStream stream = new FileInputStream(file)) { + loadedMetadata = Metadata.load(stream); + } + return loadedMetadata; + } + @SuppressWarnings("serial") private Properties newOrderedProperties() { return new Properties() { @@ -243,21 +249,21 @@ public boolean isApp() { return TYPE_APP.equals(type); } - public boolean sameAs(Metadata installedMetadata) { + public boolean sameAs(Metadata other) { // Starts with the timestamp because this is most of the times unique! - if (!this.getPackageTimestamp().equals(installedMetadata.getPackageTimestamp())) { + if (!this.getPackageTimestamp().equals(other.getPackageTimestamp())) { Logger.getLogger(NMFPackageManager.class.getName()).log( Level.FINE, "The creation timestamp does not match!"); return false; } - if (!this.getPackageName().equals(installedMetadata.getPackageName())) { + if (!this.getPackageName().equals(other.getPackageName())) { Logger.getLogger(NMFPackageManager.class.getName()).log( Level.FINE, "The name does not match!"); return false; } - if (!this.getPackageVersion().equals(installedMetadata.getPackageVersion())) { + if (!this.getPackageVersion().equals(other.getPackageVersion())) { Logger.getLogger(NMFPackageManager.class.getName()).log( Level.FINE, "The version does not match!"); return false; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java index 411ae4ef2..f709f97d9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java @@ -20,12 +20,10 @@ */ package esa.mo.nmf.nmfpackage.metadata; -import esa.mo.helpertools.helpers.HelperTime; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Properties; -import org.ccsds.moims.mo.mal.structures.Time; /** * The MetadataApp class holds the metadata of an App in a NMF Package. diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 0e56490a3..8967c1c8f 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -49,9 +49,10 @@ public class HelperNMFPackage { public static final String NMF_PACKAGE_DESCRIPTOR_VERSION = "NMFPackageDescriptorVersion="; public static long calculateCRCFromFile(final String filepath) throws IOException { - InputStream inputStream = new BufferedInputStream(new FileInputStream(filepath)); - long crc = calculateCRCFromInputStream(inputStream); - inputStream.close(); + long crc; + try (InputStream inputStream = new BufferedInputStream(new FileInputStream(filepath))) { + crc = calculateCRCFromInputStream(inputStream); + } return crc; } @@ -91,7 +92,7 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); str.append("MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); - + str.append("# Jars from: App, NMF, and Shared dependencies:\n"); str.append("JAR_APP=").append(jarFilename).append("\n"); // The following code must be changed: @@ -99,7 +100,7 @@ public static String generateLinuxStartAppScript(String javaCommand, String shared = ""; if (meta.hasDependencies()) { - String nmf = Deployment.getInstallationFolder().getAbsolutePath(); + String nmf = Deployment.getNMFRootDir().getAbsolutePath(); File sharedLibs = new File(nmf + File.separator + Deployment.DIR_JARS_SHARED); String paths = meta.getAppDependenciesFullPaths(sharedLibs); str.append("JARS_SHARED=").append(paths); @@ -131,12 +132,12 @@ public static String generateWindowsStartAppScript(String javaCommand, str.append("@echo off\n\n"); str.append(":: Java Runtime Environment:\n"); str.append("set JAVA_CMD=").append(javaCommand).append("\n\n"); - + str.append(":: App-related constants:\n"); str.append("set MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); str.append("set MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); str.append("set MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); - + str.append(":: Jars from: App, NMF, and Shared dependencies:\n"); str.append("set JAR_APP=").append(jarFilename).append("\n"); @@ -145,7 +146,7 @@ public static String generateWindowsStartAppScript(String javaCommand, str.append("\n\nset JARS_ALL=\"%JAR_APP%;%JARS_NMF%\""); str.append("\n\n"); - + str.append("%JAVA_CMD% %JAVA_OPTS% -classpath %JARS_ALL%"); str.append(" -Dapp.name=\"").append(meta.getPackageName()); str.append("\" ").append(meta.getAppMainclass()); @@ -359,7 +360,7 @@ public static String findJREPath(File nmfDir, int recommended, int min, int max) return bestJRE; } - public static void generateStartScript(MetadataApp appDetails, + public static void generateStartScript(MetadataApp appDetails, File appDir, File nmfDir) throws IOException { String name = appDetails.getPackageName(); String jarName = appDetails.getAppMainJar(); @@ -406,4 +407,13 @@ public static void writeFile(String path, String content) { } } + public static String generateFilePathForSystem(final String path) throws IOException { + // Sanitize the path to prevent a ZipSlip attack: + if (path.contains("..")) { + throw new IOException("Warning! A ZipSlip attack was detected!"); + } + + String out = path.replace('/', File.separatorChar); + return out.replace('\\', File.separatorChar); + } } From ea3672c3eb24c1cacbf2fc423833e58063fa9b5a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sat, 29 Oct 2022 12:46:10 +0200 Subject: [PATCH 120/173] Code cleanup --- .../connections/ConnectionProvider.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java index f47bc6421..ce4c7b79c 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java @@ -46,15 +46,16 @@ */ public class ConnectionProvider { + private final static ServicesConnectionDetails GLOBAL_PROVIDERS_DETAILS_PRIMARY = new ServicesConnectionDetails(); + private final static ServicesConnectionDetails GLOBAL_PROVIDERS_DETAILS_SECONDARY = new ServicesConnectionDetails(); + + private final SingleConnectionDetails primaryConnectionDetails = new SingleConnectionDetails(); private MALContextFactory malFactory; private MALContext mal; private MALProviderManager providerMgr; private MALProvider primaryMALServiceProvider = null; private MALProvider secondaryMALServiceProvider = null; - private final SingleConnectionDetails primaryConnectionDetails = new SingleConnectionDetails(); private SingleConnectionDetails secondaryConnectionDetails = null; - private static ServicesConnectionDetails globalProvidersDetailsPrimary = new ServicesConnectionDetails(); - private static ServicesConnectionDetails globalProvidersDetailsSecondary = new ServicesConnectionDetails(); /** * Getter for the primaryConnectionDetails object. @@ -190,12 +191,12 @@ public MALProvider startService(String serviceName, MALService malService, boole if (shouldInitUriFiles()) { String path = System.getProperty(HelperMisc.PROP_PROVIDERURIS_PATH, HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME); - + this.writeURIsOnFile(primaryConnectionDetails, serviceName, path); } - globalProvidersDetailsPrimary.add(serviceName, primaryConnectionDetails); + GLOBAL_PROVIDERS_DETAILS_PRIMARY.add(serviceName, primaryConnectionDetails); primaryMALServiceProvider = serviceProvider; @@ -226,16 +227,15 @@ public MALProvider startService(String serviceName, MALService malService, boole .getDomain(), serviceKey}); - if (shouldInitUriFiles()) { String pathSec = System.getProperty(HelperMisc.PROP_PROVIDERURIS_SEC_PATH, HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME); - + this.writeURIsOnFile(secondaryConnectionDetails, serviceName, pathSec); } - globalProvidersDetailsSecondary.add(serviceName, secondaryConnectionDetails); + GLOBAL_PROVIDERS_DETAILS_SECONDARY.add(serviceName, secondaryConnectionDetails); secondaryMALServiceProvider = serviceProvider2; } @@ -295,8 +295,7 @@ public void closeAll() { } /** - * Indicates whether the URI Files should be initialised. - * Defaults to false. + * Indicates whether the URI Files should be initialised. Defaults to false. * * @return true if URI Files should be initialised */ @@ -308,8 +307,8 @@ public static boolean shouldInitUriFiles() { * Clears the URI links file if its generation is enabled */ public static void resetURILinks() { - globalProvidersDetailsPrimary.reset(); - globalProvidersDetailsSecondary.reset(); + GLOBAL_PROVIDERS_DETAILS_PRIMARY.reset(); + GLOBAL_PROVIDERS_DETAILS_SECONDARY.reset(); if (shouldInitUriFiles()) { String path = System.getProperty(HelperMisc.PROP_PROVIDERURIS_PATH, @@ -335,21 +334,23 @@ public static void resetURILinks() { } /** - * Get primary connection interface details of all providers in the application. - * + * Get primary connection interface details of all providers in the + * application. + * * @return Primary connection details of all providers in the application. */ public static ServicesConnectionDetails getGlobalProvidersDetailsPrimary() { - return globalProvidersDetailsPrimary; + return GLOBAL_PROVIDERS_DETAILS_PRIMARY; } /** - * Get secondary connection interface details of all providers in the application. - * + * Get secondary connection interface details of all providers in the + * application. + * * @return Secondary connection details of all providers in the application. */ public static ServicesConnectionDetails getGlobalProvidersDetailsSecondary() { - return globalProvidersDetailsSecondary; + return GLOBAL_PROVIDERS_DETAILS_SECONDARY; } /** From 7d4d4a230ea77862eea43947d8289173947bade9 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sat, 29 Oct 2022 13:01:55 +0200 Subject: [PATCH 121/173] Apps Launcher service support for multiple folders with Apps --- .../sm/impl/provider/AppsLauncherManager.java | 144 ++++++++++++------ .../AppsLauncherProviderServiceImpl.java | 30 ++-- .../PackageManagementProviderServiceImpl.java | 4 +- .../NanoSatMOSupervisor.java | 2 + .../esa/mo/nmf/nmfpackage/Deployment.java | 4 + .../mo/nmf/nmfpackage/NMFPackageManager.java | 18 ++- 6 files changed, 136 insertions(+), 66 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index fe0323758..d254d9c60 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -92,7 +92,7 @@ public class AppsLauncherManager extends DefinitionsManager { /** * Location of the apps folder, relative to the MO Supervisor */ - private File appsFolderPath; + private ArrayList foldersWithApps = new ArrayList<>(); private final HashMap handlers = new HashMap<>(); @@ -100,17 +100,22 @@ public class AppsLauncherManager extends DefinitionsManager { public AppsLauncherManager(COMServicesProvider comServices) { super(comServices); + File appsFolderPath; + File defaultAppsFolder = new File(DEFAULT_APPS_FOLDER_PATH); // If there is a property for that, then use it!! if (System.getProperty(FOLDER_LOCATION_PROPERTY) != null) { appsFolderPath = new File(System.getProperty(FOLDER_LOCATION_PROPERTY)); } else { - LOGGER.log(Level.INFO, - "Property not set: {0} \nUsing default apps directory: {1}", + LOGGER.log(Level.INFO, "Property not set: {0} \nUsing default apps directory: {1}", new Object[]{FOLDER_LOCATION_PROPERTY, DEFAULT_APPS_FOLDER_PATH}); - appsFolderPath = new File(DEFAULT_APPS_FOLDER_PATH); + appsFolderPath = defaultAppsFolder; } + // In the future, we will support multiple folders containing Apps + // Example: If there are Apps installed in an external memory device + this.addFolderWithApps(appsFolderPath); + if (MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION) != null && MALContextFactory.lookupArea(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NAME, @@ -218,6 +223,7 @@ protected Long addApp(final AppDetails definition, final ObjectId source, final private Long readAppObjectId(final AppDetails definition) throws IOException { Long objId; + File appsFolderPath = this.getAppsFolderPath(definition.getName()); File fileProps = new File(appsFolderPath.getCanonicalPath() + File.separator + definition. getName().getValue() + File.separator + definition.getExtraInfo()); @@ -230,8 +236,20 @@ private Long readAppObjectId(final AppDetails definition) throws IOException { return objId; } - private LongList addAppToArchive(final AppDetails definition, final ObjectId source, final URI uri, Long objId, - Long related) throws MALException, MALInteractionException { + private File getAppsFolderPath(Identifier appIdentifier) { + String appName = appIdentifier.getValue(); + + for (File appsFolderPath : foldersWithApps) { + File appFolder = new File(appsFolderPath + File.separator + appName); + if (appFolder.exists()) { + return appsFolderPath; + } + } + return foldersWithApps.get(0); // Use the default folder! + } + + private LongList addAppToArchive(final AppDetails definition, final ObjectId source, + final URI uri, Long objId, Long related) throws MALException, MALInteractionException { AppDetailsList defs = new AppDetailsList(); defs.add(definition); ArchiveDetailsList archDetails = HelperArchive.generateArchiveDetailsList(related, source, uri); @@ -262,15 +280,14 @@ protected boolean update(final Long objId, final AppDetails definition, return success; } - private void updateAppInArchive(final Long objId, final AppDetails definition, final MALInteraction interaction) - throws MALException, MALInteractionException { + private void updateAppInArchive(final Long objId, final AppDetails definition, + final MALInteraction interaction) throws MALException, MALInteractionException { AppDetailsList defs = new AppDetailsList(); defs.add(definition); IdentifierList domain = ConfigurationProviderSingleton.getDomain(); - ArchiveDetails archiveDetails = HelperArchive.getArchiveDetailsFromArchive(super. - getArchiveService(), - AppsLauncherHelper.APP_OBJECT_TYPE, domain, objId); + ArchiveDetails archiveDetails = HelperArchive.getArchiveDetailsFromArchive( + super.getArchiveService(), AppsLauncherHelper.APP_OBJECT_TYPE, domain, objId); if (archiveDetails == null) { throw new MALException("No object present in archive."); } @@ -291,18 +308,39 @@ protected boolean delete(Long objId) { } protected boolean refreshAvailableAppsList(final URI providerURI) { - // Go to all the "apps folder" and check if there are new folders - // get all the files from a directory - File[] fList = appsFolderPath.listFiles(); + boolean anyChanges = false; + ArrayList fList = new ArrayList<>(); - if (fList == null) { - LOGGER.log(Level.SEVERE, "The directory could not be found: {0} (full path: {1})", - new Object[]{appsFolderPath.toString(), appsFolderPath.getAbsolutePath()}); + for (File appsFolderPath : foldersWithApps) { + if (appsFolderPath == null) { + LOGGER.log(Level.SEVERE, "The appsFolderPath parameter is null!"); - return false; + continue; + } + + File[] list = appsFolderPath.listFiles(); + + if (list != null) { + for (int i = 0; i < list.length; i++) { + File appFolder = list[i]; + if ((appFolder != null) && appFolder.isDirectory()) { + fList.add(appFolder); + } + } + } } - boolean anyChanges = false; + // Go to all the "apps folder" and check if there are new folders + // get all the files from a directory + //File[] fList = appsFolderPath.listFiles(); +/* + if (fList == null) { + LOGGER.log(Level.SEVERE, "The directory could not be found: {0} (full path: {1})", + new Object[]{appsFolderPath.toString(), appsFolderPath.getAbsolutePath()}); + + return false; + } + */ AppDetailsList apps = new AppDetailsList(); for (File folder : fList) { // Roll all the apps inside the apps folder @@ -320,11 +358,11 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { for (AppDetails singleApp : apps) { Long id = super.list(singleApp.getName()); AppDetails previousAppDetails = this.get(id); + String name = singleApp.getName().getValue(); // It didn't exist... if (previousAppDetails == null) { - LOGGER.log(Level.INFO, - "New app found! Adding new app: {0}", singleApp.getName().getValue()); + LOGGER.log(Level.INFO, "New app found! Adding new app: {0}", name); // Either is the first time running or it is a newly installed app! ObjectId source = null; @@ -341,10 +379,9 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { } // Then we have to update it... - LOGGER.log(Level.INFO, - "New update found on app: {0}\nPrevious: {1}\nNew: {2}", - new Object[]{singleApp.getName().getValue(), - previousAppDetails, singleApp}); + LOGGER.log(Level.INFO, "New update found on app: {0}" + + "\nPrevious: {1}\nNew: {2}", + new Object[]{name, previousAppDetails, singleApp}); this.update(id, singleApp, null); anyChanges = true; @@ -354,13 +391,14 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { // Also needs to check if we removed a folder! LongList ids = this.listAll(); AppDetailsList localApps = this.getAll(); - + for (int i = 0; i < ids.size(); i++) { // Roll all the apps inside the apps folder - AppDetails localApp = localApps.get(i); + String name = localApps.get(i).getName().getValue(); boolean appStillIntact = false; + for (File folder : fList) { // Roll all the apps inside the apps folder if (folder.isDirectory()) { - if (folder.getName().equals(localApp.getName().getValue())) { + if (folder.getName().equals(name)) { for (File file : folder.listFiles()) { // Roll all the files inside each app folder // Check if the folder contains the provider properties if (HelperMisc.PROVIDER_PROPERTIES_FILE.equals(file.getName())) { @@ -374,9 +412,7 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { } if (!appStillIntact) { - LOGGER.log(Level.INFO, - "The app has been removed: {0}", localApp.getName().getValue()); - + LOGGER.log(Level.INFO, "The app has been removed: {0}", name); this.delete(ids.get(i)); anyChanges = true; } @@ -401,7 +437,7 @@ protected boolean isAppRunning(final Long appId) { return this.get(appId).getRunning(); } - protected String[] assembleCommand(final String workDir, final String appName, + protected String[] assembleCommand(final String workDir, final String appName, final String runAs, final String prefix, final String[] env) { ArrayList ret = new ArrayList<>(); String trimmedAppName = appName.replaceAll("space-app-", ""); @@ -437,12 +473,12 @@ protected String[] assembleCommand(final String workDir, final String appName, return ret.toArray(new String[0]); } - protected String[] assembleAppStopCommand(final String workDir, + protected String[] assembleAppStopCommand(final String workDir, final String appName, final String runAs, final String[] env) { return assembleCommand(workDir, appName, runAs, "stop_", env); } - protected String[] assembleAppStartCommand(final String workDir, + protected String[] assembleAppStartCommand(final String workDir, final String appName, final String runAs, final String[] env) { return assembleCommand(workDir, appName, runAs, "start_", env); } @@ -486,6 +522,7 @@ protected void startAppProcess(final ProcessExecutionHandler handler, String appName = app.getName().getValue(); // Go to the folder where the app are installed + File appsFolderPath = this.getAppsFolderPath(app.getName()); final File appFolder = new File(appsFolderPath + File.separator + appName); Map env = assembleAppLauncherEnvironment(directoryServiceURI); String[] appLauncherCommand = assembleAppStartCommand( @@ -497,7 +534,7 @@ protected void startAppProcess(final ProcessExecutionHandler handler, final ProcessBuilder pb = new ProcessBuilder(appLauncherCommand); pb.environment().clear(); pb.environment().putAll(env); - + pb.directory(appFolder); LOGGER.log(Level.INFO, "Initializing ''{0}'' app in dir: {1}, using launcher command: {2}", @@ -536,11 +573,12 @@ protected boolean killAppProcess(final Long appInstId, MALInteraction interactio return true; } - protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interaction, + protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interaction, boolean onlyNativeComponent) throws IOException, MALInteractionException, MALException { AppDetails app = (AppDetails) this.getDef(appInstId); // get it from the list of available apps // Go to the folder where the app is installed + File appsFolderPath = this.getAppsFolderPath(app.getName()); File appFolder = new File(appsFolderPath + File.separator + app.getName().getValue()); Map env = assembleAppLauncherEnvironment(""); String[] appLauncherCommand = assembleAppStopCommand(appFolder.getAbsolutePath(), @@ -564,7 +602,7 @@ protected boolean stopNativeApp(final Long appInstId, StopAppInteraction interac if (!exitCleanly) { LOGGER.log(Level.WARNING, "App {0} stop script did not exit within the timeout ({1} ms). " - + "Killing the stop script and forcing the app exit.", + + "Killing the stop script and forcing the app exit.", new Object[]{app.getName().getValue(), APP_STOP_TIMEOUT}); proc.destroyForcibly(); } @@ -598,7 +636,7 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer // Stop the app... ObjectType objType = AppsLauncherHelper.STOPAPP_OBJECT_TYPE; Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.INFO, - "Sending event to app: {0} (Name: ''{1}'')", + "Sending event to app: {0} (Name: ''{1}'')", new Object[]{appInstId, appDirectoryServiceName}); MALInteraction malInt = (interaction != null) ? interaction.getInteraction() : null; this.setRunning(appInstId, false, malInt); @@ -607,7 +645,7 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer // Generate, store and publish the events to stop the App... Long objId = super.getCOMServices().getEventService() - .generateAndStoreEvent(objType, ConfigurationProviderSingleton.getDomain(), + .generateAndStoreEvent(objType, ConfigurationProviderSingleton.getDomain(), appDirectoryServiceName, appInstId, eventSource, malInt); URI uri = (malInt != null) ? malInt.getMessageHeader().getURIFrom() : new URI(""); @@ -616,7 +654,7 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer try { IdentifierList eventBodies = new IdentifierList(1); eventBodies.add(appDirectoryServiceName); - super.getCOMServices().getEventService().publishEvent(uri, + super.getCOMServices().getEventService().publishEvent(uri, objId, objType, appInstId, eventSource, eventBodies); } catch (IOException ex) { LOGGER.log(Level.SEVERE, null, ex); @@ -653,6 +691,7 @@ protected void stopApps(final LongList appInstIds, final IdentifierList appDirec if (osValidator.isWindows()) { fileExt = ".bat"; } + File appsFolderPath = this.getAppsFolderPath(curr.getName()); File stopScript = new File(appsFolderPath + File.separator + curr.getName().getValue() + File.separator + "stop_" + curr.getName().getValue() + fileExt); boolean stopExists = stopScript.exists(); @@ -778,16 +817,16 @@ private AppDetails readAppDescriptor(final String appName, final File properties props.load(inputStream); app.setExtraInfo(HelperMisc.PROVIDER_PROPERTIES_FILE); - String category = (props.getProperty(HelperMisc.APP_CATEGORY) != null) ? - props.getProperty(HelperMisc.APP_CATEGORY) : "-"; - String version = (props.getProperty(HelperMisc.APP_VERSION) != null) ? - props.getProperty(HelperMisc.APP_VERSION) : "-"; - String copyright = (props.getProperty(HelperMisc.APP_COPYRIGHT) != null) ? - props.getProperty(HelperMisc.APP_COPYRIGHT) : "-"; - String description = (props.getProperty(HelperMisc.APP_DESCRIPTION) != null) ? - props.getProperty(HelperMisc.APP_DESCRIPTION) : "-"; - String user = (props.getProperty(HelperMisc.APP_USER) != null) ? - props.getProperty(HelperMisc.APP_USER) + String category = (props.getProperty(HelperMisc.APP_CATEGORY) != null) + ? props.getProperty(HelperMisc.APP_CATEGORY) : "-"; + String version = (props.getProperty(HelperMisc.APP_VERSION) != null) + ? props.getProperty(HelperMisc.APP_VERSION) : "-"; + String copyright = (props.getProperty(HelperMisc.APP_COPYRIGHT) != null) + ? props.getProperty(HelperMisc.APP_COPYRIGHT) : "-"; + String description = (props.getProperty(HelperMisc.APP_DESCRIPTION) != null) + ? props.getProperty(HelperMisc.APP_DESCRIPTION) : "-"; + String user = (props.getProperty(HelperMisc.APP_USER) != null) + ? props.getProperty(HelperMisc.APP_USER) : null; // Since the user change is only implemented on linux this dependency is fine app.setCategory(new Identifier(category)); @@ -805,4 +844,9 @@ private AppDetails readAppDescriptor(final String appName, final File properties return app; } + public final void addFolderWithApps(File folder) { + if (!foldersWithApps.contains(folder)) { + foldersWithApps.add(folder); + } + } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index 63baa2ab9..aba266f3f 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -296,28 +296,29 @@ public void runApp(LongList appInstIds, MALInteraction interaction) // Run the apps! for (int i = 0; i < appInstIds.size(); i++) { try { - String directoryServiceURI; + SingleConnectionDetails details; + if (directoryService.getConnection().getSecondaryConnectionDetails() != null) { // For applications in space, the primary URI is MALSPP, and secondary a MALTCP - directoryServiceURI - = directoryService.getConnection().getSecondaryConnectionDetails().getProviderURI().toString(); + details = directoryService.getConnection().getSecondaryConnectionDetails(); } else { - directoryServiceURI - = directoryService.getConnection().getConnectionDetails().getProviderURI().toString(); + details = directoryService.getConnection().getConnectionDetails(); } + String directoryServiceURI = details.getProviderURI().toString(); AppDetails app = this.manager.get(appInstIds.get(i)); ObjectType objType = AppsLauncherHelper.STARTAPP_OBJECT_TYPE; ObjectId eventSource = this.manager.getCOMServices().getActivityTrackingService() .storeCOMOperationActivity(interaction, null); Logger.getLogger(AppsLauncherManager.class.getName()).log(Level.INFO, - "Generating StartApp event for app: {0} (Name: ''{1}'')", new Object[]{appInstIds.get(i), app.getName()}); - this.manager.getCOMServices().getEventService() - .generateAndStoreEvent(objType, ConfigurationProviderSingleton.getDomain(), app.getName(), + "Generating StartApp event for app: {0} (Name: ''{1}'')", + new Object[]{appInstIds.get(i), app.getName()}); + this.manager.getCOMServices().getEventService().generateAndStoreEvent( + objType, ConfigurationProviderSingleton.getDomain(), app.getName(), appInstIds.get(i), eventSource, interaction); - manager.startAppProcess(new ProcessExecutionHandler(new CallbacksImpl(), appInstIds.get(i)), - interaction, directoryServiceURI); + manager.startAppProcess(new ProcessExecutionHandler(new CallbacksImpl(), + appInstIds.get(i)), interaction, directoryServiceURI); } catch (IOException ex) { UIntegerList intIndexList = new UIntegerList(); intIndexList.add(new UInteger(i)); @@ -644,6 +645,14 @@ public COMService getCOMService() { return AppsLauncherHelper.APPSLAUNCHER_SERVICE; } + public void refresh() { + manager.refreshAvailableAppsList(new URI("")); + } + + public void addFolderWithApps(java.io.File folder){ + manager.addFolderWithApps(folder); + } + public static final class PublishInteractionListener implements MALPublishInteractionListener { @Override @@ -663,7 +672,6 @@ public void publishErrorReceived(final MALMessageHeader header, final MALErrorBo public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) throws MALException { LOGGER.fine("PublishInteractionListener::publishRegisterAckReceived"); -// Logger.getLogger(AppsLauncherProviderServiceImpl.class.getName()).log(Level.INFO, "Registration Ack: {0}", header.toString()); } @Override diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java index 8160ff986..d112db0bf 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java @@ -321,8 +321,8 @@ public void uninstall(final IdentifierList names, final BooleanList keepConfigur } @Override - public void upgrade(final IdentifierList names, final UpgradeInteraction interaction) - throws MALInteractionException, MALException { + public void upgrade(final IdentifierList names, + final UpgradeInteraction interaction) throws MALInteractionException, MALException { interaction.sendAcknowledgement(); UIntegerList unkIndexList = new UIntegerList(); diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index e2be627a3..635766c8c 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -34,6 +34,7 @@ import esa.mo.nmf.MCRegistration; import esa.mo.nmf.MissionPlanningNMFAdapter; import esa.mo.nmf.NMFException; +import esa.mo.nmf.nmfpackage.Deployment; import esa.mo.platform.impl.util.PlatformServicesConsumer; import esa.mo.reconfigurable.provider.PersistProviderConfiguration; import esa.mo.sm.impl.provider.AppsLauncherProviderServiceImpl; @@ -105,6 +106,7 @@ public void init(MonitorAndControlNMFAdapter mcAdapter, this.comServices.initArchiveSync(); super.reconfigurableServices.add(this.appsLauncherService); this.appsLauncherService.setStdQuotaPerApp(stdQuota); + this.appsLauncherService.addFolderWithApps(Deployment.getNMFAppsDir()); this.comServices.getArchiveSyncService().setStdQuota(stdQuota); this.startMCServices(mcAdapter); this.initPlatformServices(comServices); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index cdd1c947b..39a97bacf 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -59,6 +59,10 @@ public static File getInstallationsTrackerDir() { return folder; } + public static File getNMFAppsDir() { + return new File(DIR_APPS); + } + public static File getNMFRootDir() { if (pathNMF != null) { return new File(pathNMF); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index ad5c50ff3..d698b0454 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -162,6 +162,10 @@ public void install(final String packageLocation, File receiptFile = new File(receiptPath); metadata.store(receiptFile); + if (appsLauncher != null) { + appsLauncher.refresh(); + } + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully installed from: {0}", packageLocation); @@ -215,9 +219,13 @@ public void uninstall(final Metadata packageMetadata, "The receipt file could not be deleted from: " + receiptsPath); } + if (appsLauncher != null) { + appsLauncher.refresh(); + } + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully uninstalled: " + packageName); - + System.out.printf(SEPARATOR); } @@ -317,6 +325,10 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx // Store a copy of the newReceipt to know that it has been installed! newPackMetadata.store(oldReceiptFile); + if (appsLauncher != null) { + appsLauncher.refresh(); + } + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully upgraded from location: " + packageLocation); @@ -525,8 +537,8 @@ private void stopAppIfRunning(String name) { appsLauncher.stopApp(runningApp, null); } } catch (MALInteractionException ex) { - Logger.getLogger(NMFPackageManager.class.getName()).log( - Level.INFO, "The " + name + " App was not found!"); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "The " + name + " App was not found in the Directory service!"); } catch (MALException ex) { Logger.getLogger(NMFPackageManager.class.getName()).log( Level.SEVERE, "(2) Something went wrong...", ex); From ef7c1b8fea4aa2b672864df45e013cd6e21759c8 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sat, 29 Oct 2022 13:42:18 +0200 Subject: [PATCH 122/173] Better error handling --- .../java/esa/mo/sm/impl/provider/AppsLauncherManager.java | 2 +- .../main/java/esa/mo/sm/impl/util/ClosingAppListener.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index d254d9c60..854f7e731 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -665,7 +665,7 @@ protected void stopNMFApp(final Long appInstId, final Identifier appDirectorySer try { listener.waitForAppClosing(APP_STOP_TIMEOUT); } catch (InterruptedException ex) { - LOGGER.log(Level.WARNING, null, ex); + LOGGER.log(Level.WARNING, "The listener timedout!", ex); } } } diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java index 89bd78629..40d9ea00e 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/util/ClosingAppListener.java @@ -43,7 +43,7 @@ public class ClosingAppListener extends EventReceivedListener { private final EventConsumerServiceImpl eventService; private final Long objId; private boolean appClosed; - private final Object semaphore; + private final Object semaphore; // This should be done with a proper Semaphore... :/ public ClosingAppListener(final StopAppInteraction interaction, final EventConsumerServiceImpl eventService, final Long objId) { @@ -65,7 +65,9 @@ public void onDataReceived(EventCOMObject eventCOMObject) { LOGGER.log(Level.INFO, "The app with objId {0} is now stopped!", objId); try { // Send update to consumer stating that the app is stopped - interaction.sendUpdate(objId); + if (interaction != null) { + interaction.sendUpdate(objId); + } } catch (MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, null, ex); } From 7f1e27673ed99f09058bf700c74bbddf3ff3891a Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sat, 29 Oct 2022 17:51:02 +0200 Subject: [PATCH 123/173] Adds a timestamp to the service inits() --- .../connections/ConnectionSharedBroker.java | 13 +- .../ActivityTrackingProviderServiceImpl.java | 14 +- .../provider/ArchiveProviderServiceImpl.java | 12 +- .../ArchiveSyncProviderServiceImpl.java | 4 +- .../provider/EventProviderServiceImpl.java | 7 +- .../ConfigurationProviderServiceImpl.java | 11 +- .../DirectoryProviderServiceImpl.java | 213 +++++++++++++----- .../provider/ActionProviderServiceImpl.java | 10 +- .../AggregationProviderServiceImpl.java | 12 +- .../provider/AlertProviderServiceImpl.java | 59 ++--- .../provider/CheckProviderServiceImpl.java | 7 +- .../ParameterProviderServiceImpl.java | 8 +- .../StatisticProviderServiceImpl.java | 51 +++-- .../PlanDistributionProviderServiceImpl.java | 8 +- .../provider/PlanEditProviderServiceImpl.java | 8 +- ...anExecutionControlProviderServiceImpl.java | 8 +- ...ormationManagementProviderServiceImpl.java | 8 +- .../PlanningRequestProviderServiceImpl.java | 8 +- ...ficialIntelligenceProviderServiceImpl.java | 5 +- .../AutonomousADCSProviderServiceImpl.java | 5 +- .../gen/CameraProviderServiceImpl.java | 5 +- .../gen/ClockProviderServiceImpl.java | 5 +- .../provider/gen/GPSProviderServiceImpl.java | 49 +++- ...pticalDataReceiverProviderServiceImpl.java | 5 +- .../gen/PowerControlProviderServiceImpl.java | 5 +- ...ftwareDefinedRadioProviderServiceImpl.java | 5 +- .../AppsLauncherProviderServiceImpl.java | 6 +- .../CommandExecutorProviderServiceImpl.java | 6 +- .../HeartbeatProviderServiceImpl.java | 11 +- .../PackageManagementProviderServiceImpl.java | 9 +- .../GPSProviderServiceWithTLEImpl.java | 4 - 31 files changed, 401 insertions(+), 180 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionSharedBroker.java b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionSharedBroker.java index 64a8b115f..a4aa9259a 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionSharedBroker.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionSharedBroker.java @@ -25,7 +25,7 @@ import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; -import java.util.Hashtable; +import java.util.HashMap; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.mal.MALContext; @@ -72,9 +72,14 @@ public MALBrokerBinding startBroker(String brokerName, Blob authenticationId) th brokerMgr = mal.createBrokerManager(); MALBroker sharedBroker = brokerMgr.createBroker(); - MALBrokerBinding brokerBinding = brokerMgr.createBrokerBinding(sharedBroker, brokerName, System.getProperties() - .getProperty("org.ccsds.moims.mo.mal.transport.default.protocol"), null == authenticationId ? new Blob("" - .getBytes()) : authenticationId, new QoSLevel[]{QoSLevel.ASSURED}, new UInteger(1), new Hashtable()); + MALBrokerBinding brokerBinding = brokerMgr.createBrokerBinding( + sharedBroker, + brokerName, + System.getProperties().getProperty("org.ccsds.moims.mo.mal.transport.default.protocol"), + null == authenticationId ? new Blob("".getBytes()) : authenticationId, + new QoSLevel[]{QoSLevel.ASSURED}, + new UInteger(1), + new HashMap()); Logger.getLogger(ConnectionSharedBroker.class.getName()).log(Level.INFO, "Shared Broker URI: {0}", brokerBinding .getURI()); diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ActivityTrackingProviderServiceImpl.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ActivityTrackingProviderServiceImpl.java index 7ac6eea48..7df8ff84c 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ActivityTrackingProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ActivityTrackingProviderServiceImpl.java @@ -71,8 +71,9 @@ public class ActivityTrackingProviderServiceImpl { * @param eventService Event service provider * @throws MALException On initialization error. */ - public synchronized void init(ArchiveProviderServiceImpl archiveService, EventProviderServiceImpl eventService) - throws MALException { + public synchronized void init(ArchiveProviderServiceImpl archiveService, + EventProviderServiceImpl eventService) throws MALException { + long timestamp = System.currentTimeMillis(); if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { @@ -83,8 +84,8 @@ public synchronized void init(ArchiveProviderServiceImpl archiveService, EventPr COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION).getServiceByName( - ActivityTrackingHelper.ACTIVITYTRACKING_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) + .getServiceByName(ActivityTrackingHelper.ACTIVITYTRACKING_SERVICE_NAME) == null) { ActivityTrackingHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -94,8 +95,9 @@ public synchronized void init(ArchiveProviderServiceImpl archiveService, EventPr running = true; initialiased = true; - Logger.getLogger(ActivityTrackingProviderServiceImpl.class.getName()).info("Activity Tracking service READY"); - + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(ActivityTrackingProviderServiceImpl.class.getName()).info( + "Activity Tracking service: READY! (" + timestamp + " ms)"); } //------------------------------------------------------------------------------ diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveProviderServiceImpl.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveProviderServiceImpl.java index 28d7fc488..c00425baf 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveProviderServiceImpl.java @@ -75,6 +75,8 @@ public class ArchiveProviderServiceImpl extends ArchiveInheritanceSkeleton { * @throws MALException On initialization error. */ public synchronized void init(EventProviderServiceImpl eventService) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -84,8 +86,8 @@ public synchronized void init(EventProviderServiceImpl eventService) throws MALE COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION).getServiceByName( - ArchiveHelper.ARCHIVE_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) + .getServiceByName(ArchiveHelper.ARCHIVE_SERVICE_NAME) == null) { ArchiveHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -102,7 +104,9 @@ public synchronized void init(EventProviderServiceImpl eventService) throws MALE ArchiveHelper.ARCHIVE_SERVICE, false, this); running = true; initialiased = true; - Logger.getLogger(ArchiveProviderServiceImpl.class.getName()).info("Archive service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(ArchiveProviderServiceImpl.class.getName()).info( + "Archive service: READY! (" + timestamp + " ms)"); } /** @@ -120,7 +124,7 @@ public void close() { running = false; } catch (MALException ex) { Logger.getLogger(ArchiveProviderServiceImpl.class.getName()).log(Level.WARNING, - "Exception during close down of the provider {0}", ex); + "Exception during close down of the provider {0}", ex); } } diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java index da54ae059..e506ae6b9 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveSyncProviderServiceImpl.java @@ -159,6 +159,7 @@ public void setStdQuota(Quota quota) { * @throws MALException if initialization error. */ public synchronized void init(ArchiveManager manager) throws MALException { + long timestamp = System.currentTimeMillis(); if (!initialiased) { if (null == MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION)) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -184,7 +185,8 @@ public synchronized void init(ArchiveManager manager) throws MALException { archiveSyncServiceProvider = connection.startService(ArchiveSyncHelper.ARCHIVESYNC_SERVICE_NAME.toString(), ArchiveSyncHelper.ARCHIVESYNC_SERVICE, false, this); initialiased = true; - LOGGER.info("ArchiveSync service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("ArchiveSync service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java index 05a9698be..412463f6a 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/EventProviderServiceImpl.java @@ -87,6 +87,8 @@ public class EventProviderServiceImpl extends EventInheritanceSkeleton { * @throws MALException On initialization error. */ public synchronized void init(ArchiveProviderServiceImpl archiveService) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -117,8 +119,9 @@ public synchronized void init(ArchiveProviderServiceImpl archiveService) throws EventHelper.EVENT_SERVICE, this); running = true; initialiased = true; - Logger.getLogger(EventProviderServiceImpl.class.getName()).log(Level.INFO, "Event service: READY"); - + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(EventProviderServiceImpl.class.getName()).log(Level.INFO, + "Event service: READY! (" + timestamp + " ms)"); } public void setArchiveService(ArchiveProviderServiceImpl archiveService) { diff --git a/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/ConfigurationProviderServiceImpl.java b/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/ConfigurationProviderServiceImpl.java index 9bc27b6a9..dbbbfcbf5 100644 --- a/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/ConfigurationProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/ConfigurationProviderServiceImpl.java @@ -74,12 +74,11 @@ public class ConfigurationProviderServiceImpl extends ConfigurationInheritanceSk private MALProvider configurationServiceProvider; private boolean initialiased = false; private boolean running = false; - private final HashMap configs = new HashMap(); private final ConnectionProvider connection = new ConnectionProvider(); private final Random random = new Random(); private COMServicesProvider comServices; - private final HashMap serviceConfigurations = new HashMap(); - private final HashMap providerConfigurations = new HashMap(); + private final HashMap serviceConfigurations = new HashMap<>(); + private final HashMap providerConfigurations = new HashMap<>(); /** * creates the MAL objects, the publisher used to create updates and starts @@ -89,6 +88,8 @@ public class ConfigurationProviderServiceImpl extends ConfigurationInheritanceSk * @throws MALException On initialisation error. */ public synchronized void init(COMServicesProvider comServices) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -121,7 +122,9 @@ public synchronized void init(COMServicesProvider comServices) throws MALExcepti running = true; initialiased = true; - Logger.getLogger(ConfigurationProviderServiceImpl.class.getName()).info("Configuration service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(ConfigurationProviderServiceImpl.class.getName()).info( + "Configuration service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java b/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java index 3df05a424..809027e47 100644 --- a/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java @@ -76,50 +76,52 @@ /** * Directory service Provider. */ -public class DirectoryProviderServiceImpl extends DirectoryInheritanceSkeleton { - - public static final String CHAR_S2G = "s2g"; - private static final Logger LOGGER = Logger.getLogger(DirectoryProviderServiceImpl.class.getName()); - - private MALProvider directoryServiceProvider; - private boolean initialiased = false; - private boolean running = false; - private final ConnectionProvider connection = new ConnectionProvider(); - protected final Map providersAvailable = new ConcurrentHashMap<>(); - protected final Object MUTEX = new Object(); - private COMServicesProvider comServices; - - private static AddressDetails getServiceAddressDetails(final SingleConnectionDetails conn) { - QoSLevelList qos = new QoSLevelList(); - qos.add(QoSLevel.ASSURED); - NamedValueList qosProperties = new NamedValueList(); // Nothing here for now... - - AddressDetails serviceAddress = new AddressDetails(); - serviceAddress.setSupportedLevels(qos); - serviceAddress.setQoSproperties(qosProperties); - serviceAddress.setPriorityLevels(new UInteger(1)); // hum? - serviceAddress.setServiceURI(conn.getProviderURI()); - serviceAddress.setBrokerURI(conn.getBrokerURI()); - serviceAddress.setBrokerProviderObjInstId(null); - - return serviceAddress; +public class DirectoryProviderServiceImpl extends DirectoryInheritanceSkeleton +{ + + public static final String CHAR_S2G = "s2g"; + private static final Logger LOGGER + = Logger.getLogger(DirectoryProviderServiceImpl.class.getName()); + + private MALProvider directoryServiceProvider; + private boolean initialiased = false; + private boolean running = false; + private final ConnectionProvider connection = new ConnectionProvider(); + protected final Map providersAvailable + = new ConcurrentHashMap<>(); + protected final Object MUTEX = new Object(); + private COMServicesProvider comServices; + + /** + * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * + * @param comServices + * @throws MALException On initialisation error. + */ + public synchronized void init(COMServicesProvider comServices) throws MALException + { + long timestamp = System.currentTimeMillis(); + + if (!initialiased) { + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { + COMHelper.deepInit(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, + CommonHelper.COMMON_AREA_VERSION) == null) { + CommonHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) + .getServiceByName(DirectoryHelper.DIRECTORY_SERVICE_NAME) == null) { + DirectoryHelper.init(MALContextFactory.getElementFactoryRegistry()); + } } - private static AddressDetailsList findAddressDetailsListOfService(final ServiceKey key, - final ServiceCapabilityList capabilities) { - if (key == null) { - return null; - } - - // Iterate all capabilities until you find the serviceName - for (ServiceCapability capability : capabilities) { - if (capability != null) { - if (key.equals(capability.getServiceKey())) { - return capability.getServiceAddresses(); - } - } - } - return null; // Not found! } @@ -127,15 +129,22 @@ public static ServiceKey generateServiceKey(final IntegerList keys) { return new ServiceKey(new UShort(keys.get(0)), new UShort(keys.get(1)), new UOctet(keys.get(2).shortValue())); } - /* - public HashMap getListOfProviders() { - final HashMap list = new HashMap(); - - synchronized (MUTEX) { - list.putAll(providersAvailable); - } - - return list; + directoryServiceProvider = connection.startService( + DirectoryHelper.DIRECTORY_SERVICE_NAME.toString(), + DirectoryHelper.DIRECTORY_SERVICE, false, this); + + running = true; + initialiased = true; + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Directory service: READY! (" + timestamp + " ms)"); + } + + @Override + public ProviderSummaryList lookupProvider(final ServiceFilter filter, + final MALInteraction interaction) throws MALInteractionException, MALException + { + if (null == filter) { // Is the input null? + throw new IllegalArgumentException("filter argument must not be null"); } */ /** @@ -456,12 +465,104 @@ public void withdrawProvider(Long providerObjectKey, MALInteraction interaction) } } - public void withdrawAllProviders() throws MALInteractionException, MALException { - synchronized (MUTEX) { - for (Long key : providersAvailable.keySet()) { - withdrawProvider(key, null); - } + private static AddressDetails getServiceAddressDetails(final SingleConnectionDetails conn) + { + QoSLevelList qos = new QoSLevelList(); + qos.add(QoSLevel.ASSURED); + NamedValueList qosProperties = new NamedValueList(); // Nothing here for now... + + AddressDetails serviceAddress = new AddressDetails(); + serviceAddress.setSupportedLevels(qos); + serviceAddress.setQoSproperties(qosProperties); + serviceAddress.setPriorityLevels(new UInteger(1)); // hum? + serviceAddress.setServiceURI(conn.getProviderURI()); + serviceAddress.setBrokerURI(conn.getBrokerURI()); + serviceAddress.setBrokerProviderObjInstId(null); + + return serviceAddress; + } + + private static AddressDetailsList findAddressDetailsListOfService(final ServiceKey key, + final ServiceCapabilityList capabilities) + { + if (key == null) { + return null; + } + + // Iterate all capabilities until you find the serviceName + for (ServiceCapability capability : capabilities) { + if (capability != null) { + if (key.equals(capability.getServiceKey())) { + return capability.getServiceAddresses(); } + } + } + + return null; // Not found! + } + + public static ServiceKey generateServiceKey(final IntegerList keys) + { + return new ServiceKey(new UShort(keys.get(0)), new UShort(keys.get(1)), new UOctet( + keys.get(2).shortValue())); + } + + /** + * Closes all running threads and releases the MAL resources. + */ + public void close() + { + try { + if (null != directoryServiceProvider) { + directoryServiceProvider.close(); + } + + connection.closeAll(); + running = false; + } catch (MALException ex) { + LOGGER.log(Level.WARNING, + "Exception during close down of the provider {0}", ex); + } + } + + public ConnectionProvider getConnection() + { + return this.connection; + } + + public void withdrawAllProviders() throws MALInteractionException, MALException + { + synchronized (MUTEX) { + for(Long key : providersAvailable.keySet()) { + withdrawProvider(key, null); + } + } + } + + public PublishDetails loadURIs(final String providerName) + { + ServicesConnectionDetails primaryConnectionDetails = ConnectionProvider.getGlobalProvidersDetailsPrimary(); + ServicesConnectionDetails secondaryAddresses = ConnectionProvider.getGlobalProvidersDetailsSecondary(); + + // Services' connections + HashMap connsMap = primaryConnectionDetails.getServices(); + Object[] serviceNames = connsMap.keySet().toArray(); + + final ServiceCapabilityList capabilities = new ServiceCapabilityList(); + + // Iterate all the services and make them available... + for (Object serviceName : serviceNames) { + SingleConnectionDetails conn = connsMap.get((String) serviceName); + AddressDetails serviceAddress = DirectoryProviderServiceImpl.getServiceAddressDetails(conn); + AddressDetailsList serviceAddresses = new AddressDetailsList(); + serviceAddresses.add(serviceAddress); + ServiceKey key = DirectoryProviderServiceImpl.generateServiceKey(conn.getServiceKey()); + ServiceCapability capability = new ServiceCapability(); + capability.setServiceKey(key); + capability.setSupportedCapabilitySets(null); // "If NULL then all capabilities supported." + capability.setServiceProperties(new NamedValueList()); + capability.setServiceAddresses(serviceAddresses); + capabilities.add(capability); } public PublishDetails loadURIs(final String providerName) { diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionProviderServiceImpl.java index 60a8f57cb..67ca34407 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ActionProviderServiceImpl.java @@ -84,8 +84,10 @@ public class ActionProviderServiceImpl extends ActionInheritanceSkeleton impleme * @param actions * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, ActionInvocationListener actions) - throws MALException { + public synchronized void init(COMServicesProvider comServices, + ActionInvocationListener actions) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { @@ -128,7 +130,9 @@ public synchronized void init(COMServicesProvider comServices, ActionInvocationL manager = new ActionManager(comServices, actions); initialiased = true; - Logger.getLogger(ActionProviderServiceImpl.class.getName()).info("Action service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(ActionProviderServiceImpl.class.getName()).info( + "Action service READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java index c4c89ed91..f2f12fc0f 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AggregationProviderServiceImpl.java @@ -27,11 +27,8 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.TaskScheduler; import esa.mo.mc.impl.util.GroupRetrieval; -import esa.mo.mc.impl.util.MCServicesHelper; import esa.mo.reconfigurable.service.ConfigurationChangeListener; import esa.mo.reconfigurable.service.ReconfigurableService; - -import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -112,8 +109,9 @@ public class AggregationProviderServiceImpl extends AggregationInheritanceSkelet * @param parameterManager * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, ParameterManager parameterManager) - throws MALException { + public synchronized void init(COMServicesProvider comServices, ParameterManager parameterManager) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -168,7 +166,9 @@ public synchronized void init(COMServicesProvider comServices, ParameterManager */ initialiased = true; - Logger.getLogger(AggregationProviderServiceImpl.class.getName()).info("Aggregation service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(AggregationProviderServiceImpl.class.getName()).info( + "Aggregation service READY! (" + timestamp + " ms)"); } public ConnectionProvider getConnectionProvider() { diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AlertProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AlertProviderServiceImpl.java index 6e76e981f..b83dc267e 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AlertProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/AlertProviderServiceImpl.java @@ -93,6 +93,8 @@ public class AlertProviderServiceImpl extends AlertInheritanceSkeleton implement * @throws MALException On initialisation error. */ public synchronized void init(COMServicesProvider comServices) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { @@ -107,8 +109,8 @@ public synchronized void init(COMServicesProvider comServices) throws MALExcepti COMHelper.init(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(MCHelper.MC_AREA_NAME, MCHelper.MC_AREA_VERSION).getServiceByName( - AlertHelper.ALERT_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(MCHelper.MC_AREA_NAME, MCHelper.MC_AREA_VERSION) + .getServiceByName(AlertHelper.ALERT_SERVICE_NAME) == null) { AlertHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -126,7 +128,9 @@ public synchronized void init(COMServicesProvider comServices) throws MALExcepti groupService.init(manager.getArchiveService()); initialiased = true; - Logger.getLogger(AlertProviderServiceImpl.class.getName()).info("Alert service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(AlertProviderServiceImpl.class.getName()).info( + "Alert service READY! (" + timestamp + " ms)"); } /** @@ -256,8 +260,8 @@ public LongList enableGeneration(Boolean isGroupIds, InstanceBooleanPairList ena // requirement: 3.4.8.2.i (This part of the code is only reached if no error was raised) for (int index = 0; index < objIdToBeEnabled.size(); index++) { // requirement: 3.4.8.e and 3.4.8.f and 3.4.8.j - Long out = manager.setGenerationEnabled(objIdToBeEnabled.get(index), valueToBeEnabled.get(index), source, - connection.getConnectionDetails()); + Long out = manager.setGenerationEnabled(objIdToBeEnabled.get(index), + valueToBeEnabled.get(index), source, connection.getConnectionDetails()); output.add(out); } @@ -354,7 +358,7 @@ public ObjectInstancePairList addAlert(AlertCreationRequestList alertCreationReq for (AlertCreationRequest alertCreationRequest : alertCreationRequests) { //requirement: 3.4.10.2.a outPairLst.add(manager.add(alertCreationRequest.getName(), alertCreationRequest.getAlertDefDetails(), - source, connection.getConnectionDetails())); // requirement: 3.4.10.2.f + source, connection.getConnectionDetails())); // requirement: 3.4.10.2.f } if (configurationAdapter != null) { @@ -366,7 +370,7 @@ public ObjectInstancePairList addAlert(AlertCreationRequestList alertCreationReq @Override public LongList updateDefinition(LongList alertObjInstIds, AlertDefinitionDetailsList newAlertDefDetails, - MALInteraction interaction) throws MALInteractionException, MALException { + MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); @@ -404,8 +408,8 @@ public LongList updateDefinition(LongList alertObjInstIds, AlertDefinitionDetail // requirement: 3.4.11.2.e, 3.4.11.2.j for (int index = 0; index < alertObjInstIds.size(); index++) { //requirement: 3.4.11.2.a, 3.4.11.2.d - outLst.add(manager.update(alertObjInstIds.get(index), newAlertDefDetails.get(index), source, connection - .getConnectionDetails())); //requirement: 3.4.11.2.h Change in the manager/archive + outLst.add(manager.update(alertObjInstIds.get(index), newAlertDefDetails.get(index), + source, connection.getConnectionDetails())); //requirement: 3.4.11.2.h Change in the manager/archive } if (configurationAdapter != null) { @@ -548,8 +552,8 @@ public Long publishAlertEvent(final MALInteraction interaction, final Identifier * @param identityId * @return */ - private Long generateAlertDefinition(final AttributeValueList argumentValues, final Identifier alertDefinitionName, - final MALInteraction interaction, Long identityId) { + private Long generateAlertDefinition(final AttributeValueList argumentValues, + final Identifier alertDefinitionName, final MALInteraction interaction, Long identityId) { AlertCreationRequest alertCreationDef = new AlertCreationRequest(); AlertDefinitionDetails alertDef = new AlertDefinitionDetails(); alertDef.setDescription("This def. was auto-generated by the Alert service"); @@ -621,47 +625,48 @@ public Boolean reloadConfiguration(ConfigurationObjectDetails configurationObjec ConfigurationObjectSet confSet1 = configurationObjectDetails.getConfigObjects().get(1); // Confirm the objTypes - if (!confSet0.getObjType().equals(AlertHelper.ALERTDEFINITION_OBJECT_TYPE) && !confSet1.getObjType().equals( - AlertHelper.ALERTDEFINITION_OBJECT_TYPE)) { + if (!confSet0.getObjType().equals(AlertHelper.ALERTDEFINITION_OBJECT_TYPE) + && !confSet1.getObjType().equals(AlertHelper.ALERTDEFINITION_OBJECT_TYPE)) { return false; } - if (!confSet0.getObjType().equals(AlertHelper.ALERTIDENTITY_OBJECT_TYPE) && !confSet1.getObjType().equals( - AlertHelper.ALERTIDENTITY_OBJECT_TYPE)) { + if (!confSet0.getObjType().equals(AlertHelper.ALERTIDENTITY_OBJECT_TYPE) + && !confSet1.getObjType().equals(AlertHelper.ALERTIDENTITY_OBJECT_TYPE)) { return false; } // Confirm the domain - if (!confSet0.getDomain().equals(ConfigurationProviderSingleton.getDomain()) || !confSet1.getDomain().equals( - ConfigurationProviderSingleton.getDomain())) { + if (!confSet0.getDomain().equals(ConfigurationProviderSingleton.getDomain()) + || !confSet1.getDomain().equals(ConfigurationProviderSingleton.getDomain())) { return false; } // If the list is empty, reconfigure the service with nothing... if (confSet0.getObjInstIds().isEmpty() && confSet1.getObjInstIds().isEmpty()) { - manager.reconfigureDefinitions(new LongList(), new IdentifierList(), new LongList(), - new AlertDefinitionDetailsList()); // Reconfigures the Manager + manager.reconfigureDefinitions(new LongList(), new IdentifierList(), + new LongList(), new AlertDefinitionDetailsList()); // Reconfigures the Manager return true; } // ok, we're good to go... // Load the Parameter Definitions from this configuration... - ConfigurationObjectSet confSetDefs = (confSet0.getObjType().equals(AlertHelper.ALERTDEFINITION_OBJECT_TYPE)) ? - confSet0 : confSet1; + ConfigurationObjectSet confSetDefs = (confSet0.getObjType().equals(AlertHelper.ALERTDEFINITION_OBJECT_TYPE)) ? confSet0 : confSet1; AlertDefinitionDetailsList pDefs = (AlertDefinitionDetailsList) HelperArchive.getObjectBodyListFromArchive( manager.getArchiveService(), AlertHelper.ALERTDEFINITION_OBJECT_TYPE, ConfigurationProviderSingleton .getDomain(), confSetDefs.getObjInstIds()); - ConfigurationObjectSet confSetIdents = (confSet0.getObjType().equals(AlertHelper.ALERTIDENTITY_OBJECT_TYPE)) ? - confSet0 : confSet1; + ConfigurationObjectSet confSetIdents = (confSet0.getObjType().equals(AlertHelper.ALERTIDENTITY_OBJECT_TYPE)) ? confSet0 : confSet1; - IdentifierList idents = (IdentifierList) HelperArchive.getObjectBodyListFromArchive(manager.getArchiveService(), - AlertHelper.ALERTIDENTITY_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), confSetIdents - .getObjInstIds()); + IdentifierList idents = (IdentifierList) HelperArchive.getObjectBodyListFromArchive( + manager.getArchiveService(), + AlertHelper.ALERTIDENTITY_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + confSetIdents.getObjInstIds()); - manager.reconfigureDefinitions(confSetIdents.getObjInstIds(), idents, confSetDefs.getObjInstIds(), pDefs); // Reconfigures the Manager + manager.reconfigureDefinitions(confSetIdents.getObjInstIds(), idents, + confSetDefs.getObjInstIds(), pDefs); // Reconfigures the Manager return true; } diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/CheckProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/CheckProviderServiceImpl.java index 4b655e579..3a5efa2e8 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/CheckProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/CheckProviderServiceImpl.java @@ -109,7 +109,8 @@ public class CheckProviderServiceImpl extends CheckInheritanceSkeleton { * @throws MALException On initialisation error. */ public synchronized void init(COMServicesProvider comServices, MCServicesConsumer mcServicesConsumer, - ParameterManager parameterManager) throws MALException { + ParameterManager parameterManager) throws MALException { + long timestamp = System.currentTimeMillis(); if (!initialiased) { @@ -161,7 +162,9 @@ public synchronized void init(COMServicesProvider comServices, MCServicesConsume periodicCheckingManager.init(); // Initialize the Periodic Sampling Manager initialiased = true; - Logger.getLogger(CheckProviderServiceImpl.class.getName()).info("Check service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(CheckProviderServiceImpl.class.getName()).info( + "Check service READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java index 02a1e93c4..4b4ed3b9e 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/ParameterProviderServiceImpl.java @@ -27,10 +27,8 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.TaskScheduler; import esa.mo.mc.impl.util.GroupRetrieval; -import esa.mo.mc.impl.util.MCServicesHelper; import esa.mo.reconfigurable.service.ConfigurationChangeListener; import esa.mo.reconfigurable.service.ReconfigurableService; -import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -124,6 +122,8 @@ public class ParameterProviderServiceImpl extends ParameterInheritanceSkeleton i * @throws MALException On initialisation error. */ public synchronized void init(ParameterManager parameterManager) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -170,7 +170,9 @@ public synchronized void init(ParameterManager parameterManager) throws MALExcep */ initialiased = true; - Logger.getLogger(ParameterProviderServiceImpl.class.getName()).info("Parameter service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(ParameterProviderServiceImpl.class.getName()).info( + "Parameter service READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/StatisticProviderServiceImpl.java b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/StatisticProviderServiceImpl.java index b802634c8..2174f98c2 100644 --- a/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/StatisticProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mc-impl/src/main/java/esa/mo/mc/impl/provider/StatisticProviderServiceImpl.java @@ -135,8 +135,11 @@ public class StatisticProviderServiceImpl extends StatisticInheritanceSkeleton { * @param statisticFunctions * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, ParameterManager parameterManager, - ExternalStatisticFunctionsInterface statisticFunctions) throws MALException { + public synchronized void init(COMServicesProvider comServices, + ParameterManager parameterManager, + ExternalStatisticFunctionsInterface statisticFunctions) + throws MALException { + long timestamp = System.currentTimeMillis(); if (!initialiased) { @@ -182,7 +185,9 @@ public synchronized void init(COMServicesProvider comServices, ParameterManager periodicSamplingManager.init(); // Initialize the Periodic Sampling Manager initialiased = true; - Logger.getLogger(StatisticProviderServiceImpl.class.getName()).info("Statistic service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(StatisticProviderServiceImpl.class.getName()).info( + "Statistic service READY! (" + timestamp + " ms)"); } /** @@ -197,8 +202,8 @@ public void close() { connection.close(); running = false; } catch (MALException ex) { - Logger.getLogger(StatisticProviderServiceImpl.class.getName()).log(Level.WARNING, - "Exception during close down of the provider {0}", ex); + Logger.getLogger(StatisticProviderServiceImpl.class.getName()).log( + Level.WARNING, "Exception during close down of the provider {0}", ex); } } @@ -254,8 +259,9 @@ private void publishStatisticsUpdate(final Long objIdLink, final Long objIdLinkD } @Override - public StatisticEvaluationReportList getStatistics(LongList funcObjInstIds, Boolean isGroupIds, - ObjectKeyList reportInstances, MALInteraction interaction) throws MALInteractionException, MALException { + public StatisticEvaluationReportList getStatistics(LongList funcObjInstIds, + Boolean isGroupIds, ObjectKeyList reportInstances, + MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); @@ -462,8 +468,9 @@ private StatisticValue generateStatisticValue(Long statLinkId, StatisticCreation } @Override - public StatisticEvaluationReportList resetEvaluation(Boolean isGroupIds, LongList resetInstances, - Boolean returnCurrentEval, MALInteraction interaction) throws MALInteractionException, MALException { + public StatisticEvaluationReportList resetEvaluation(Boolean isGroupIds, + LongList resetInstances, Boolean returnCurrentEval, + MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); @@ -597,8 +604,8 @@ public Boolean getServiceStatus(MALInteraction interaction) throws MALInteractio } @Override - public void enableReporting(Boolean isGroupIds, InstanceBooleanPairList enableInstances, MALInteraction interaction) - throws MALInteractionException, MALException { + public void enableReporting(Boolean isGroupIds, InstanceBooleanPairList enableInstances, + MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); UIntegerList invIndexList = new UIntegerList(); @@ -616,7 +623,8 @@ public void enableReporting(Boolean isGroupIds, InstanceBooleanPairList enableIn if (instance.getId() == 0) { // Is it the wildcard '0'? requirement: 3.6.12.2.c // requirement: 3.6.12.2.e and 3.6.12.2.f and 3.6.12.2.j manager.setReportingEnabledAll(instance.getValue(), connection.getConnectionDetails()); - //3.6.2.n.b when disabling the periodic statistics reporting, the service shall continue evaluating the parameter statistics -> continue sampling + // 3.6.2.n.b when disabling the periodic statistics reporting, + // the service shall continue evaluating the parameter statistics -> continue sampling periodicReportingManager.refreshAll(); periodicCollectionManager.refreshAll(); foundWildcard = true; @@ -710,8 +718,8 @@ public void enableReporting(Boolean isGroupIds, InstanceBooleanPairList enableIn } @Override - public ObjectInstancePairList addParameterEvaluation(StatisticCreationRequestList newDetails, - MALInteraction interaction) throws MALInteractionException, MALException { + public ObjectInstancePairList addParameterEvaluation(StatisticCreationRequestList newDetails, + MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList invIndexList = new UIntegerList(); UIntegerList unkIndexList = new UIntegerList(); @@ -794,8 +802,8 @@ public ObjectInstancePairList addParameterEvaluation(StatisticCreationRequestLis } @Override - public LongList updateParameterEvaluation(LongList objInstIds, StatisticLinkDetailsList newDetails, - MALInteraction interaction) throws MALInteractionException, MALException { + public LongList updateParameterEvaluation(LongList objInstIds, StatisticLinkDetailsList newDetails, + MALInteraction interaction) throws MALInteractionException, MALException { UIntegerList invIndexList = new UIntegerList(); UIntegerList unkIndexList = new UIntegerList(); @@ -910,8 +918,8 @@ public void removeParameterEvaluation(LongList objInstIds, MALInteraction intera } @Override - public StatisticLinkSummaryList listParameterEvaluations(LongList statObjInstId, MALInteraction interaction) - throws MALInteractionException, MALException { + public StatisticLinkSummaryList listParameterEvaluations(LongList statObjInstId, + MALInteraction interaction) throws MALInteractionException, MALException { LongList statLinkIds = new LongList(); UIntegerList unkIndexList = new UIntegerList(); @@ -1070,12 +1078,15 @@ public void refreshList(LongList identityIds) { private void addPeriodicSampling(Long identityId) { final StatisticCreationRequest statLink = manager.getStatisticLink(identityId); - //requirement 3.6.2.n.b: Periodic Sampling shall not occur if the generation was disabled. So if it was never enabled nothing happens. If is was already enabled it should not even reach this code as the refresh-method will not be called in the enabledGeneration-operation + //requirement 3.6.2.n.b: Periodic Sampling shall not occur if the generation was disabled. + // So if it was never enabled nothing happens. If is was already enabled it should not even + // reach this code as the refresh-method will not be called in the enabledGeneration-operation //if (!statLink.getLinkDetails().getReportingEnabled()) { // return; //} // Add to the Periodic Sampling Manager only if there's a sampleInterval selected for the parameterSet - // NOTE: The standard says its "perfectly possible" to set a sampleInterval greater than a reporting or collection interval so no other checks of the sampleinterval necessary here + // NOTE: The standard says its "perfectly possible" to set a sampleInterval greater than a reporting + // or collection interval so no other checks of the sampleinterval necessary here Duration sampleInterval = statLink.getLinkDetails().getSamplingInterval(); if (sampleInterval.getValue() != 0) { TaskScheduler timer = new TaskScheduler(1, true); // Take care of adding a new timer diff --git a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanDistributionProviderServiceImpl.java b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanDistributionProviderServiceImpl.java index 2a2813608..58dd88937 100644 --- a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanDistributionProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanDistributionProviderServiceImpl.java @@ -99,8 +99,9 @@ public class PlanDistributionProviderServiceImpl extends PlanDistributionInherit * @param comServices * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, - MPServiceOperationManager registration) throws MALException { + public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, MPServiceOperationManager registration) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!this.initialised) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -192,7 +193,8 @@ public void onDataReceived(EventCOMObject eventCOMObject) { } this.initialised = true; - LOGGER.info("Plan Distribution service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Plan Distribution service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanEditProviderServiceImpl.java b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanEditProviderServiceImpl.java index 886b9e149..80a2f06b9 100644 --- a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanEditProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanEditProviderServiceImpl.java @@ -78,8 +78,9 @@ public class PlanEditProviderServiceImpl extends PlanEditInheritanceSkeleton { * @param comServices * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, - MPServiceOperationManager registration) throws MALException { + public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, MPServiceOperationManager registration) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!this.initialised) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -112,7 +113,8 @@ public synchronized void init(COMServicesProvider comServices, MPArchiveManager this.operationCallbackManager = registration; this.initialised = true; - LOGGER.info("Plan Edit service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Plan Edit service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanExecutionControlProviderServiceImpl.java b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanExecutionControlProviderServiceImpl.java index 6a80c7a1d..bf4e7e004 100644 --- a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanExecutionControlProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanExecutionControlProviderServiceImpl.java @@ -104,8 +104,9 @@ public class PlanExecutionControlProviderServiceImpl extends PlanExecutionContro * @param comServices * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, - MPServiceOperationManager registration, ActivityExecutionEngine activityExecutionEngine) throws MALException { + public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, MPServiceOperationManager registration, ActivityExecutionEngine activityExecutionEngine) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!this.initialised) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -174,7 +175,8 @@ public void onDataReceived(EventCOMObject eventCOMObject) { executor.setTickInterval(1000); this.initialised = true; - LOGGER.info("Plan Execution Control service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Plan Execution Control service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanInformationManagementProviderServiceImpl.java b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanInformationManagementProviderServiceImpl.java index 814d5e7ba..06c5964fc 100644 --- a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanInformationManagementProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanInformationManagementProviderServiceImpl.java @@ -83,8 +83,9 @@ public class PlanInformationManagementProviderServiceImpl extends PlanInformatio * @param comServices * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, - MPServiceOperationManager registration) throws MALException { + public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, MPServiceOperationManager registration) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!this.initialised) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -118,7 +119,8 @@ public synchronized void init(COMServicesProvider comServices, MPArchiveManager this.operationCallbackManager = registration; this.initialised = true; - LOGGER.info("Plan Information Management service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Plan Information Management service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanningRequestProviderServiceImpl.java b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanningRequestProviderServiceImpl.java index 620eea964..5b69c3954 100644 --- a/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanningRequestProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-mp-impl/src/main/java/esa/mo/mp/impl/provider/PlanningRequestProviderServiceImpl.java @@ -101,8 +101,9 @@ public class PlanningRequestProviderServiceImpl extends PlanningRequestInheritan * @param comServices * @throws MALException On initialisation error. */ - public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, - MPServiceOperationManager registration) throws MALException { + public synchronized void init(COMServicesProvider comServices, MPArchiveManager archiveManager, MPServiceOperationManager registration) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!this.initialised) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -166,7 +167,8 @@ public void onDataReceived(EventCOMObject eventCOMObject) { } this.initialised = true; - LOGGER.info("Planning Request service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Planning Request service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java index f85067a4c..03b325834 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ArtificialIntelligenceProviderServiceImpl.java @@ -65,6 +65,8 @@ public class ArtificialIntelligenceProviderServiceImpl extends ArtificialIntelli * @throws MALException On initialisation error. */ public synchronized void init(AIAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -97,7 +99,8 @@ public synchronized void init(AIAdapterInterface adapter) throws MALException { ArtificialIntelligenceHelper.ARTIFICIALINTELLIGENCE_SERVICE, this); initialiased = true; - LOGGER.info("Artificial Intelligence service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Artificial Intelligence service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java index 2088b13d1..9b89e4f72 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/AutonomousADCSProviderServiceImpl.java @@ -110,6 +110,8 @@ public class AutonomousADCSProviderServiceImpl extends AutonomousADCSInheritance */ public synchronized void init(COMServicesProvider comServices, AutonomousADCSAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -151,7 +153,8 @@ public synchronized void init(COMServicesProvider comServices, AutonomousADCSHelper.AUTONOMOUSADCS_SERVICE, true, this); initialiased = true; - LOGGER.info("AutonomousADCS service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("AutonomousADCS service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java index 27883795c..a8cdc5d15 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java @@ -99,6 +99,8 @@ public class CameraProviderServiceImpl extends CameraInheritanceSkeleton { */ public synchronized void init(COMServicesProvider comServices, CameraAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -142,7 +144,8 @@ public synchronized void init(COMServicesProvider comServices, availableFormats = adapter.getAvailableFormats(); running = true; initialiased = true; - LOGGER.info("Camera service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Camera service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java index aef96c0f2..48518e1e4 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/ClockProviderServiceImpl.java @@ -51,6 +51,8 @@ public class ClockProviderServiceImpl extends ClockInheritanceSkeleton { * @throws MALException On initialisation error. */ public synchronized void init(ClockAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -82,7 +84,8 @@ public synchronized void init(ClockAdapterInterface adapter) throws MALException ClockHelper.CLOCK_SERVICE_NAME.toString(), ClockHelper.CLOCK_SERVICE, this); initialiased = true; - LOGGER.info("Clock service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Clock service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java index 458c735ee..dc18bc313 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java @@ -89,9 +89,8 @@ /** * GPS service Provider. */ -public class GPSProviderServiceImpl extends GPSInheritanceSkeleton - implements ReconfigurableService -{ +public class GPSProviderServiceImpl extends GPSInheritanceSkeleton implements ReconfigurableService { + protected static final Logger LOGGER = Logger.getLogger(GPSProviderServiceImpl.class.getName()); private MALProvider gpsServiceProvider; private boolean initialiased = false; @@ -125,6 +124,8 @@ public class GPSProviderServiceImpl extends GPSInheritanceSkeleton public synchronized void init(final COMServicesProvider comServices, final GPSAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, @@ -154,9 +155,45 @@ public synchronized void init(final COMServicesProvider comServices, ConfigurationProviderSingleton.getSourceSessionName(), QoSLevel.BESTEFFORT, null, new UInteger(0)); - publisher = createNearbyPositionPublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, ConfigurationProviderSingleton - .getSourceSessionName(), QoSLevel.BESTEFFORT, null, new UInteger(0)); + // Shut down old service transport + if (null != gpsServiceProvider) { + connection.closeAll(); + } + + manager = new GPSManager(comServices); + this.adapter = adapter; + gpsServiceProvider = connection.startService(GPSHelper.GPS_SERVICE_NAME.toString(), + GPSHelper.GPS_SERVICE, this); + + if (Boolean.parseBoolean(System.getProperty(HelperMisc.PROP_GPS_POLLING_ACTIVE, "true"))) { + periodicCurrentPosition = new PeriodicCurrentPosition(); + periodicCurrentPosition.init(); + running = true; + initialiased = true; + periodicCurrentPosition.start(); + } + + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("GPS service: READY! (" + timestamp + " ms)"); + } + + /** + * Closes all running threads and releases the MAL resources. + */ + public void close() + { + try { + if (null != gpsServiceProvider) { + gpsServiceProvider.close(); + } + + connection.closeAll(); + running = false; + } catch (MALException ex) { + LOGGER.log(Level.WARNING, + "Exception during close down of the provider {0}", ex); + } + } // Shut down old service transport if (null != gpsServiceProvider) { diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java index ef3383469..17a96ba75 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/OpticalDataReceiverProviderServiceImpl.java @@ -57,6 +57,8 @@ public class OpticalDataReceiverProviderServiceImpl extends OpticalDataReceiverI * @throws MALException On initialisation error. */ public synchronized void init(OpticalDataReceiverAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -89,8 +91,9 @@ public synchronized void init(OpticalDataReceiverAdapterInterface adapter) throw OpticalDataReceiverHelper.OPTICALDATARECEIVER_SERVICE, this); initialiased = true; + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(OpticalDataReceiverProviderServiceImpl.class.getName()).info( - "Optical Data Receiver service READY"); + "Optical Data Receiver service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java index f8c7cebbf..e2104224a 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/PowerControlProviderServiceImpl.java @@ -63,6 +63,8 @@ public class PowerControlProviderServiceImpl extends PowerControlInheritanceSkel * @throws MALException On initialisation error. */ public synchronized void init(PowerControlAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -96,7 +98,8 @@ public synchronized void init(PowerControlAdapterInterface adapter) throws MALEx running = true; initialiased = true; - LOGGER.info("Power Control service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Power Control service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java index b5fc51b5a..414a4346c 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/SoftwareDefinedRadioProviderServiceImpl.java @@ -82,6 +82,8 @@ public class SoftwareDefinedRadioProviderServiceImpl extends SoftwareDefinedRadi * @throws MALException On initialisation error. */ public synchronized void init(SoftwareDefinedRadioAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { @@ -125,8 +127,9 @@ public synchronized void init(SoftwareDefinedRadioAdapterInterface adapter) thro running = true; initialiased = true; + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(SoftwareDefinedRadioProviderServiceImpl.class.getName()).info( - "Software-defined Radio service READY"); + "Software-defined Radio service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index aba266f3f..e3ca36921 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -107,6 +107,8 @@ public class AppsLauncherProviderServiceImpl extends AppsLauncherInheritanceSkel */ public synchronized void init(final COMServicesProvider comServices, final DirectoryProviderServiceImpl directoryService) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -151,8 +153,8 @@ public synchronized void init(final COMServicesProvider comServices, AppsLauncherHelper.APPSLAUNCHER_SERVICE, this); running = true; initialiased = true; - - LOGGER.log(Level.INFO, "Apps Launcher service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Apps Launcher service: READY! (" + timestamp + " ms)"); } public ConnectionProvider getConnectionProvider() { diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java index 9906f34fe..501294aff 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/CommandExecutorProviderServiceImpl.java @@ -83,6 +83,8 @@ public class CommandExecutorProviderServiceImpl extends CommandExecutorInheritan * @throws MALException On initialization error. */ public synchronized void init(final COMServicesProvider comServices) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -120,8 +122,8 @@ public synchronized void init(final COMServicesProvider comServices) throws MALE CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NAME.toString(), CommandExecutorHelper.COMMANDEXECUTOR_SERVICE, this); initialiased = true; - - LOGGER.log(Level.INFO, "Command Executor service READY"); + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Command Executor service: READY! (" + timestamp + " ms)"); } protected String[] assembleCommand(final String command) { diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java index cba1408fb..ecd8fe597 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/HeartbeatProviderServiceImpl.java @@ -75,6 +75,8 @@ public class HeartbeatProviderServiceImpl extends HeartbeatInheritanceSkeleton { * @throws MALException On initialisation error. */ public synchronized void init() throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -109,10 +111,6 @@ public synchronized void init() throws MALException { HeartbeatHelper.HEARTBEAT_SERVICE_NAME.toString(), HeartbeatHelper.HEARTBEAT_SERVICE, true, this); - running = true; - initialiased = true; - LOGGER.info("Heartbeat service READY"); - // Start the timer to publish the heartbeat timer = new Timer("HeartbeatThread"); timer.schedule(new TimerTask() { @@ -123,6 +121,11 @@ public void run() { } } }, period, period); + + running = true; + initialiased = true; + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Heartbeat service: READY! (" + timestamp + " ms)"); } /** diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java index d112db0bf..8a11b6bb1 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/PackageManagementProviderServiceImpl.java @@ -67,7 +67,10 @@ public class PackageManagementProviderServiceImpl extends PackageManagementInher * @param backend * @throws MALException On initialization error. */ - public synchronized void init(final COMServicesProvider comServices, final PMBackend backend) throws MALException { + public synchronized void init(final COMServicesProvider comServices, + final PMBackend backend) throws MALException { + long timestamp = System.currentTimeMillis(); + if (backend == null) { Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).severe( "Package Management service could not be initialized! " + "The backend object cannot be null."); @@ -108,7 +111,9 @@ public synchronized void init(final COMServicesProvider comServices, final PMBac PackageManagementHelper.PACKAGEMANAGEMENT_SERVICE, false, this); running = true; initialiased = true; - Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).info("Package Management service READY"); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(PackageManagementProviderServiceImpl.class.getName()).info( + "Package Management service: READY! (" + timestamp + " ms)"); } /** diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java index 68e437f32..28e888f95 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/GPSProviderServiceWithTLEImpl.java @@ -59,14 +59,10 @@ */ public class GPSProviderServiceWithTLEImpl extends GPSProviderServiceImpl { - private static final int NANOSECONDS_IN_MILLISECOND = 1000000; - private final Boolean isTLEFallbackEnabled = Boolean.parseBoolean(System.getProperty(Const.PLATFORM_GNSS_FALLBACK_TO_TLE_PROPERTY, Const.PLATFORM_GNSS_FALLBACK_TO_TLE_DEFAULT)); - private final Double utcOffset = Double.parseDouble(System.getProperty(Const.PLATFORM_GNSS_UTC_OFFSET_PROPERTY, - Const.PLATFORM_GNSS_UTC_OFFSET_DEFAULT)); private static boolean isOrekitDataInitialized = false; private final GPSSoftSimAdapter adapterCast = (GPSSoftSimAdapter) adapter; From 272316c7128021122b346c9550c14cebce4715d4 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 30 Oct 2022 16:20:15 +0100 Subject: [PATCH 124/173] Small optimizations --- .../connections/ConnectionProvider.java | 9 ++ .../mo/com/impl/provider/ArchiveManager.java | 1 + .../src/main/java/esa/mo/nmf/NMFProvider.java | 2 +- .../NanoSatMOConnectorImpl.java | 118 +++++++++--------- 4 files changed, 70 insertions(+), 60 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java index ce4c7b79c..80a32b781 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/connections/ConnectionProvider.java @@ -357,7 +357,15 @@ public static ServicesConnectionDetails getGlobalProvidersDetailsSecondary() { * Writes the URIs on a text file */ private void writeURIsOnFile(SingleConnectionDetails connectionDetails, String serviceName, String filename) { + StringBuilder str = new StringBuilder(); + str.append(serviceName).append(HelperConnections.SUFFIX_URI).append("=").append(connectionDetails.getProviderURI()).append("\n"); + str.append(serviceName).append(HelperConnections.SUFFIX_BROKER).append("=").append(connectionDetails.getBrokerURI()).append("\n"); + str.append(serviceName).append(HelperConnections.SUFFIX_DOMAIN).append("=").append(HelperMisc.domain2domainId(connectionDetails.getDomain())).append("\n"); + str.append(serviceName).append(HelperConnections.SUFFIX_SERVICE_KEY).append("=").append(connectionDetails.getServiceKey()).append("\n"); + try (BufferedWriter wrt = new BufferedWriter(new FileWriter(filename, true))) { + wrt.append(str.toString()); + /* wrt.append(serviceName + HelperConnections.SUFFIX_URI + "=" + connectionDetails.getProviderURI()); wrt.newLine(); wrt.append(serviceName + HelperConnections.SUFFIX_BROKER + "=" + connectionDetails.getBrokerURI()); @@ -367,6 +375,7 @@ private void writeURIsOnFile(SingleConnectionDetails connectionDetails, String s wrt.newLine(); wrt.append(serviceName + HelperConnections.SUFFIX_SERVICE_KEY + "=" + connectionDetails.getServiceKey()); wrt.newLine(); + */ } catch (IOException ex) { Logger.getLogger(ConnectionProvider.class.getName()).log(Level.WARNING, "Unable to write URI information to properties file {0}", ex); diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java index 3ff9c2b96..efbe939a2 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/com/impl/provider/ArchiveManager.java @@ -105,6 +105,7 @@ public class ArchiveManager { public ArchiveManager(EventProviderServiceImpl eventService) { this.eventService = eventService; + // This code is no longer needed here... if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) != null && MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) .getServiceByName(ArchiveHelper.ARCHIVE_SERVICE_NAME) == null) { diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java index 2596cd1ae..9709f8914 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java @@ -324,7 +324,7 @@ protected String generateStartBanner() { Properties p = System.getProperties(); final String SEPARATOR = "------------\n"; - StringBuilder banner = new StringBuilder(); + StringBuilder banner = new StringBuilder(256); banner.append("\n"); banner.append(SEPARATOR); banner.append("NanoSat MO Framework\n"); diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 71bde7da6..2834c806c 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -48,7 +48,6 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; -import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.com.COMService; @@ -80,6 +79,8 @@ public class NanoSatMOConnectorImpl extends NMFProvider { private static final Logger LOGGER = Logger.getLogger(NanoSatMOConnectorImpl.class.getName()); + private final boolean fastMode = false; + private Long appDirectoryServiceId; private EventConsumerServiceImpl serviceCOMEvent; private Subscription subscription; @@ -97,38 +98,43 @@ public class NanoSatMOConnectorImpl extends NMFProvider { public void init(final MonitorAndControlNMFAdapter mcAdapter) { super.startTime = System.currentTimeMillis(); LOGGER.log(Level.INFO, this.generateStartBanner()); - + HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties ConnectionProvider.resetURILinks(); // Resets the providerURIs.properties file // Create provider name to be registerd on the Directory service... - String appName = "Unknown"; - try { // Use the folder name - appName = (new File((new File("")).getCanonicalPath())).getName(); - System.setProperty(HelperMisc.PROP_MO_APP_NAME, appName); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "The NMF App name could not be established."); - } - + String appName = this.determineAppName(); this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; // Check if the new Home dir mode property is enabled: int mode = Integer.parseInt(System.getProperty(HelperMisc.PROP_WORK_DIR_STORAGE_MODE, "0")); - - if(mode >= 2){ + + if (mode >= 2) { File nmfInternal = AppStorage.getAppNMFInternalDir(); String location = nmfInternal + File.separator + "comArchive.db"; String url = "jdbc:sqlite:" + location; System.setProperty("esa.nmf.archive.persistence.jdbc.url", url); - + String urisPath = nmfInternal + File.separator + HelperMisc.PROVIDER_URIS_PROPERTIES_FILENAME; System.setProperty(HelperMisc.PROP_PROVIDERURIS_PATH, urisPath); String urisPath_sec = nmfInternal + File.separator + HelperMisc.PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME; System.setProperty(HelperMisc.PROP_PROVIDERURIS_SEC_PATH, urisPath_sec); } - - ConnectionProvider.resetURILinks(); // Resets the providerURIs.properties file - + + if (fastMode) { + Thread mcThread = new Thread(() -> { + try { + startMCServices(mcAdapter); + } catch (MALException ex) { + LOGGER.log(Level.SEVERE, + "The services could not be initialized. " + + "Perhaps there's something wrong with the Transport Layer.", ex); + } + }); + + mcThread.start(); + } + try { comServices.init(); comServices.initArchiveSync(); @@ -142,9 +148,11 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { if (centralDirectoryURI != null && centralDirectoryURI.getValue().startsWith("malspp")) { LOGGER.log(Level.INFO, - "The Central Directory service URI read is selecting 'malspp' as transport. The URI will be discarded." + - " To enable a better IPC communication, please enable the secondary transport protocol flag: " + - HelperMisc.SECONDARY_PROTOCOL); + "The Central Directory service URI read is selecting 'malspp' as " + + "transport. The URI will be discarded. To enable a better IPC " + + "communication, please enable the secondary transport protocol flag: " + + HelperMisc.SECONDARY_PROTOCOL + ); centralDirectoryURI = null; } @@ -188,16 +196,6 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { subscription = HelperCOM.generateSubscriptionCOMEvent("CloseAppEventListener", AppsLauncherHelper.APP_OBJECT_TYPE); - /* Previous code */ - /* - final Long secondEntityKey = 0xFFFFFFFFFF000000L & HelperCOM.generateSubKey(AppsLauncherHelper.APP_OBJECT_TYPE); - final Random random = new Random(); - subscription = ConnectionConsumer.subscriptionKeys( - new Identifier("CloseAppEventListener" + random.nextInt()), - new Identifier("*"), secondEntityKey, new Long(0), new Long(0)); - */ - /* ------------- */ - // Register with the subscription key provided serviceCOMEvent.addEventReceivedListener(subscription, new CloseAppEventListener(this)); } @@ -245,7 +243,10 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { // Initialize the rest of the services try { - this.startMCServices(mcAdapter); + if (!fastMode) { + this.startMCServices(mcAdapter); + } + directoryService.init(comServices); heartbeatService.init(); } catch (MALException ex) { @@ -264,15 +265,15 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { if (centralDirectoryURI != null) { try { if (centralDirectory != null) { - LOGGER.log(Level.INFO, "Populating Central Directory service on URI: {0}", centralDirectoryURI - .getValue()); + LOGGER.log(Level.INFO, "Populating Central Directory service " + + "on URI: " + centralDirectoryURI.getValue()); final PublishProviderResponse response = centralDirectory.getDirectoryStub().publishProvider( publishDetails); this.appDirectoryServiceId = response.getBodyElement0(); centralDirectory.close(); // Close the connection to the Directory service - LOGGER.log(Level.INFO, - "Populated! And the connection to the Directory service has been successfully closed!"); + LOGGER.log(Level.INFO, "Populated! And the connection to the " + + "Directory service has been successfully closed!"); } } catch (MALException ex) { LOGGER.log(Level.SEVERE, null, ex); @@ -300,8 +301,10 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { } if (mcAdapter != null) { - MCRegistration registration = new MCRegistration(comServices, mcServices.getParameterService(), mcServices - .getAggregationService(), mcServices.getAlertService(), mcServices.getActionService()); + LOGGER.log(Level.INFO, "Performing initial M&C registrations..."); + MCRegistration registration = new MCRegistration(comServices, + mcServices.getParameterService(), mcServices.getAggregationService(), + mcServices.getAlertService(), mcServices.getActionService()); mcAdapter.initialRegistrations(registration); mcAdapter.restoreParameterValuesFromArchive(); } @@ -321,14 +324,7 @@ public void init(final MissionPlanningNMFAdapter mpAdapter) { ConnectionProvider.resetURILinks(); // Create provider name to be registerd on the Directory service... - String appName = "Unknown"; - try { // Use the folder name - appName = (new File((new File("")).getCanonicalPath())).getName(); - System.setProperty(HelperMisc.PROP_MO_APP_NAME, appName); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "The NMF App name could not be established."); - } - + String appName = this.determineAppName(); this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; try { @@ -390,14 +386,7 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter, final MissionPlann ConnectionProvider.resetURILinks(); // Create provider name to be registerd on the Directory service... - String appName = "Unknown"; - try { // Use the folder name - appName = (new File((new File("")).getCanonicalPath())).getName(); - System.setProperty(HelperMisc.PROP_MO_APP_NAME, appName); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, "The NMF App name could not be established."); - } - + String appName = this.determineAppName(); this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; try { @@ -460,15 +449,14 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter, final MissionPlann AppsLauncherHelper.APP_OBJECT_TYPE); /* Previous code */ - /* + /* final Long secondEntityKey = 0xFFFFFFFFFF000000L & HelperCOM.generateSubKey(AppsLauncherHelper.APP_OBJECT_TYPE); final Random random = new Random(); subscription = ConnectionConsumer.subscriptionKeys( new Identifier("CloseAppEventListener" + random.nextInt()), new Identifier("*"), secondEntityKey, new Long(0), new Long(0)); */ - /* ------------- */ - + /* ------------- */ // Register with the subscription key provided serviceCOMEvent.addEventReceivedListener(subscription, new CloseAppEventListener(this)); } @@ -489,10 +477,9 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter, final MissionPlann } // Select the best transport for IPC and convert to a ConnectionConsumer object - final ProviderSummary filteredConnections = HelperCommon.selectBestIPCTransport( - supervisorConnections.get(0)); - final ConnectionConsumer supervisorCCPlat = HelperCommon.providerSummaryToConnectionConsumer( - filteredConnections); + final ProviderSummary filteredConnections + = HelperCommon.selectBestIPCTransport(supervisorConnections.get(0)); + final ConnectionConsumer supervisorCCPlat = HelperCommon.providerSummaryToConnectionConsumer(filteredConnections); // Connect to them... platformServices = new PlatformServicesConsumer(); @@ -722,4 +709,17 @@ public int getPlatformTimeFactor() { }); } + private String determineAppName() { + String appName = "Unknown"; + + try { // Use the folder name + appName = (new File((new File("")).getCanonicalPath())).getName(); + System.setProperty(HelperMisc.PROP_MO_APP_NAME, appName); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "The NMF App name could not be established."); + } + + return appName; + } + } From 485ec1b22263d66068d27de1555e38346c98fa42 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 31 Oct 2022 20:00:33 +0100 Subject: [PATCH 125/173] Creates and sets permissions to the logs folder, so apps can store logs. Code cleanup. --- .../esa/mo/nmf/nmfpackage/Deployment.java | 147 ++++++++++++++++- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 4 +- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 3 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 155 +++++++----------- .../nmf/nmfpackage/NMFPackagePMBackend.java | 8 +- .../mo/nmf/nmfpackage/metadata/Metadata.java | 5 - .../nmf/nmfpackage/metadata/MetadataApp.java | 23 ++- .../nmfpackage/utils/HelperNMFPackage.java | 153 +++-------------- .../nmfpackage/GenerateNMFPackageMojo.java | 8 +- 9 files changed, 249 insertions(+), 257 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index 39a97bacf..d7ff01e3e 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -20,7 +20,14 @@ */ package esa.mo.nmf.nmfpackage; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -45,11 +52,11 @@ public class Deployment { private static final String PROPERTY_INSTALLED_RECEIPTS_FOLDER = "esa.mo.nmf.nmfpackage.receipts"; - private static String pathNMF = null; + private static File pathNMF = null; public static File getInstallationsTrackerDir() { // Default location of the folder - File folder = new File(DIR_ETC + File.separator + DIR_INSTALLATIONS_TRACKER); + File folder = new File(getEtcDir(), DIR_INSTALLATIONS_TRACKER); // Read the Property of the folder to install the packages if (System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER) != null) { @@ -58,14 +65,26 @@ public static File getInstallationsTrackerDir() { return folder; } + + public static File getEtcDir() { + return new File(getNMFRootDir(), DIR_ETC); + } + + public static File getLogsDir() { + return new File(getNMFRootDir(), DIR_LOGS); + } public static File getNMFAppsDir() { - return new File(DIR_APPS); + return new File(getNMFRootDir(), DIR_APPS); } - + + public static File getJarsSharedDir() { + return new File(getNMFRootDir(), DIR_JARS_SHARED); + } + public static File getNMFRootDir() { if (pathNMF != null) { - return new File(pathNMF); + return pathNMF; } File folder = new File((new File("")).getAbsolutePath()); @@ -73,12 +92,126 @@ public static File getNMFRootDir() { // Default location of the folder if (DIR_NMF.equals(currentFolder) || "supervisor".equals(currentFolder)) { - pathNMF = folder.getAbsolutePath(); - return new File(pathNMF); + pathNMF = folder; + return pathNMF; } // We need additional logic to make sure we are in the right directory! return folder; } + /** + * Find the best Java Runtime Environment inside an nmf directory. The best + * JRE will be determined based on arguments containing a recommended + * version, a minimum version, and a maximum version. + * + * @param recommended The recommended version to run the App. + * @param min The minimum version needed to run the App. + * @param max The maximum version to run the App. + * @return The Best JRE available for . + */ + public static String findJREPath(File nmfDir, int recommended, int min, int max) { + if (min < max) { + Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, + "The JRE minimum version cannot be greater than the maximum!"); + } + + if (recommended < min || recommended > max) { + Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, + "The JRE recommended version should be between the min and max!"); + } + + File javaNMFDir = new File(nmfDir, DIR_JAVA); + String bestJRE = "java"; // Default value and worst-case scenario + + if (!javaNMFDir.exists()) { + return bestJRE; // Return the default value + } + + final String VERSION_PROP = "JAVA_VERSION"; + File[] list = javaNMFDir.listFiles(); + + for (File dir : list) { + if (!dir.isDirectory()) { + continue; // Jump over if it is not a directory + } + + try { + // Check which java version it is from the release file... + String path = dir.getAbsolutePath(); + File release = new File(dir, "release"); + + if (!release.exists()) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JRE release file does not " + + "exist in: " + release.getAbsolutePath()); + continue; + } + + Properties props = new Properties(); + props.load(new FileInputStream(release)); + String version = (String) props.get(VERSION_PROP); + + if (version == null) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JAVA_VERSION property " + + "was not be found on release file: " + path); + continue; + } + + String[] subs = version.replace("\"", "").split("\\."); + + if (subs.length < 3) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "The JRE version '" + version + + "' could not be determined from the release file: " + + release.getAbsolutePath()); + continue; + } + + // Java version used to start with 1 until at least Java 8 + int java_version = (Integer.parseInt(subs[0]) != 1) + ? Integer.parseInt(subs[0]) + : Integer.parseInt(subs[1]); + + String jre = dir.getAbsolutePath() + File.separator + + "bin" + File.separator + "java"; + + if (!(new File(jre)).exists()) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, + "The JRE could not be found in directory: " + path); + continue; + } + + if (java_version == recommended) { + // Perfect, just return it directly! + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.INFO, "The JRE version " + java_version + + " was successfully found in directory:" + + "\n >> " + jre); + + return jre; + } + + // The version is outside boundaries? + if (java_version < min && java_version > max) { + continue; + } + bestJRE = jre; + // The code here will need to be improved... + // The objective should be to return the + // highest available version within the choices + } catch (FileNotFoundException ex) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "Something went wrong...", ex); + } catch (IOException ex) { + Logger.getLogger(HelperNMFPackage.class.getName()).log( + Level.WARNING, "Something went wrong...", ex); + } + } + + return bestJRE; + } + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 83a349034..78a1c0555 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -117,10 +117,10 @@ public void extractFiles(File to) throws IOException { String path = HelperNMFPackage.generateFilePathForSystem(entry.getName()); newFile = new File(to.getCanonicalPath() + File.separator + path); - File parent = new File(newFile.getParent()); + File parent = newFile.getParentFile(); if (!parent.exists()) { - new File(newFile.getParent()).mkdirs(); + parent.mkdirs(); } System.out.println(" >> Copying file to: " + newFile.getCanonicalPath()); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 367d338e3..46f786d66 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -124,7 +124,7 @@ public static String create(Metadata metadata, ArrayList filesInput, Level.SEVERE, "The file could not be stored!", ex); } - // Add the receipt file to the list of Files to be zipped + // Add the metadata file to the list of Files to be zipped files.add(metadataFile.getPath()); newLocations.add(Metadata.FILENAME); // ------------------------------------------------------------------- @@ -188,7 +188,6 @@ public static String create(Metadata metadata, ArrayList filesInput, } */ // Delete temporary files: - //receipt.delete(); metadataFile.delete(); //digitalSignature.delete(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index d698b0454..ebaa282ba 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -61,6 +61,8 @@ public class NMFPackageManager { private static final String SEPARATOR = "--------------\n"; + private static final OSValidator OS = new OSValidator(); + private AppsLauncherProviderServiceImpl appsLauncher; public NMFPackageManager(AppsLauncherProviderServiceImpl appsLauncher) { @@ -86,8 +88,8 @@ public void install(final String packageLocation, "Reading the package file to be installed..."); // Get the File to be installed - NMFPackage pack = new NMFPackage(packageLocation); - Metadata metadata = pack.getMetadata(); + NMFPackage nmfPackage = new NMFPackage(packageLocation); + Metadata metadata = nmfPackage.getMetadata(); if (metadata.getMetadataVersion() < 3) { throw new IOException("The package version is deprecated! " @@ -99,28 +101,25 @@ public void install(final String packageLocation, "Verifying the integrity of the files to be installed..."); // Do the files actually match the descriptor? - pack.verifyPackageIntegrity(); - - // Copy the files according to the NMF statement file - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Copying the files to the new locations..."); + nmfPackage.verifyPackageIntegrity(); if (metadata.isApp()) { installDependencies(metadata.castToApp(), packageLocation, nmfDir); } - pack.extractFiles(nmfDir); + // Copy the files according to the NMF statement file + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "Copying the files to the new locations..."); + + nmfPackage.extractFiles(nmfDir); String packageName = metadata.getPackageName(); if (metadata.isApp()) { - File appDir = new File(nmfDir.getAbsolutePath() - + File.separator + Deployment.DIR_APPS - + File.separator + packageName); - + File appDir = new File(Deployment.getNMFAppsDir(), packageName); String username = null; String password = null; - if ((new OSValidator()).isUnix()) { + if (OS.isUnix()) { try { // Create the User for this App username = generateUsername(packageName); @@ -131,9 +130,9 @@ public void install(final String packageLocation, // Set the right Group and Permissions to the Home Directory // The owner remains with the app, the group is nmf-admin - String homeDir = LinuxUsersGroups.findHomeDir(username); - LinuxUsersGroups.chgrp(true, USER_NMF_ADMIN, homeDir); - LinuxUsersGroups.chmod(true, true, "770", homeDir); + String appHomeDir = LinuxUsersGroups.findHomeDir(username); + LinuxUsersGroups.chgrp(true, USER_NMF_ADMIN, appHomeDir); + LinuxUsersGroups.chmod(true, true, "770", appHomeDir); } catch (IOException ex) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "The User could not be created: " + username, ex); @@ -143,29 +142,25 @@ public void install(final String packageLocation, HelperNMFPackage.generateStartScript(metadata.castToApp(), appDir, nmfDir); createAuxiliaryFiles(appDir, username); + File logDir = new File(Deployment.getLogsDir(), packageName); + logDir.mkdirs(); - if ((new OSValidator()).isUnix()) { - // Change Group owner of the appDir - if (username != null) { - LinuxUsersGroups.chgrp(true, username, appDir.getAbsolutePath()); - } - - // chmod the installation directory with recursive - LinuxUsersGroups.chmod(false, true, "750", appDir.getAbsolutePath()); + if (OS.isUnix()) { // Change Group owner of the appDir + changeGroupAndSetPermissions(appDir, username, "750"); + changeGroupAndSetPermissions(logDir, username, "770"); } } // Store a copy of the newReceipt to know that it has been installed! File receiptsFolder = Deployment.getInstallationsTrackerDir(); String receiptFilename = packageName + RECEIPT_ENDING; - String receiptPath = receiptsFolder.getCanonicalPath() + File.separator + receiptFilename; - File receiptFile = new File(receiptPath); + File receiptFile = new File(receiptsFolder, receiptFilename); metadata.store(receiptFile); if (appsLauncher != null) { appsLauncher.refresh(); } - + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully installed from: {0}", packageLocation); @@ -193,14 +188,10 @@ public void uninstall(final Metadata packageMetadata, if (packageMetadata.isApp()) { // This directory should be passed in the method signature: - File nmfDir = Deployment.getNMFRootDir(); - File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + Deployment.DIR_APPS - + File.separator + packageName); - + File installationDir = new File(Deployment.getNMFAppsDir(), packageName); removeAuxiliaryFiles(installationDir, packageName); - if ((new OSValidator()).isUnix()) { + if (OS.isUnix()) { if (!keepUserData) { String username = generateUsername(packageName); LinuxUsersGroups.deluser(username, true); @@ -210,13 +201,12 @@ public void uninstall(final Metadata packageMetadata, removeFiles(packageMetadata); - String receiptsPath = Deployment.getInstallationsTrackerDir().getCanonicalPath(); - String receiptFilename = packageName + RECEIPT_ENDING; - File receiptFile = new File(receiptsPath + File.separator + receiptFilename); + File receiptsFolder = Deployment.getInstallationsTrackerDir(); + File receiptFile = new File(receiptsFolder, packageName + RECEIPT_ENDING); if (!receiptFile.delete()) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.WARNING, - "The receipt file could not be deleted from: " + receiptsPath); + "The receipt file could not be deleted from: " + receiptsFolder); } if (appsLauncher != null) { @@ -225,7 +215,7 @@ public void uninstall(final Metadata packageMetadata, Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully uninstalled: " + packageName); - + System.out.printf(SEPARATOR); } @@ -253,7 +243,7 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx File receiptsFolder = Deployment.getInstallationsTrackerDir(); String receiptFilename = newPackMetadata.getPackageName() + RECEIPT_ENDING; - File oldReceiptFile = new File(receiptsFolder.getCanonicalPath() + File.separator + receiptFilename); + File oldReceiptFile = new File(receiptsFolder, receiptFilename); Metadata oldPackMetadata = Metadata.load(oldReceiptFile); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Upgrading..." @@ -275,10 +265,7 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx if (isApp) { // This directory should be passed in the method signature: - File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + Deployment.DIR_APPS - + File.separator + packageName); - + File installationDir = new File(Deployment.getNMFAppsDir(), packageName); removeAuxiliaryFiles(installationDir, packageName); } @@ -298,27 +285,17 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx newPack.extractFiles(nmfDir); if (isApp) { - String username = null; - File installationDir = new File(nmfDir.getAbsolutePath() - + File.separator + Deployment.DIR_APPS - + File.separator + packageName); - - if ((new OSValidator()).isUnix()) { - username = generateUsername(packageName); - } + File installationDir = new File(Deployment.getNMFAppsDir(), packageName); + String username= generateUsername(packageName); HelperNMFPackage.generateStartScript(appMetadata, installationDir, nmfDir); createAuxiliaryFiles(installationDir, username); + File logDir = new File(Deployment.getLogsDir(), packageName); + logDir.mkdirs(); - if ((new OSValidator()).isUnix()) { - String path = installationDir.getAbsolutePath(); - // Change Group owner of the appDir - if (username != null) { - LinuxUsersGroups.chgrp(true, username, path); - } - - // chmod the installation directory with recursive - LinuxUsersGroups.chmod(false, true, "750", path); + if (OS.isUnix()) { // Change Group owner of the appDir + changeGroupAndSetPermissions(installationDir, username, "750"); + changeGroupAndSetPermissions(logDir, username, "770"); } } @@ -328,7 +305,7 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx if (appsLauncher != null) { appsLauncher.refresh(); } - + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Package successfully upgraded from location: " + packageLocation); @@ -361,19 +338,9 @@ public boolean isPackageInstalled(final String packageLocation) { File temp = Deployment.getInstallationsTrackerDir(); String packageName = metadata.getPackageName(); - String receiptFilename = packageName + RECEIPT_ENDING; - File receiptFile; - try { - receiptFile = new File(temp.getCanonicalPath() + File.separator + receiptFilename); - } catch (IOException ex) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, - "Something is wrong with the receipt file!", ex); - return false; - } - - boolean exists = receiptFile.exists(); + File receiptFile = new File(temp, packageName + RECEIPT_ENDING); - if (!exists) { + if (!receiptFile.exists()) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, "The package " + packageName + " is not installed!"); return false; @@ -428,36 +395,30 @@ private static void installDependencies(MetadataApp metadata, } } - private static void removeAuxiliaryFiles(File installationDir, String appName) throws IOException { - String providerPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; - String transportPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; - File linux = new File(installationDir.getAbsolutePath() - + File.separator + "start_" + appName + ".sh"); - File windows = new File(installationDir.getAbsolutePath() - + File.separator + "start_" + appName + ".sh"); + private static void removeAuxiliaryFiles(File folder, String appName) throws IOException { + File provider = new File(folder, HelperMisc.PROVIDER_PROPERTIES_FILE); + File transport = new File(folder, HelperMisc.TRANSPORT_PROPERTIES_FILE); + File linux = new File(folder, "start_" + appName + ".sh"); + File windows = new File(folder, "start_" + appName + ".bat"); // Remove the provider.properties // Remove the transport.properties - // Remove the start_myAppName.sh - NMFPackageManager.removeFile(new File(providerPath)); - NMFPackageManager.removeFile(new File(transportPath)); + // Remove the start_myAppName.sh or start_myAppName.bat + NMFPackageManager.removeFile(provider); + NMFPackageManager.removeFile(transport); NMFPackageManager.removeFile(windows.exists() ? windows : linux); } private static void createAuxiliaryFiles(File installationDir, String username) throws IOException { // Generate provider.properties - String providerPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.PROVIDER_PROPERTIES_FILE; + File providerFile = new File(installationDir, HelperMisc.PROVIDER_PROPERTIES_FILE); String providerContent = HelperNMFPackage.generateProviderProperties(username); - HelperNMFPackage.writeFile(providerPath, providerContent); + HelperNMFPackage.writeFile(providerFile, providerContent); // Generate transport.properties - String transportPath = installationDir.getAbsolutePath() - + File.separator + HelperMisc.TRANSPORT_PROPERTIES_FILE; + File transportFile = new File(installationDir, HelperMisc.TRANSPORT_PROPERTIES_FILE); String transportContent = HelperNMFPackage.generateTransportProperties(); - HelperNMFPackage.writeFile(transportPath, transportContent); + HelperNMFPackage.writeFile(transportFile, transportContent); } private static void removeFiles(Metadata metadata) throws IOException { @@ -508,6 +469,16 @@ private static String generateUsername(String appName) { return USER_NMF_APP_PREFIX + appName; } + private static void changeGroupAndSetPermissions(File file, + String toGroup, String permissions) throws IOException { + if (toGroup != null) { + LinuxUsersGroups.chgrp(true, toGroup, file.getAbsolutePath()); + } + + // chmod the installation directory with recursive + LinuxUsersGroups.chmod(false, true, permissions, file.getAbsolutePath()); + } + private void stopAppIfRunning(String name) { if (appsLauncher == null) { return; @@ -537,7 +508,7 @@ private void stopAppIfRunning(String name) { appsLauncher.stopApp(runningApp, null); } } catch (MALInteractionException ex) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "The " + name + " App was not found in the Directory service!"); } catch (MALException ex) { Logger.getLogger(NMFPackageManager.class.getName()).log( diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java index 7763aae4b..e3899c8f2 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackagePMBackend.java @@ -90,7 +90,7 @@ public StringList getListOfPackages() throws IOException { @Override public void install(final String packageName) { String packageLocation = this.getFolderLocation(packageName); - File destination = getNMFDir(); + File destination = Deployment.getNMFRootDir(); Logger.getLogger(NMFPackagePMBackend.class.getName()).log(Level.INFO, "Installing the package...\nPackage name: " + packageName @@ -133,7 +133,7 @@ public void upgrade(final String packageName) { "Upgrading the package from: {0}", packageLocation); // Define the location to be installed! - File destination = getNMFDir(); + File destination = Deployment.getNMFRootDir(); try { manager.upgrade(packageLocation, destination); @@ -165,10 +165,6 @@ private String getFolderLocation(final String packageName) { return packagesFolder.getAbsolutePath() + File.separator + packageName; } - private File getNMFDir() { - return new File(""); - } - public void setAppsLauncher(AppsLauncherProviderServiceImpl appsLauncherService) { manager.setAppsLauncher(appsLauncherService); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index f69262999..8cc5d6c0c 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -157,11 +157,6 @@ public void store(OutputStream outStream) throws IOException { properties.store(outStream, "NMF Package Metadata"); } - @Deprecated - public void store() throws IOException, FileNotFoundException, IOException { - this.store(new FileOutputStream(Metadata.FILENAME)); - } - public void store(File file) throws FileNotFoundException, IOException { String parent = file.getParent(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java index f709f97d9..331cf2504 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataApp.java @@ -39,25 +39,27 @@ public class MetadataApp extends Metadata { public static final String APP_DEPENDENCIES = "pack.app.dependencies"; /** + * Constructor for the MetadataApp class. * * @param packageName The name of the package. - * @param version - * @param timestamp - * @param mainclass - * @param mainJar - * @param maxHeap - * @param dependencies + * @param version The version of the package. + * @param timestamp The timestamp of the package. + * @param mainclass The mainclass of the package. + * @param mainJar The main jar of the package. + * @param maxHeap The Maximum Heap of the package. + * @param dependencies The jar filenames dependencies of the App. */ public MetadataApp(final String packageName, final String version, final String mainclass, final String mainJar, final String maxHeap, - final ArrayList dependencies) { + final String minHeap, final ArrayList dependencies) { super(new Properties()); properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_APP); properties.put(Metadata.PACKAGE_NAME, packageName); properties.put(Metadata.PACKAGE_VERSION, version); properties.put(MetadataApp.APP_MAINCLASS, mainclass); properties.put(MetadataApp.APP_MAIN_JAR, mainJar); - properties.put(MetadataApp.APP_MAX_HEAP, maxHeap); + properties.put(MetadataApp.APP_MAX_HEAP, maxHeap == null ? "128m" : maxHeap); + properties.put(MetadataApp.APP_MIN_HEAP, minHeap == null ? "32m" : minHeap); if (dependencies != null && !dependencies.isEmpty()) { StringBuilder str = new StringBuilder(); @@ -68,6 +70,11 @@ public MetadataApp(final String packageName, final String version, } } + /** + * Constructor for the MetadataApp class. + * + * @param props The initial properties for the package. + */ MetadataApp(Properties props) { super(props); } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 8967c1c8f..4db3933c5 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -1,3 +1,4 @@ + /* ---------------------------------------------------------------------------- * Copyright (C) 2021 European Space Agency * European Space Operations Centre @@ -27,14 +28,10 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import java.util.Properties; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.zip.CRC32; /** @@ -100,8 +97,7 @@ public static String generateLinuxStartAppScript(String javaCommand, String shared = ""; if (meta.hasDependencies()) { - String nmf = Deployment.getNMFRootDir().getAbsolutePath(); - File sharedLibs = new File(nmf + File.separator + Deployment.DIR_JARS_SHARED); + File sharedLibs = Deployment.getJarsSharedDir(); String paths = meta.getAppDependenciesFullPaths(sharedLibs); str.append("JARS_SHARED=").append(paths); shared = ":$JARS_SHARED"; @@ -110,18 +106,25 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("\n\n"); str.append("if [ -z \"$JAVA_OPTS\" ] ; then\n"); - str.append(" JAVA_OPTS=\"-Xms32m -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); + str.append(" JAVA_OPTS=\"-Xms$MIN_HEAP -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); str.append("fi\n\n"); str.append("export JAVA_OPTS\n"); str.append("export NMF_LIB\n\n"); + str.append("NOW=$(date +\"%F\")\n"); + String appName = meta.getPackageName(); + str.append("FILENAME=").append(appName).append("_$NOW.log\n"); + str.append("LOG_PATH=/nanosat-mo-framework/logs/").append(appName).append("\n"); + str.append("mkdir -p $LOG_PATH\n\n"); + // The command "exec" spawns the execution in a different process // str.append("exec "); str.append("$JAVA_CMD $JAVA_OPTS \\\n"); str.append(" -classpath \"$JARS_ALL\" \\\n"); str.append(" \"$MAIN_CLASS\" \\\n"); - str.append(" \"$@\"\n"); + str.append(" \"$@\" \\\n"); + str.append(" 2>&1 | tee -a $LOG_PATH/$FILENAME \n"); return str.toString(); } @@ -246,120 +249,6 @@ public static File findAppJarInFolder(File folder) throws IOException { throw new IOException("There are too many jars inside the target folder!"); } - /** - * Find the best Java Runtime Environment inside an nmf directory. The best - * JRE will be determined based on arguments containing a recommended - * version, a minimum version, and a maximum version. - * - * @param recommended The recommended version to run the App. - * @param min The minimum version needed to run the App. - * @param max The maximum version to run the App. - * @return The Best JRE available for . - */ - public static String findJREPath(File nmfDir, int recommended, int min, int max) { - if (min < max) { - Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, - "The JRE minimum version cannot be greater than the maximum!"); - } - - if (recommended < min || recommended > max) { - Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, - "The JRE recommended version should be between the min and max!"); - } - - File javaNMFDir = new File(nmfDir.getAbsolutePath() + File.separator + "java"); - String bestJRE = "java"; // Default value and worst-case scenario - - if (!javaNMFDir.exists()) { - return bestJRE; // Return the default value - } - - final String VERSION_PROP = "JAVA_VERSION"; - File[] list = javaNMFDir.listFiles(); - - for (File dir : list) { - if (!dir.isDirectory()) { - continue; // Jump over if it is not a directory - } - - try { - // Check which java version it is from the release file... - String path = dir.getAbsolutePath(); - File release = new File(path + File.separator + "release"); - - if (!release.exists()) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "The JRE release file does not " - + "exist in: " + release.getAbsolutePath()); - continue; - } - - Properties props = new Properties(); - props.load(new FileInputStream(release)); - String version = (String) props.get(VERSION_PROP); - - if (version == null) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "The JAVA_VERSION property " - + "was not be found on release file: " + path); - continue; - } - - String[] subs = version.replace("\"", "").split("\\."); - - if (subs.length < 3) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "The JRE version '" + version - + "' could not be determined from the release file: " - + release.getAbsolutePath()); - continue; - } - - // Java version used to start with 1 until at least Java 8 - int java_version = (Integer.parseInt(subs[0]) != 1) - ? Integer.parseInt(subs[0]) - : Integer.parseInt(subs[1]); - - String jre = dir.getAbsolutePath() + File.separator - + "bin" + File.separator + "java"; - - if (!(new File(jre)).exists()) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, - "The JRE could not be found in directory: " + path); - continue; - } - - if (java_version == recommended) { - // Perfect, just return it directly! - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.INFO, "The JRE version " + java_version - + " was successfully found in directory:" - + "\n >> " + jre); - - return jre; - } - - // The version is outside boundaries? - if (java_version < min && java_version > max) { - continue; - } - bestJRE = jre; - // The code here will need to be improved... - // The objective should be to return the - // highest available version within the choices - } catch (FileNotFoundException ex) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "Something went wrong...", ex); - } catch (IOException ex) { - Logger.getLogger(HelperNMFPackage.class.getName()).log( - Level.WARNING, "Something went wrong...", ex); - } - } - - return bestJRE; - } - public static void generateStartScript(MetadataApp appDetails, File appDir, File nmfDir) throws IOException { String name = appDetails.getPackageName(); @@ -372,33 +261,29 @@ public static void generateStartScript(MetadataApp appDetails, // The Java version for now will be forced to 8, however in // the future the package should recommend a version - String javaCMD = HelperNMFPackage.findJREPath(nmfDir, 8, 8, 8); + String javaCMD = Deployment.findJREPath(nmfDir, 8, 8, 8); OSValidator os = new OSValidator(); - String path = appDir.getAbsolutePath() + File.separator; if (os.isUnix() || os.isMac()) { String content = generateLinuxStartAppScript(javaCMD, jarName, appDetails); - - path += "start_" + name + ".sh"; - HelperNMFPackage.writeFile(path, content); - File startApp = new File(path); + File startApp = new File(appDir, "start_" + name + ".sh"); + HelperNMFPackage.writeFile(startApp, content); startApp.setExecutable(true, true); } if (os.isWindows()) { String content = HelperNMFPackage.generateWindowsStartAppScript( javaCMD, jarName, appDetails); - - path += "start_" + name + ".bat"; - HelperNMFPackage.writeFile(path, content); + File startApp = new File(appDir, "start_" + name + ".bat"); + HelperNMFPackage.writeFile(startApp, content); } } - public static void writeFile(String path, String content) { - System.out.println(" >> Creating file on: " + path); + public static void writeFile(File file, String content) { + System.out.println(" >> Creating file on: " + file); - try (FileWriter writer = new FileWriter(path)) { + try (FileWriter writer = new FileWriter(file)) { writer.write(content); writer.flush(); writer.close(); diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 8fb853c9e..8732547b3 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -84,6 +84,12 @@ public class GenerateNMFPackageMojo extends AbstractMojo { @Parameter(property = "generate-nmf-package.maxHeap", defaultValue = "128m") private String maxHeap; + /** + * The App maximum heap size to be set on the JVM + */ + @Parameter(property = "generate-nmf-package.maxHeap", defaultValue = "16m") + private String minHeap; + /** * The set of libraries to be added to the .nmfpack */ @@ -200,7 +206,7 @@ public void execute() throws MojoExecutionException { // Package MetadataApp metadata = new MetadataApp(name, version, - mainClass, mainJar, maxHeap, dependencies); + mainClass, mainJar, maxHeap, minHeap, dependencies); NMFPackageCreator.create(metadata, inputFiles, locations, TARGET_FOLDER); } From 0762e92aed7ddbbdba44c9a67e7a103d4aec8166 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Tue, 1 Nov 2022 20:14:58 +0100 Subject: [PATCH 126/173] [edge-ai] Code cleanup --- .../src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java index 19e5a0842..e66ceedc7 100644 --- a/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java +++ b/sdk/examples/space/edge-ai/src/main/java/esa/mo/nmf/apps/edgeai/MCAdapter.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.apps.edgeai; -import static esa.mo.helpertools.helpers.HelperAttributes.attribute2JavaType; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.mal.provider.MALInteraction; @@ -34,7 +33,6 @@ import org.ccsds.moims.mo.mc.action.structures.ActionDefinitionDetailsList; import org.ccsds.moims.mo.mc.structures.ArgumentDefinitionDetails; import org.ccsds.moims.mo.mc.structures.ArgumentDefinitionDetailsList; -import org.ccsds.moims.mo.mc.structures.AttributeValue; import org.ccsds.moims.mo.mc.structures.AttributeValueList; import esa.mo.nmf.MCRegistration; import esa.mo.nmf.MonitorAndControlNMFAdapter; @@ -202,11 +200,4 @@ private void publishParameter(String id, int exitCode) { } } - private static T getAs(AttributeValue attributeValue) { - if (attributeValue == null) { - return null; - } - return (T) attribute2JavaType(attributeValue.getValue()); - } - } From 9adf3a19a1fb82eab7b4b5a7b9f63baff7c75665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Thu, 3 Nov 2022 18:01:24 +0100 Subject: [PATCH 127/173] Adds to the ShellCommander the ability to run commands from a Mac machine --- .../esa/mo/helpertools/misc/ShellCommander.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java index 63004da0f..fa89ebdc5 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/ShellCommander.java @@ -117,19 +117,18 @@ public String runCommandAndGetOutputMessageAndError(String cmd) { */ public Process runCommand(String cmd, File dirPath) { try { - Process proc; - if (osValidator.isUnix()) { - proc = Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd}, null, dirPath); + return Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd}, null, dirPath); + } else if (osValidator.isMac()) { + return Runtime.getRuntime().exec(new String[]{"sh", "-c", cmd}, null, dirPath); } else if (osValidator.isWindows()) { - proc = Runtime.getRuntime().exec(new String[]{"cmd", "/c", cmd}, null, dirPath); + return Runtime.getRuntime().exec(new String[]{"cmd", "/c", cmd}, null, dirPath); } else { - Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, - "The command could not executed due to an Unknown OS!"); + Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, + "The command could not be executed! Unknown OS: {0}", + osValidator.getOS()); return null; } - - return proc; } catch (IOException ex) { Logger.getLogger(ShellCommander.class.getName()).log(Level.SEVERE, "The command could not be executed!", ex); From 675010934546cb3ac1ca79146143dcf232f407ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Thu, 3 Nov 2022 18:52:05 +0100 Subject: [PATCH 128/173] Code cleanup --- .../sm/impl/provider/AppsLauncherManager.java | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java index 854f7e731..3d6364ad1 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherManager.java @@ -92,9 +92,9 @@ public class AppsLauncherManager extends DefinitionsManager { /** * Location of the apps folder, relative to the MO Supervisor */ - private ArrayList foldersWithApps = new ArrayList<>(); - private final HashMap handlers - = new HashMap<>(); + private final ArrayList foldersWithApps = new ArrayList<>(); + + private final HashMap handlers = new HashMap<>(); private AtomicLong uniqueObjIdDef; // Counter @@ -321,8 +321,7 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { File[] list = appsFolderPath.listFiles(); if (list != null) { - for (int i = 0; i < list.length; i++) { - File appFolder = list[i]; + for (File appFolder : list) { if ((appFolder != null) && appFolder.isDirectory()) { fList.add(appFolder); } @@ -330,17 +329,6 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { } } - // Go to all the "apps folder" and check if there are new folders - // get all the files from a directory - //File[] fList = appsFolderPath.listFiles(); -/* - if (fList == null) { - LOGGER.log(Level.SEVERE, "The directory could not be found: {0} (full path: {1})", - new Object[]{appsFolderPath.toString(), appsFolderPath.getAbsolutePath()}); - - return false; - } - */ AppDetailsList apps = new AppDetailsList(); for (File folder : fList) { // Roll all the apps inside the apps folder @@ -402,8 +390,7 @@ protected boolean refreshAvailableAppsList(final URI providerURI) { for (File file : folder.listFiles()) { // Roll all the files inside each app folder // Check if the folder contains the provider properties if (HelperMisc.PROVIDER_PROPERTIES_FILE.equals(file.getName())) { - // All Good! - appStillIntact = true; + appStillIntact = true; // All Good! break; } } @@ -441,13 +428,12 @@ protected String[] assembleCommand(final String workDir, final String appName, final String runAs, final String prefix, final String[] env) { ArrayList ret = new ArrayList<>(); String trimmedAppName = appName.replaceAll("space-app-", ""); + if (osValidator.isWindows()) { ret.add("cmd"); ret.add("/c"); StringBuilder str = new StringBuilder(); - str.append(prefix); - str.append(trimmedAppName); - str.append(".bat"); + str.append(prefix).append(trimmedAppName).append(".bat"); ret.add(str.toString()); } else { if (runAs != null) { @@ -464,11 +450,11 @@ protected String[] assembleCommand(final String workDir, final String appName, } StringBuilder envString = new StringBuilder(); for (String envVar : env) { - envString.append(envVar); - envString.append(" "); + envString.append(envVar).append(" "); } - ret.add("cd " + workDir + ";" + envString.toString() + "./" + prefix + trimmedAppName + ".sh"); + String script = prefix + trimmedAppName + ".sh"; + ret.add("cd " + workDir + ";" + envString.toString() + "./" + script); } return ret.toArray(new String[0]); } From 05929085a469e9d0e912f959c2fb4cae4431e50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Fri, 4 Nov 2022 10:34:17 +0100 Subject: [PATCH 129/173] Fixes null pointer exception when trying to get the metadata of the NMF Package --- .../src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 78a1c0555..6c3ef205d 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -79,7 +79,7 @@ public ZipEntry getZipFileEntry(String path) { } public void verifyPackageIntegrity() throws IOException { - ArrayList files = metadata.getFiles(); + ArrayList files = this.getMetadata().getFiles(); for (int i = 0; i < files.size(); i++) { NMFPackageFile filepack = files.get(i); From 8c2642484d0b77641baca2b1f596d98a263da9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Fri, 4 Nov 2022 10:40:57 +0100 Subject: [PATCH 130/173] (2) Fixes null pointer exception when trying to get the metadata of the NMF Package --- .../src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 6c3ef205d..2e79a22aa 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -109,7 +109,7 @@ public void extractFiles(File to) throws IOException { byte[] buffer = new byte[1024]; // Iterate through the files, unpack them into the right folders - ArrayList files = metadata.getFiles(); + ArrayList files = this.getMetadata().getFiles(); for (int i = 0; i < files.size(); i++) { NMFPackageFile file = files.get(i); From 744ecdefddc6cce9f5b176398a52864a01d8b42b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Fri, 4 Nov 2022 15:03:25 +0100 Subject: [PATCH 131/173] Adds support to Mac OS for the AI service execution --- .../java/esa/mo/helpertools/misc/OSValidator.java | 2 +- .../impl/provider/adapters/AIMovidiusAdapter.java | 14 +++++++------- .../mo/nmf/nmfpackage/utils/HelperNMFPackage.java | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java index a2c5d6e62..176ff7430 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/misc/OSValidator.java @@ -52,7 +52,7 @@ public String getOS() { if (isWindows()) { return "win"; } else if (isMac()) { - return "osx"; + return "mac"; } else if (isUnix()) { return "uni"; } else if (isSolaris()) { diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java index feaa53513..b3e4d5214 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/adapters/AIMovidiusAdapter.java @@ -61,7 +61,7 @@ public AIMovidiusAdapter() throws IOException { + " The command returned: " + out); } - LOGGER.log(Level.FINE, "The Python3 version is: " + splits[1]); + LOGGER.log(Level.FINE, "The Python3 version is: {0}", splits[1]); String[] subVersions = splits[1].split("\\."); if (Integer.valueOf(subVersions[1]) < 6) { @@ -69,21 +69,21 @@ public AIMovidiusAdapter() throws IOException { + "\n>>>> Please update your Python version!"); } - // Is it Linux or Windows? - if (os.isUnix()) { + // Is it Linux or Mac? + if (os.isUnix() || os.isMac()) { // Find the folder where the Intel Movidius software is installed String[] options = { "/opt/intel" }; File file; - try{ + try { file = this.crawlOptions(options, "setupvars.sh"); - }catch(IOException ex){ + } catch (IOException ex) { LOGGER.log(Level.WARNING, "The setupvars.sh was not found!"); file = new File(""); } - + setupVarsPath = file; return; } @@ -172,7 +172,7 @@ public void executeInference(String modelPath, String weightsPath, String pythonCmd = buildPythonCommand(modelPath, weightsPath, inputPath, outputPath); String cmd = null; - if (os.isUnix()) { + if (os.isUnix() || os.isMac()) { cmd = this.generateScriptSH(pathIntelVar, pythonCmd); } if (os.isWindows()) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 4db3933c5..c33fb0ae9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -117,7 +117,7 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("FILENAME=").append(appName).append("_$NOW.log\n"); str.append("LOG_PATH=/nanosat-mo-framework/logs/").append(appName).append("\n"); str.append("mkdir -p $LOG_PATH\n\n"); - + // The command "exec" spawns the execution in a different process // str.append("exec "); str.append("$JAVA_CMD $JAVA_OPTS \\\n"); From 05109cb4c73441d5fec8efe1ea0887ecbbf0f457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Fri, 4 Nov 2022 15:59:54 +0100 Subject: [PATCH 132/173] [ctt] Close button is now threading the shutdown of the connections --- .../DirectoryConnectionConsumerPanel.java | 263 +++++++++--------- 1 file changed, 137 insertions(+), 126 deletions(-) diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java index 89a05c184..b6c05dc41 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java @@ -24,9 +24,6 @@ import esa.mo.helpertools.connections.SingleConnectionDetails; import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.nmf.groundmoadapter.GroundMOAdapterImpl; - -import java.util.Random; -import java.util.prefs.Preferences; import java.awt.Component; import java.awt.Font; import java.awt.GridBagConstraints; @@ -35,13 +32,14 @@ import java.net.MalformedURLException; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.prefs.Preferences; +import java.util.Random; import javax.swing.DefaultListModel; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTabbedPane; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableModel; - import org.ccsds.moims.mo.com.archive.ArchiveHelper; import org.ccsds.moims.mo.common.directory.DirectoryHelper; import org.ccsds.moims.mo.common.directory.structures.ProviderSummary; @@ -61,95 +59,84 @@ * @author Cesar Coelho */ public class DirectoryConnectionConsumerPanel extends javax.swing.JPanel { - private static Random RANDOM = new Random(); - private ConnectionConsumer connectionConsumer; - private javax.swing.JTabbedPane tabs; - private ProviderSummaryList summaryList; - private DefaultTableModel tableData; - private final boolean isS2G; - private static final String LAST_USED_CONSUMER_PREF = "last_used_consumer"; - private static Preferences prefs = Preferences.userNodeForPackage(DirectoryConnectionConsumerPanel.class); - - /** - * Creates new form ConsumerPanelArchive - * - * @param isS2G Flag that defines if it is a Space to Ground link - * @param connectionConsumer - * @param tabs - */ - public DirectoryConnectionConsumerPanel(final boolean isS2G, final ConnectionConsumer connectionConsumer, - final JTabbedPane tabs) { - initComponents(); - this.connectionConsumer = connectionConsumer; - this.tabs = tabs; - this.initTextBoxAddress(); - this.isS2G = isS2G; - - String[] tableCol = new String[]{"Service name", "Supported Capabilities", "Service Properties", "URI address", - "Broker URI Address"}; - - tableData = new javax.swing.table.DefaultTableModel(new Object[][]{}, tableCol) { - Class[] types = new Class[]{java.lang.String.class, java.lang.String.class, java.lang.String.class, - java.lang.String.class, java.lang.String.class}; - - @Override //all cells false - public boolean isCellEditable(int row, int column) { - return false; - } - - @Override - public Class getColumnClass(int columnIndex) { - return types[columnIndex]; - } - }; - - jTable1.setModel(tableData); - - ListSelectionListener listSelectionListener = listSelectionEvent -> { - // Update the jTable according to the selection of the index - cleanTableData(); - - int index = providersList.getSelectedIndex(); - - if (index == -1) { - index = 0; - } - - ServiceCapabilityList services = summaryList.get(index).getProviderDetails().getServiceCapabilities(); - - // And then add the new stuff - for (int i = 0; i < services.size(); i++) { - ServiceCapability service = services.get(i); - String serviceName; - try { - serviceName = HelperMisc.serviceKey2name(service.getServiceKey().getKeyArea(), service - .getServiceKey().getKeyAreaVersion(), service.getServiceKey().getKeyService()); - } catch (MALException ex) { - serviceName = ""; - } - - String serviceURI = ""; - String brokerURI = ""; - - if (service.getServiceAddresses().size() > 0) { - serviceURI = service.getServiceAddresses().get(0).getServiceURI().toString(); - // To avoid null pointers here... - brokerURI = (service.getServiceAddresses().get(0).getBrokerURI() == null) ? "null" : service - .getServiceAddresses().get(0).getBrokerURI().toString(); - } - - String supportedCapabilities = (service.getSupportedCapabilitySets() == null) ? "All Supported" : - service.getSupportedCapabilitySets().toString(); - - tableData.addRow(new Object[]{serviceName, supportedCapabilities, service.getServiceProperties() - .toString(), serviceURI, brokerURI}); - } - }; + private final javax.swing.JTabbedPane tabs; + private ConnectionConsumer connectionConsumer; + private ProviderSummaryList summaryList; + private DefaultTableModel tableData; + private final boolean isS2G; + private static final String LAST_USED_CONSUMER_PREF = "last_used_consumer"; + private static Preferences prefs = Preferences.userNodeForPackage(DirectoryConnectionConsumerPanel.class); + + /** + * Creates new form ConsumerPanelArchive + * + * @param isS2G Flag that defines if it is a Space to Ground link + * @param connectionConsumer + * @param tabs + */ + public DirectoryConnectionConsumerPanel(final boolean isS2G, + final ConnectionConsumer connectionConsumer, final JTabbedPane tabs) + { + initComponents(); + this.connectionConsumer = connectionConsumer; + this.tabs = tabs; + this.initTextBoxAddress(); + this.isS2G = isS2G; + + String[] tableCol = new String[]{"Service name", "Supported Capabilities", + "Service Properties", "URI address", "Broker URI Address"}; + + tableData = new javax.swing.table.DefaultTableModel( + new Object[][]{}, tableCol) + { + Class[] types = new Class[]{ + java.lang.String.class, java.lang.String.class, java.lang.String.class, + java.lang.String.class, java.lang.String.class + }; + + @Override //all cells false + public boolean isCellEditable(int row, int column) + { + return false; + } + + @Override + public Class getColumnClass(int columnIndex) + { + return types[columnIndex]; + } + }; + + jTable1.setModel(tableData); + + ListSelectionListener listSelectionListener = listSelectionEvent -> { + // Update the jTable according to the selection of the index + cleanTableData(); + + int index = providersList.getSelectedIndex(); + + if (index == -1) { + index = 0; + } + + ServiceCapabilityList services + = summaryList.get(index).getProviderDetails().getServiceCapabilities(); + + // And then add the new stuff + for (int i = 0; i < services.size(); i++) { + ServiceCapability service = services.get(i); + + String serviceName; + try { + serviceName = HelperMisc.serviceKey2name(service.getServiceKey().getKeyArea(), + service.getServiceKey().getKeyAreaVersion(), service.getServiceKey().getKeyService()); + } catch (MALException ex) { + serviceName = ""; + } - providersList.addListSelectionListener(listSelectionListener); - connectButton.setEnabled(false); - } + String serviceURI = ""; + String brokerURI = ""; /** * Cleans the table data that contains the list of services provided by the currently selected prodiver. @@ -158,6 +145,30 @@ private void cleanTableData() { while (tableData.getRowCount() != 0) { tableData.removeRow(tableData.getRowCount() - 1); } + + String supportedCapabilities = (service.getSupportedCapabilitySets() == null) + ? "All Supported" : service.getSupportedCapabilitySets().toString(); + + tableData.addRow(new Object[]{ + serviceName, + supportedCapabilities, + service.getServiceProperties().toString(), + serviceURI, + brokerURI + }); + } + }; + + providersList.addListSelectionListener(listSelectionListener); + connectButton.setEnabled(false); + } + + /** + * Cleans the table data that contains the list of services provided by the currently selected provider. + */ + private void cleanTableData() { + while (tableData.getRowCount() != 0) { + tableData.removeRow(tableData.getRowCount() - 1); } public void setURITextbox(final String uri) { @@ -451,46 +462,46 @@ public class CloseMouseHandler implements MouseListener { this.providerPanel = providerPanel; } - @Override - public void mouseClicked(MouseEvent evt) { + @Override + public void mouseClicked(MouseEvent evt) { + for (int i = 0; i < tabs.getTabCount(); i++) { + final Component component = tabs.getTabComponentAt(i); + + if (component == panel) { + tabs.remove(i); + tabs.revalidate(); + tabs.repaint(); + Thread t1 = new Thread() { @Override public void run() { - this.setName("CloseButtonTabThread"); - for (int i = 0; i < tabs.getTabCount(); i++) { - Component component = tabs.getTabComponentAt(i); - - if (component == panel) { - tabs.remove(i); - - try { - if (providerPanel.getServices().getAuthenticationId() != null) { - try { - providerPanel.getServices().getCommonServices().getLoginService().getLoginStub() - .logout(); - providerPanel.getServices().setAuthenticationId(null); - Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()).log( - Level.INFO, "Logged out successfully"); - - } catch (MALInteractionException | MALException e) { - Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()).log( - Level.SEVERE, "Unexpected exception during logout!", e); - } - } - providerPanel.getServices().closeConnections(); - } catch (Exception ex) { - Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()).log(Level.WARNING, - "The connection was not closed correctly. Maybe the provider was unreachable!"); - } - - return; - } - } - } - }; - + this.setName("CloseButtonTabThread"); + + try { + if(providerPanel.getServices().getAuthenticationId() != null) { + try { + providerPanel.getServices().getCommonServices().getLoginService().getLoginStub().logout(); + providerPanel.getServices().setAuthenticationId(null); + Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()) + .log(Level.INFO, "Logged out successfully"); + } catch (MALInteractionException | MALException e) { + Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()) + .log(Level.SEVERE, "Unexpected exception during logout!", e); + } + } + providerPanel.getServices().closeConnections(); + } catch (Exception ex) { + Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()).log(Level.WARNING, + "The connection was not closed correctly. Maybe the provider was unreachable!"); + } + } + }; + t1.start(); + return; + } } + } @Override public void mousePressed(MouseEvent me) { From bddf3f625df4ed3542464e5ed721ea39b64b8d34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Fri, 4 Nov 2022 16:29:11 +0100 Subject: [PATCH 133/173] Adds support to non-fixed camera resolutions --- .../provider/gen/CameraAdapterInterface.java | 6 ++++ .../gen/CameraProviderServiceImpl.java | 29 ++++++++++--------- .../softsim/CameraSoftSimAdapter.java | 5 ++++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java index 8cd56a8b2..c1e625513 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraAdapterInterface.java @@ -41,6 +41,12 @@ public interface CameraAdapterInterface { */ boolean isUnitAvailable(); + /** + * @return true if the camera has only a fixed set of resolutions. They can + * then be retrieved with the getAvailableResolutions() method. + */ + boolean hasFixedResolutions(); + /** * @return The resolutions supported by the Camera Adapter */ diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java index a8cdc5d15..25d9a2319 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/CameraProviderServiceImpl.java @@ -100,7 +100,7 @@ public class CameraProviderServiceImpl extends CameraInheritanceSkeleton { public synchronized void init(COMServicesProvider comServices, CameraAdapterInterface adapter) throws MALException { long timestamp = System.currentTimeMillis(); - + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -220,20 +220,23 @@ private void isCapturePossible(final CameraSettings settings) throws MALInteract PlatformHelper.DEVICE_IN_USE_ERROR_NUMBER, null)); } final PixelResolutionList availableResolutions = adapter.getAvailableResolutions(); - boolean isResolutionAvailable = false; - // Do we have the resolution requested? - for (PixelResolution availableResolution : availableResolutions) { - if (settings.getResolution().equals(availableResolution)) { - isResolutionAvailable = true; - break; + if (adapter.hasFixedResolutions()) { + boolean isResolutionAvailable = false; + + // Do we have the resolution requested? + for (PixelResolution availableResolution : availableResolutions) { + if (settings.getResolution().equals(availableResolution)) { + isResolutionAvailable = true; + break; + } } - } - // If not, then send the available resolutions to the consumer so they can pick... - if (!isResolutionAvailable) { - throw new MALInteractionException(new MALStandardError( - COMHelper.INVALID_ERROR_NUMBER, availableResolutions)); + // If not, then send the available resolutions to the consumer so they can pick... + if (!isResolutionAvailable) { + throw new MALInteractionException(new MALStandardError( + COMHelper.INVALID_ERROR_NUMBER, availableResolutions)); + } } boolean isFormatsAvailable = false; @@ -364,7 +367,7 @@ public GetPropertiesResponse getProperties(MALInteraction interaction) throws } @Override - public void preprocessPicture(Picture inputPicture, CameraSettings settings, + public void preprocessPicture(Picture inputPicture, CameraSettings settings, PreprocessPictureInteraction interaction) throws MALInteractionException, MALException { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/CameraSoftSimAdapter.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/CameraSoftSimAdapter.java index d7bd8a249..003301c0c 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/CameraSoftSimAdapter.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/provider/softsim/CameraSoftSimAdapter.java @@ -177,4 +177,9 @@ public boolean isUnitAvailable() { return pcAdapter.isDeviceEnabled(DeviceType.CAMERA); } + @Override + public boolean hasFixedResolutions() + { + return true; + } } From 243e180fa52eaf9b02755abd6240f103bd682a70 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 14 Nov 2022 18:25:17 +0100 Subject: [PATCH 134/173] Fixes to make the code compilable --- .../impl/provider/AppsLauncherProviderServiceImpl.java | 5 ++--- .../java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java | 10 ---------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java index e3ca36921..6a8de7faa 100644 --- a/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-software-management-impl/src/main/java/esa/mo/sm/impl/provider/AppsLauncherProviderServiceImpl.java @@ -473,7 +473,7 @@ private void prepareStopApp(final LongList appInstIds, final StopAppInteraction ServiceKey serviceKey = new ServiceKey(eventCOM.getArea().getNumber(), eventCOM.getNumber(), eventCOM.getArea().getVersion()); ServiceFilter sf = new ServiceFilter(serviceProviderName, domain, new Identifier("*"), - null, new Identifier("*"), serviceKey, new UIntegerList()); + null, new Identifier("*"), serviceKey, new UShortList()); if (app.getCategory().getValue().equalsIgnoreCase("NMF_App")) { // Do a lookup on the Central Drectory service for the app that we want MALInteraction malInt = (interaction != null) ? interaction.getInteraction() : null; @@ -482,14 +482,13 @@ private void prepareStopApp(final LongList appInstIds, final StopAppInteraction try { // Add here the filtering for the best IPC!!! - final SingleConnectionDetails connectionDetails = AppsLauncherManager.getSingleConnectionDetailsFromProviderSummaryList(providersList); appConnections.add(connectionDetails); // Add to the list of Directory service Obj Ids if (!providersList.isEmpty()) { - appDirectoryServiceNames.add(providersList.get(0).getProviderName()); + appDirectoryServiceNames.add(providersList.get(0).getProviderId()); } else { appDirectoryServiceNames.add(null); } diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java index ade146c9a..07bf180b9 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java @@ -83,16 +83,6 @@ public ProviderTabPanel(final ProviderSummary provider, Blob authenticationId, S initComponents(); } - /** - * Creates a new tab for a Provider and populates it. - * - * @param connection - */ - public ProviderTabPanel(final ConnectionConsumer connection) { - services = new GroundMOAdapterImpl(connection); - initComponents(); - } - public GroundMOAdapterImpl getServices() { return this.services; } From 39e011c4d1b954db46d05db12447aab6c4646666 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 16 Nov 2022 13:22:48 +0100 Subject: [PATCH 135/173] Fixes the adduser problem when the command is called for a BusyBox installation --- .../java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java index f1795c268..e305ac030 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java @@ -105,7 +105,7 @@ public static void addgroup(String groupName, boolean isSystemGroup) throws IOEx public static void adduser(String username, String password, boolean withGroup) throws IOException { // First, we need to check if the "useradd" is from BusyBox or not - String[] cmd1 = {"sudo", "adduser", "-h"}; + String[] cmd1 = {"sudo", "adduser", "--help"}; String out1 = runCommand(cmd1); // Different Linux Systems have different syntaxes for the same command @@ -271,8 +271,9 @@ private static String runCommand(String[] cmd) throws IOException { if (exitValue != 0) { // Error! String error = extractString(p.getErrorStream()); - throw new IOException("There was an error:\n >> " - + String.join(" ", cmd) + "\n" + out + "\nError:\n" + error); + throw new IOException("There was an error with code " + exitValue + + ". For command:\n >> " + String.join(" ", cmd) + "\n" + + out + "\nError:\n" + error); } return out; From ba2419fb8424eee56ca7976d16196431551501e4 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 16 Nov 2022 13:23:21 +0100 Subject: [PATCH 136/173] The logs folder is now selected from the Deployment static class --- .../java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index c33fb0ae9..55f24f1ce 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -115,7 +115,8 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("NOW=$(date +\"%F\")\n"); String appName = meta.getPackageName(); str.append("FILENAME=").append(appName).append("_$NOW.log\n"); - str.append("LOG_PATH=/nanosat-mo-framework/logs/").append(appName).append("\n"); + String logPath = Deployment.getLogsDir().getAbsolutePath(); + str.append("LOG_PATH=").append(logPath).append("/").append(appName).append("\n"); str.append("mkdir -p $LOG_PATH\n\n"); // The command "exec" spawns the execution in a different process From 6e49780868c6e186301345e0a403e3858d8ba4ea Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 16 Nov 2022 13:44:00 +0100 Subject: [PATCH 137/173] Forces the transport to bind on 127.0.0.1 but with a auto-allocated port number --- .../java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 55f24f1ce..eb97af625 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -203,8 +203,8 @@ public static String generateTransportProperties() throws IOException { str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); */ - str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=true\n"); - str.append("#org.ccsds.moims.mo.mal.transport.tcpip.host=xxx.xxx.xxx.xxx\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=127.0.0.1\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); return str.toString(); From b717c5d85c84dfbe982c96651fdfd2c591a159a6 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 16 Nov 2022 22:27:39 +0100 Subject: [PATCH 138/173] Better Package Management handling --- .../NanoSatMOSupervisor.java | 2 +- .../esa/mo/nmf/nmfpackage/Deployment.java | 81 +++++++++++++------ .../mo/nmf/nmfpackage/NMFPackageManager.java | 67 +++++++++------ .../nmfpackage/utils/HelperNMFPackage.java | 16 ++-- .../nmfpackage/utils/LinuxUsersGroups.java | 1 + 5 files changed, 108 insertions(+), 59 deletions(-) diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index 635766c8c..09daf6a1f 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -106,7 +106,7 @@ public void init(MonitorAndControlNMFAdapter mcAdapter, this.comServices.initArchiveSync(); super.reconfigurableServices.add(this.appsLauncherService); this.appsLauncherService.setStdQuotaPerApp(stdQuota); - this.appsLauncherService.addFolderWithApps(Deployment.getNMFAppsDir()); + this.appsLauncherService.addFolderWithApps(Deployment.getAppsDir()); this.comServices.getArchiveSyncService().setStdQuota(stdQuota); this.startMCServices(mcAdapter); this.initPlatformServices(comServices); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index d7ff01e3e..fb71b7dee 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -30,6 +30,9 @@ import java.util.logging.Logger; /** + * The Deployment class is contains the information on how the NMF root + * directory is expected to look like and where the NMF files and folders can be + * found. * * @author Cesar Coelho */ @@ -42,6 +45,8 @@ public class Deployment { public static final String DIR_ETC = "etc"; public static final String DIR_JARS_MISSION = "jars-mission"; public static final String DIR_JARS_NMF = "jars-nmf"; + @Deprecated + public static final String DIR_JARS_NMF_OLD = "libs"; public static final String DIR_JARS_SHARED = "jars-shared-libraries"; public static final String DIR_JAVA = "java"; public static final String DIR_LOGS = "logs"; @@ -54,49 +59,75 @@ public class Deployment { private static File pathNMF = null; - public static File getInstallationsTrackerDir() { - // Default location of the folder - File folder = new File(getEtcDir(), DIR_INSTALLATIONS_TRACKER); + public synchronized static File getNMFRootDir() { + if (pathNMF != null) { + return pathNMF; + } - // Read the Property of the folder to install the packages - if (System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER) != null) { - folder = new File(System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER)); + File folder = new File((new File("")).getAbsolutePath()); + String currentFolder = folder.getName(); + + // Default location of the folder + if (DIR_NMF.equals(currentFolder) || "supervisor".equals(currentFolder)) { + pathNMF = folder; + return pathNMF; } + // We need additional logic to make sure we are in the right directory! return folder; } - + + public static File getAppsDir() { + return new File(getNMFRootDir(), DIR_APPS); + } + + public static File getDriversDir() { + return new File(getNMFRootDir(), DIR_DRIVERS); + } + public static File getEtcDir() { return new File(getNMFRootDir(), DIR_ETC); } - - public static File getLogsDir() { - return new File(getNMFRootDir(), DIR_LOGS); - } - public static File getNMFAppsDir() { - return new File(getNMFRootDir(), DIR_APPS); + public static File getJarsNMFDir() { + File deprecatedFolder = new File(getNMFRootDir(), DIR_JARS_NMF_OLD); + + if (deprecatedFolder.exists()) { + return deprecatedFolder; + } + + return new File(getNMFRootDir(), DIR_JARS_NMF); } public static File getJarsSharedDir() { return new File(getNMFRootDir(), DIR_JARS_SHARED); } - public static File getNMFRootDir() { - if (pathNMF != null) { - return pathNMF; - } + public static File getJarsMissionDir() { + return new File(getNMFRootDir(), DIR_JARS_MISSION); + } - File folder = new File((new File("")).getAbsolutePath()); - String currentFolder = folder.getName(); + public static File getJavaDir() { + return new File(getNMFRootDir(), DIR_JAVA); + } + + public static File getLogsDir() { + return new File(getNMFRootDir(), DIR_LOGS); + } + + public static File getLogsDirForApp(String appName) { + return new File(getLogsDir(), "app_" + appName); + } + public static File getInstallationsTrackerDir() { // Default location of the folder - if (DIR_NMF.equals(currentFolder) || "supervisor".equals(currentFolder)) { - pathNMF = folder; - return pathNMF; + File folder = new File(getEtcDir(), DIR_INSTALLATIONS_TRACKER); + + // Read the Property of the folder to install the packages + if (System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER) != null) { + folder = new File(System.getProperty(PROPERTY_INSTALLED_RECEIPTS_FOLDER)); } - // We need additional logic to make sure we are in the right directory! return folder; } @@ -110,7 +141,7 @@ public static File getNMFRootDir() { * @param max The maximum version to run the App. * @return The Best JRE available for . */ - public static String findJREPath(File nmfDir, int recommended, int min, int max) { + public static String findJREPath(int recommended, int min, int max) { if (min < max) { Logger.getLogger(HelperNMFPackage.class.getName()).log(Level.WARNING, "The JRE minimum version cannot be greater than the maximum!"); @@ -121,7 +152,7 @@ public static String findJREPath(File nmfDir, int recommended, int min, int max) "The JRE recommended version should be between the min and max!"); } - File javaNMFDir = new File(nmfDir, DIR_JAVA); + File javaNMFDir = getJavaDir(); String bestJRE = "java"; // Default value and worst-case scenario if (!javaNMFDir.exists()) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index ebaa282ba..b39304ff2 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -115,18 +115,21 @@ public void install(final String packageLocation, String packageName = metadata.getPackageName(); if (metadata.isApp()) { - File appDir = new File(Deployment.getNMFAppsDir(), packageName); - String username = null; + String username = generateUsername(packageName); String password = null; + File appDir = new File(Deployment.getAppsDir(), packageName); + HelperNMFPackage.generateStartScript(metadata.castToApp(), appDir, nmfDir); + createAuxiliaryFiles(appDir, username); + File logDir = Deployment.getLogsDirForApp(packageName); + logDir.mkdirs(); + if (OS.isUnix()) { try { // Create the User for this App - username = generateUsername(packageName); boolean withGroup = true; LinuxUsersGroups.adduser(username, password, withGroup); LinuxUsersGroups.addUserToGroup(username, GROUP_NMF_APPS); - //LinuxUsersGroups.useradd(username, password, withGroup, GROUP_NMF_APPS); // Set the right Group and Permissions to the Home Directory // The owner remains with the app, the group is nmf-admin @@ -140,14 +143,15 @@ public void install(final String packageLocation, } } - HelperNMFPackage.generateStartScript(metadata.castToApp(), appDir, nmfDir); - createAuxiliaryFiles(appDir, username); - File logDir = new File(Deployment.getLogsDir(), packageName); - logDir.mkdirs(); - if (OS.isUnix()) { // Change Group owner of the appDir changeGroupAndSetPermissions(appDir, username, "750"); - changeGroupAndSetPermissions(logDir, username, "770"); + + try { + changeGroupAndSetPermissions(logDir, username, "770"); + } catch (IOException ex) { + // The previous log files were created with a user that + // might no longer exist, so just ignore the exception! + } } } @@ -157,7 +161,7 @@ public void install(final String packageLocation, File receiptFile = new File(receiptsFolder, receiptFilename); metadata.store(receiptFile); - if (appsLauncher != null) { + if (metadata.isApp() && appsLauncher != null) { appsLauncher.refresh(); } @@ -186,9 +190,11 @@ public void uninstall(final Metadata packageMetadata, Logger.getLogger(NMFPackageManager.class.getName()).log( Level.INFO, "Removing the files..."); + removeFiles(packageMetadata); + if (packageMetadata.isApp()) { // This directory should be passed in the method signature: - File installationDir = new File(Deployment.getNMFAppsDir(), packageName); + File installationDir = new File(Deployment.getAppsDir(), packageName); removeAuxiliaryFiles(installationDir, packageName); if (OS.isUnix()) { @@ -199,8 +205,6 @@ public void uninstall(final Metadata packageMetadata, } } - removeFiles(packageMetadata); - File receiptsFolder = Deployment.getInstallationsTrackerDir(); File receiptFile = new File(receiptsFolder, packageName + RECEIPT_ENDING); @@ -265,7 +269,7 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx if (isApp) { // This directory should be passed in the method signature: - File installationDir = new File(Deployment.getNMFAppsDir(), packageName); + File installationDir = new File(Deployment.getAppsDir(), packageName); removeAuxiliaryFiles(installationDir, packageName); } @@ -280,22 +284,31 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Copying the new files to the locations..."); - MetadataApp appMetadata = newPackMetadata.castToApp(); - installDependencies(appMetadata, packageLocation, nmfDir); + if (isApp) { + MetadataApp appMetadata = newPackMetadata.castToApp(); + installDependencies(appMetadata, packageLocation, nmfDir); + } newPack.extractFiles(nmfDir); if (isApp) { - File installationDir = new File(Deployment.getNMFAppsDir(), packageName); - String username= generateUsername(packageName); + File installationDir = new File(Deployment.getAppsDir(), packageName); + String username = generateUsername(packageName); + MetadataApp appMetadata = newPackMetadata.castToApp(); HelperNMFPackage.generateStartScript(appMetadata, installationDir, nmfDir); createAuxiliaryFiles(installationDir, username); - File logDir = new File(Deployment.getLogsDir(), packageName); + File logDir = Deployment.getLogsDirForApp(packageName); logDir.mkdirs(); if (OS.isUnix()) { // Change Group owner of the appDir changeGroupAndSetPermissions(installationDir, username, "750"); - changeGroupAndSetPermissions(logDir, username, "770"); + + try { + changeGroupAndSetPermissions(logDir, username, "770"); + } catch (IOException ex) { + // The previous log files were created with a user that + // might no longer exist, so just ignore the exception! + } } } @@ -375,8 +388,8 @@ public boolean isPackageInstalled(final String packageLocation) { return true; } - private static void installDependencies(MetadataApp metadata, - String packageLocation, File installationDir) throws IOException { + private void installDependencies(MetadataApp metadata, + String packageLocation, File nmfDir) throws IOException { if (!metadata.hasDependencies()) { return; } @@ -390,8 +403,12 @@ private static void installDependencies(MetadataApp metadata, for (String file : dependencies) { file = file.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); String path = parent + File.separator + file; - NMFPackage pack = new NMFPackage(path); - pack.extractFiles(installationDir); + // NMFPackage pack = new NMFPackage(path); + // pack.extractFiles(installationDir); + + // TBD: We need to check if it has been installed + // already, otherwise no need to do it again + this.install(path, nmfDir); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index eb97af625..1449f66d0 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -77,7 +77,7 @@ private static String getBanner() { } public static String generateLinuxStartAppScript(String javaCommand, - String jarFilename, MetadataApp meta) throws IOException { + MetadataApp meta) throws IOException { StringBuilder str = new StringBuilder(); str.append("#!/bin/sh\n"); str.append(getBanner()); @@ -91,9 +91,9 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); str.append("# Jars from: App, NMF, and Shared dependencies:\n"); - str.append("JAR_APP=").append(jarFilename).append("\n"); + str.append("JAR_APP=").append(meta.getAppMainJar()).append("\n"); // The following code must be changed: - str.append("JARS_NMF=").append("`cd ../../libs > /dev/null; pwd`").append("\n"); + str.append("JARS_NMF=").append(Deployment.getJarsNMFDir()).append("\n"); String shared = ""; if (meta.hasDependencies()) { @@ -115,12 +115,12 @@ public static String generateLinuxStartAppScript(String javaCommand, str.append("NOW=$(date +\"%F\")\n"); String appName = meta.getPackageName(); str.append("FILENAME=").append(appName).append("_$NOW.log\n"); - String logPath = Deployment.getLogsDir().getAbsolutePath(); - str.append("LOG_PATH=").append(logPath).append("/").append(appName).append("\n"); + String logPath = Deployment.getLogsDirForApp(appName).getAbsolutePath(); + str.append("LOG_PATH=").append(logPath).append("\n"); str.append("mkdir -p $LOG_PATH\n\n"); // The command "exec" spawns the execution in a different process - // str.append("exec "); + // str.append("exec -a MyUniqueProcessName "); str.append("$JAVA_CMD $JAVA_OPTS \\\n"); str.append(" -classpath \"$JARS_ALL\" \\\n"); str.append(" \"$MAIN_CLASS\" \\\n"); @@ -262,12 +262,12 @@ public static void generateStartScript(MetadataApp appDetails, // The Java version for now will be forced to 8, however in // the future the package should recommend a version - String javaCMD = Deployment.findJREPath(nmfDir, 8, 8, 8); + String javaCMD = Deployment.findJREPath(8, 8, 8); OSValidator os = new OSValidator(); if (os.isUnix() || os.isMac()) { - String content = generateLinuxStartAppScript(javaCMD, jarName, appDetails); + String content = generateLinuxStartAppScript(javaCMD, appDetails); File startApp = new File(appDir, "start_" + name + ".sh"); HelperNMFPackage.writeFile(startApp, content); startApp.setExecutable(true, true); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java index e305ac030..dfebce830 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java @@ -262,6 +262,7 @@ private static String runCommand(String[] cmd) throws IOException { } String out = extractString(p.getInputStream()); + out += extractString(p.getErrorStream()); int exitValue = p.exitValue(); if (exitValue == 127) { // Command not found! From 1d1fc11a0907c956cc9c955aa760c6df80ff3500 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 17 Nov 2022 15:06:09 +0100 Subject: [PATCH 139/173] Adds the OneInstanceLock class to avoid multiple instances of the Supervisor --- .../main/java/esa/mo/nmf/OneInstanceLock.java | 82 +++++++++++++++++++ .../NanoSatMOSupervisor.java | 2 + 2 files changed, 84 insertions(+) create mode 100644 core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/OneInstanceLock.java diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/OneInstanceLock.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/OneInstanceLock.java new file mode 100644 index 000000000..129a79ac7 --- /dev/null +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/OneInstanceLock.java @@ -0,0 +1,82 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under the European Space Agency Public License, Version 2.0 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; + +/** + * Locks the application to one single instance. + * + * @author Cesar Coelho + */ +public class OneInstanceLock { + + private static File f; + private static FileChannel channel; + private static FileLock lock; + + public OneInstanceLock() { + try { + File internalDir = AppStorage.getAppNMFInternalDir(); + f = new File(internalDir, "application.lck"); + + // Try to get the lock + channel = new RandomAccessFile(f, "rw").getChannel(); + lock = channel.tryLock(); + if (lock == null) { + // File is locked by other application + channel.close(); + throw new RuntimeException("Two instances cannot run at a time."); + } + // Add shutdown hook to release lock when application shutdown + ShutdownHook shutdownHook = new ShutdownHook(); + Runtime.getRuntime().addShutdownHook(shutdownHook); + } catch (IOException e) { + throw new RuntimeException("Could not start process.", e); + } + } + + public static void unlockFile() { + // release and delete file lock + try { + if (lock != null) { + lock.release(); + channel.close(); + f.delete(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + static class ShutdownHook extends Thread { + + @Override + public void run() { + unlockFile(); + } + } + +} diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index 09daf6a1f..d41c55e35 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -34,6 +34,7 @@ import esa.mo.nmf.MCRegistration; import esa.mo.nmf.MissionPlanningNMFAdapter; import esa.mo.nmf.NMFException; +import esa.mo.nmf.OneInstanceLock; import esa.mo.nmf.nmfpackage.Deployment; import esa.mo.platform.impl.util.PlatformServicesConsumer; import esa.mo.reconfigurable.provider.PersistProviderConfiguration; @@ -84,6 +85,7 @@ public void init(MonitorAndControlNMFAdapter mcAdapter, PlatformServicesConsumer platformServices, PMBackend packageManagementBackend) { super.startTime = System.currentTimeMillis(); + OneInstanceLock lock = new OneInstanceLock(); HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties ConnectionProvider.resetURILinks(); From 55d1e08160ed226a3e3a1d79a46f058131aa2bee Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 17 Nov 2022 15:08:39 +0100 Subject: [PATCH 140/173] Updates the installation code to handle better the adduser linux command --- .../mo/nmf/nmfpackage/NMFPackageManager.java | 8 ++++++- .../nmfpackage/utils/LinuxUsersGroups.java | 24 ++++++++++--------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index b39304ff2..c895222f9 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -200,7 +200,13 @@ public void uninstall(final Metadata packageMetadata, if (OS.isUnix()) { if (!keepUserData) { String username = generateUsername(packageName); - LinuxUsersGroups.deluser(username, true); + try { + LinuxUsersGroups.deluser(username, true); + } catch (IOException ex) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.WARNING, "The User could not be deleted: " + + username, ex); + } } } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java index dfebce830..cb4dc24b0 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java @@ -57,6 +57,7 @@ public class LinuxUsersGroups { * with no intervening whitespace. * @throws IOException if the user could not be created. */ + @Deprecated public static void useradd(String username, String password, boolean withGroup, String extraGroups) throws IOException { // Second, we need to check if we have permissions to run the commands @@ -105,31 +106,32 @@ public static void addgroup(String groupName, boolean isSystemGroup) throws IOEx public static void adduser(String username, String password, boolean withGroup) throws IOException { // First, we need to check if the "useradd" is from BusyBox or not - String[] cmd1 = {"sudo", "adduser", "--help"}; - String out1 = runCommand(cmd1); - // Different Linux Systems have different syntaxes for the same command // So we need to check if we are using the adduser from "BusyBox" or not + String[] cmd1 = {"sudo", "adduser", "--help"}; + String out1 = runCommand(cmd1); boolean isBusyBox = out1.contains("BusyBox"); - // Second, we need to check if we have permissions to run the commands + // Second, we execute the adduser command String[] cmd2; if (isBusyBox) { if (withGroup) { LinuxUsersGroups.addgroup(username, true); - } - cmd2 = new String[]{"sudo", "adduser", "-s", DEFAULT_SHELL, - withGroup ? " -G " : "", withGroup ? username : "", - "-S", username}; + cmd2 = new String[]{"sudo", "adduser", "-s", DEFAULT_SHELL, + "-G", username, "-S", username}; + } else { + cmd2 = new String[]{"sudo", "adduser", "-s", DEFAULT_SHELL, + "-S", username}; + } } else { + // It is NOT BusyBox: cmd2 = new String[]{"sudo", "adduser", "--system", "--shell", DEFAULT_SHELL, withGroup ? "--group" : "", username}; } - //String cmd = "useradd $user_nmf_admin -m -s /bin/bash --user-group"; - //String cmd = "useradd $user_nmf_admin --create-home --shell /bin/bash --user-group"; + String out2 = runCommand(cmd2); checkIfPermissionDenied(cmd2, out2); @@ -274,7 +276,7 @@ private static String runCommand(String[] cmd) throws IOException { String error = extractString(p.getErrorStream()); throw new IOException("There was an error with code " + exitValue + ". For command:\n >> " + String.join(" ", cmd) + "\n" - + out + "\nError:\n" + error); + + out + "\nError:\n" + error + "\n----"); } return out; From 157853916fa3136181b8ef17616e91a4d9ac0d25 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 17 Nov 2022 21:27:05 +0100 Subject: [PATCH 141/173] Better handling of Linux users creation during the installation of the Apps --- .../mo/nmf/nmfpackage/NMFPackageManager.java | 55 ++++++++++++------- .../nmfpackage/utils/LinuxUsersGroups.java | 2 + 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index c895222f9..475da6d4b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -85,7 +85,7 @@ public void install(final String packageLocation, final File nmfDir) throws FileNotFoundException, IOException { System.out.printf(SEPARATOR); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Reading the package file to be installed..."); + "Openning an verifying the package file to be installed..."); // Get the File to be installed NMFPackage nmfPackage = new NMFPackage(packageLocation); @@ -97,9 +97,6 @@ public void install(final String packageLocation, } // Verify integrity of the file: Are all the declared files matching their CRCs? - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Verifying the integrity of the files to be installed..."); - // Do the files actually match the descriptor? nmfPackage.verifyPackageIntegrity(); @@ -129,28 +126,44 @@ public void install(final String packageLocation, // Create the User for this App boolean withGroup = true; LinuxUsersGroups.adduser(username, password, withGroup); - LinuxUsersGroups.addUserToGroup(username, GROUP_NMF_APPS); + + try { // Handle it seperately! + LinuxUsersGroups.addUserToGroup(username, GROUP_NMF_APPS); + } catch (IOException ex) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "The User " + username + + " could not be added to the Group: " + + GROUP_NMF_APPS, ex); + } // Set the right Group and Permissions to the Home Directory // The owner remains with the app, the group is nmf-admin - String appHomeDir = LinuxUsersGroups.findHomeDir(username); - LinuxUsersGroups.chgrp(true, USER_NMF_ADMIN, appHomeDir); - LinuxUsersGroups.chmod(true, true, "770", appHomeDir); + try { + String appHomeDir = LinuxUsersGroups.findHomeDir(username); + LinuxUsersGroups.chgrp(true, USER_NMF_ADMIN, appHomeDir); + LinuxUsersGroups.chmod(true, true, "770", appHomeDir); + } catch (IOException ex) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "The permissions of the User Home " + + "directory could not be set for username: " + + username, ex); + } + + // There is a group with the same name as the username: + String toGroup = username; + // Change Group owner of the appDir... + // Usually something like: /nanosat-mo-framework/apps/my-app + changeGroupAndSetPermissions(appDir, toGroup, "750"); + + try { + changeGroupAndSetPermissions(logDir, toGroup, "770"); + } catch (IOException ex) { + // The previous log files were created with a user that + // might no longer exist, so just ignore the exception! + } } catch (IOException ex) { Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "The User could not be created: " + username, ex); - username = null; - } - } - - if (OS.isUnix()) { // Change Group owner of the appDir - changeGroupAndSetPermissions(appDir, username, "750"); - - try { - changeGroupAndSetPermissions(logDir, username, "770"); - } catch (IOException ex) { - // The previous log files were created with a user that - // might no longer exist, so just ignore the exception! } } } @@ -174,7 +187,7 @@ public void install(final String packageLocation, /** * Uninstalls an NMF Package using the respective package descriptor. * - * @param descriptor The descriptor + * @param packageMetadata The metadata * @param keepUserData A flag that sets if the user data is kept * @throws IOException if there was a problem during the uninstallation */ diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java index cb4dc24b0..fdac3df43 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java @@ -144,6 +144,8 @@ public static void adduser(String username, String password, } public static void addUserToGroup(String username, String extraGroup) throws IOException { + // Note: usermod does not exist in some trimmed Linux versions + // Therefore we will be using the adduser equivalent functionality String[] cmd = {"sudo", "adduser", username, extraGroup}; String out = runCommand(cmd); checkIfPermissionDenied(cmd, out); From a7e67528906c9c2125ca004ab932a4c69eebcd04 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 18 Nov 2022 14:13:19 +0100 Subject: [PATCH 142/173] [nmf-package] Skips over the dependencies that are already installed during installation --- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 42 +++++++++++++++++- .../esa/mo/nmf/nmfpackage/NMFPackageFile.java | 20 ++++++++- .../mo/nmf/nmfpackage/NMFPackageManager.java | 43 ++++++++++++------- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 2e79a22aa..5bb394a24 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -40,10 +40,23 @@ public class NMFPackage { private final ZipFile zipFile; private Metadata metadata; + /** + * Constructor. + * + * @param filepath The path to the NMF Package file. + * @throws IOException If there is a problem with the file. + */ public NMFPackage(String filepath) throws IOException { this.zipFile = new ZipFile(filepath); } + /** + * Returns the metadata of the NMF Package. + * + * @return The metadata of the NMF Package. + * @throws IOException If the metadata from the NMF Package could not be + * parsed. + */ public synchronized Metadata getMetadata() throws IOException { if (metadata != null) { return metadata; @@ -53,6 +66,12 @@ public synchronized Metadata getMetadata() throws IOException { return metadata; } + /** + * Returns the CRC of the NMF Package metadata. + * + * @return The CRC of the NMF Package metadata. + * @throws IOException If the CRC could not be calculated. + */ public long calculateMetadataCRC() throws IOException { ZipEntry entry = zipFile.getEntry(Metadata.FILENAME); @@ -68,6 +87,12 @@ public long calculateMetadataCRC() throws IOException { return crc; } + /** + * Returns the zip entry for the selected path. + * + * @param path The path to the zip entry. + * @return The ZipEntry for the selected path. + */ public ZipEntry getZipFileEntry(String path) { ZipEntry entry = zipFile.getEntry(path); @@ -78,6 +103,12 @@ public ZipEntry getZipFileEntry(String path) { return entry; } + /** + * Verifies the package integrity. Checks if the CRCs of the files match. + * This prevents package tainting. + * + * @throws IOException + */ public void verifyPackageIntegrity() throws IOException { ArrayList files = this.getMetadata().getFiles(); @@ -98,13 +129,20 @@ public void verifyPackageIntegrity() throws IOException { + "\nAvailable entries:\n" + allEntries.toString()); } + // Are all the declared files matching their CRCs? if (filepack.getCRC() != entry.getCrc()) { throw new IOException("The CRC does not match!"); } } } - public void extractFiles(File to) throws IOException { + /** + * Extracts the files in this package to the selected folder. + * + * @param toFolder The folder where the files will be extracted to. + * @throws IOException If the files could not be extracted. + */ + public void extractFiles(File toFolder) throws IOException { File newFile; byte[] buffer = new byte[1024]; @@ -116,7 +154,7 @@ public void extractFiles(File to) throws IOException { ZipEntry entry = this.getZipFileEntry(file.getPath()); String path = HelperNMFPackage.generateFilePathForSystem(entry.getName()); - newFile = new File(to.getCanonicalPath() + File.separator + path); + newFile = new File(toFolder.getCanonicalPath() + File.separator + path); File parent = newFile.getParentFile(); if (!parent.exists()) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java index f5c3f8a11..5e698a063 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageFile.java @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency + * Copyright (C) 2022 European Space Agency * European Space Operations Centre * Darmstadt * Germany @@ -21,6 +21,7 @@ package esa.mo.nmf.nmfpackage; /** + * Holds an entry to a file in the NMF Package. * * @author Cesar Coelho */ @@ -29,17 +30,32 @@ public class NMFPackageFile { private final String path; private final long crc; + /** + * Constructor for the NMFPackageFile object. + * + * @param path The path to the file in the package. + * @param crc The CRC to the file in the package. + */ public NMFPackageFile(final String path, final long crc) { this.path = path; this.crc = crc; } + /** + * Returns the path to the file in the package. + * + * @return The path to the file in the package. + */ public String getPath() { return path; } + /** + * Returns the CRC of the file in the package. + * + * @return The CRC of the file in the package. + */ public long getCRC() { return crc; } - } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 475da6d4b..5c4780b45 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -85,7 +85,7 @@ public void install(final String packageLocation, final File nmfDir) throws FileNotFoundException, IOException { System.out.printf(SEPARATOR); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Openning an verifying the package file to be installed..."); + "Reading the package on: " + packageLocation); // Get the File to be installed NMFPackage nmfPackage = new NMFPackage(packageLocation); @@ -96,8 +96,6 @@ public void install(final String packageLocation, + "Version: " + metadata.getMetadataVersion()); } - // Verify integrity of the file: Are all the declared files matching their CRCs? - // Do the files actually match the descriptor? nmfPackage.verifyPackageIntegrity(); if (metadata.isApp()) { @@ -148,7 +146,7 @@ public void install(final String packageLocation, + "directory could not be set for username: " + username, ex); } - + // There is a group with the same name as the username: String toGroup = username; // Change Group owner of the appDir... @@ -396,13 +394,13 @@ public boolean isPackageInstalled(final String packageLocation) { // We need to check if the metadatas are the same! if (!metadata.sameAs(installedMetadata)) { - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.SEVERE, + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, "The NMF Package is not the same as the installed one!"); return false; } Logger.getLogger(NMFPackageManager.class.getName()).log(Level.FINE, - "The package " + metadata.getPackageName() + " installation folder was found!"); + "The package " + packageName + " installation folder was found!"); return true; } @@ -416,18 +414,32 @@ private void installDependencies(MetadataApp metadata, ArrayList dependencies = metadata.getAppDependencies(); String parent = (new File(packageLocation)).getParent(); - Logger.getLogger(NMFPackageManager.class.getName()).log( - Level.INFO, "Dependencies are: " + dependencies.toString()); + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "The dependencies are: " + dependencies.toString()); + + ArrayList toBeInstalled = new ArrayList<>(); - for (String file : dependencies) { - file = file.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); + for (String dependency : dependencies) { + String file = dependency.replace(".jar", "." + Const.NMF_PACKAGE_SUFFIX); String path = parent + File.separator + file; - // NMFPackage pack = new NMFPackage(path); - // pack.extractFiles(installationDir); - // TBD: We need to check if it has been installed - // already, otherwise no need to do it again + if (isPackageInstalled(path)) { + Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, + "The dependency is already installed: " + dependency); + } else { + if ((new File(path)).exists()) { + toBeInstalled.add(path); + } else { + throw new IOException("The package was not found for " + + "dependency: " + dependency); + } + } + } + + for (String path : toBeInstalled) { this.install(path, nmfDir); + // NMFPackage pack = new NMFPackage(path); + // pack.extractFiles(nmfDir); } } @@ -522,7 +534,8 @@ private void stopAppIfRunning(String name) { try { Logger.getLogger(NMFPackageManager.class.getName()).log( - Level.INFO, "Checking if " + name + " App is running..."); + Level.INFO, "Checking if " + name + " App is running... " + + " The App will be stopped if running!"); IdentifierList myApp = new IdentifierList(); myApp.add(new Identifier(name)); From 21ec9c756d6612f9dcaaf7bf0d20637c4415419c Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 18 Nov 2022 19:46:19 +0100 Subject: [PATCH 143/173] Removes polluting code from the NanoSat MO Connector --- .../src/main/java/esa/mo/nmf/NMFProvider.java | 8 ---- .../NanoSatMOMonolithic.java | 5 -- .../NanoSatMOConnectorImpl.java | 47 ++++++++++--------- .../NanoSatMOSupervisor.java | 5 -- 4 files changed, 26 insertions(+), 39 deletions(-) diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java index 9709f8914..9a3c554c8 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java @@ -88,14 +88,6 @@ public abstract class NMFProvider implements ReconfigurableProvider, NMFInterfac */ public abstract void init(final MonitorAndControlNMFAdapter mcAdapter); - /** - * Initializes the NMF provider using a mission planning adapter that - * connects to the Mission Planning services. - * - * @param mpAdapter The Mission Planning Adapter. - */ - public abstract void init(final MissionPlanningNMFAdapter mpAdapter); - @Override public COMServicesProvider getCOMServices() throws NMFException { if (this.comServices == null) { diff --git a/core/nmf-composites/generic-nanosat-monolithic/src/main/java/esa/mo/nmf/nanosatmomonolithic/NanoSatMOMonolithic.java b/core/nmf-composites/generic-nanosat-monolithic/src/main/java/esa/mo/nmf/nanosatmomonolithic/NanoSatMOMonolithic.java index 48572fab8..069cec6f1 100644 --- a/core/nmf-composites/generic-nanosat-monolithic/src/main/java/esa/mo/nmf/nanosatmomonolithic/NanoSatMOMonolithic.java +++ b/core/nmf-composites/generic-nanosat-monolithic/src/main/java/esa/mo/nmf/nanosatmomonolithic/NanoSatMOMonolithic.java @@ -124,11 +124,6 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter, final PlatformServ Logger.getLogger(NanoSatMOMonolithic.class.getName()).log(Level.INFO, "URI: {0}\n", uri); } - @Override - public void init(MissionPlanningNMFAdapter mpAdapter) { - // Not implemented. MP services are accessible only from connector. - } - /** * It closes the App gracefully. * diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index 2834c806c..f4dd0ab06 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -75,8 +75,6 @@ */ public class NanoSatMOConnectorImpl extends NMFProvider { - private static final String SEPARATOR = "------------"; - private static final Logger LOGGER = Logger.getLogger(NanoSatMOConnectorImpl.class.getName()); private final boolean fastMode = false; @@ -99,12 +97,12 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { super.startTime = System.currentTimeMillis(); LOGGER.log(Level.INFO, this.generateStartBanner()); - HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties - ConnectionProvider.resetURILinks(); // Resets the providerURIs.properties file + // Loads: provider.properties; settings.properties; transport.properties + HelperMisc.loadPropertiesFile(); + ConnectionProvider.resetURILinks(); // Resets the URIs file // Create provider name to be registerd on the Directory service... - String appName = this.determineAppName(); - this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; + this.providerName = this.determineAppName(); // Check if the new Home dir mode property is enabled: int mode = Integer.parseInt(System.getProperty(HelperMisc.PROP_WORK_DIR_STORAGE_MODE, "0")); @@ -216,10 +214,10 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { } // Select the best transport for IPC and convert to a ConnectionConsumer object - final ProviderSummary filteredConnections = HelperCommon.selectBestIPCTransport( - supervisorConnections.get(0)); - final ConnectionConsumer supervisorCCPlat = HelperCommon.providerSummaryToConnectionConsumer( - filteredConnections); + final ProviderSummary filteredConnections + = HelperCommon.selectBestIPCTransport(supervisorConnections.get(0)); + final ConnectionConsumer supervisorCCPlat + = HelperCommon.providerSummaryToConnectionConsumer(filteredConnections); // Connect to them... platformServices = new PlatformServicesConsumer(); @@ -234,8 +232,10 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { "The NanoSat MO Connector was expecting a single NMF Platform services provider!" + " Instead it found {0}.", supervisorConnections.size()); } - } catch (MALException | MalformedURLException ex) { - LOGGER.log(Level.SEVERE, null, ex); + } catch (MALException ex) { + LOGGER.log(Level.SEVERE, "MALException in NanoSat MO Connector!", ex); + } catch (MalformedURLException ex) { + LOGGER.log(Level.SEVERE, "MalformedURLException in NanoSat MO Connector!", ex); } catch (MALInteractionException ex) { LOGGER.log(Level.SEVERE, "Could not connect to the Central Directory service! Maybe it is down..."); } @@ -302,8 +302,8 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { if (mcAdapter != null) { LOGGER.log(Level.INFO, "Performing initial M&C registrations..."); - MCRegistration registration = new MCRegistration(comServices, - mcServices.getParameterService(), mcServices.getAggregationService(), + MCRegistration registration = new MCRegistration(comServices, + mcServices.getParameterService(), mcServices.getAggregationService(), mcServices.getAlertService(), mcServices.getActionService()); mcAdapter.initialRegistrations(registration); mcAdapter.restoreParameterValuesFromArchive(); @@ -317,15 +317,20 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { LOGGER.log(Level.INFO, "URI: {0}\n", uri); } - @Override + /** + * Initializes the NanoSat MO Connector. The MissionPlanningNMFAdapter + * adapter class can be extended for planning and scheduling with the + * CCSDS Planning and Scheduling services. + * + * @param mpAdapter The adapter to connect the mission planning adapter. + */ public void init(final MissionPlanningNMFAdapter mpAdapter) { super.startTime = System.currentTimeMillis(); HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties ConnectionProvider.resetURILinks(); // Create provider name to be registerd on the Directory service... - String appName = this.determineAppName(); - this.providerName = AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; + this.providerName = this.determineAppName(); try { comServices.init(); @@ -668,8 +673,9 @@ public final void closeGracefully(final ObjectId source) { this.getCOMServices().closeAll(); // Exit the Java application - LOGGER.log(Level.INFO, "Success! The currently running Java Virtual Machine will now terminate. " + - "(App closed in: {0} ms)\n", System.currentTimeMillis() - time); + LOGGER.log(Level.INFO, "Success! The currently running Java Virtual" + + " Machine will now terminate. (App closed in: {0} ms)\n", + System.currentTimeMillis() - time); } catch (NMFException ex) { LOGGER.log(Level.SEVERE, null, ex); } @@ -719,7 +725,6 @@ private String determineAppName() { LOGGER.log(Level.SEVERE, "The NMF App name could not be established."); } - return appName; + return AppsLauncherProviderServiceImpl.PROVIDER_PREFIX_NAME + appName; } - } diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index d41c55e35..5e131c5d3 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -203,11 +203,6 @@ public AppsLauncherProviderServiceImpl getAppsLauncherService() { return appsLauncherService; } - @Override - public void init(MissionPlanningNMFAdapter mpAdapter) { - // Not implemented. MP services are accessible only from connector. - } - @Override public void setCloseAppListener(final CloseAppListener closeAppAdapter) { this.closeAppAdapter = closeAppAdapter; From 48875146eb4a7b838d24c3fb4d5535abd46ba90e Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 18 Nov 2022 19:49:38 +0100 Subject: [PATCH 144/173] Better error handling --- .../PersistProviderConfiguration.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java index 28f12f1e1..96083e76b 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java @@ -92,11 +92,22 @@ public PersistProviderConfiguration(final ReconfigurableProvider provider, final // Does the providerConfiguration object exists? if (comObjectProvider != null) { final ArchivePersistenceObject comObjectConfs = HelperArchive.getArchiveCOMObject(archiveService, - ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, confId.getKey().getDomain(), comObjectProvider - .getArchiveDetails().getDetails().getRelated()); - objIds = ((ConfigurationObjectDetails) comObjectConfs.getObject()).getConfigObjects().get(0) - .getObjInstIds(); - return; + ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, + confId.getKey() + .getDomain(), + comObjectProvider.getArchiveDetails() + .getDetails() + .getRelated()); + + if(comObjectConfs != null) { + ConfigurationObjectDetails conf = (ConfigurationObjectDetails) comObjectConfs.getObject(); + ConfigurationObjectSetList sets = conf.getConfigObjects(); + objIds = sets.get(0).getObjInstIds(); + return; + } else { + Logger.getLogger(PersistProviderConfiguration.class.getName()).log( + Level.WARNING, "The Configuration objects could not be retrieved!"); + } } // It doesn't exist... create all the necessary objects... From fe5efda894f70b5f0ce318eef3e4dd7634b3bb8d Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 18 Nov 2022 19:57:15 +0100 Subject: [PATCH 145/173] Restored sanity to the file --- .../PersistProviderConfiguration.java | 116 +++++++++++------- 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java index 96083e76b..48c2a1b15 100644 --- a/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java +++ b/core/mo-services-impl/ccsds-com-impl/src/main/java/esa/mo/reconfigurable/provider/PersistProviderConfiguration.java @@ -51,8 +51,9 @@ import org.ccsds.moims.mo.mal.structures.URI; /** - * This class is responsible for storing the configuration of a provider in the COM Archive every time there is a change - * on the configuration of one of its reconfigurable services. + * This class is responsible for storing the configuration of a provider in the + * COM Archive every time there is a change on the configuration of one of its + * reconfigurable services. */ public class PersistProviderConfiguration { @@ -67,46 +68,49 @@ public class PersistProviderConfiguration { private LongList objIds; public PersistProviderConfiguration(final ReconfigurableProvider provider, final ObjectId confId, - final ArchiveInheritanceSkeleton archiveService) { + final ArchiveInheritanceSkeleton archiveService) { - if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) != null && - MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) - .getServiceByName(ConfigurationHelper.CONFIGURATION_SERVICE_NAME) == null) { + if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) != null + && MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) + .getServiceByName(ConfigurationHelper.CONFIGURATION_SERVICE_NAME) == null) { try { ConfigurationHelper.init(MALContextFactory.getElementFactoryRegistry()); } catch (MALException ex) { - Logger.getLogger(PersistProviderConfiguration.class.getName()).log(Level.SEVERE, - "Unexpectedly ConfigurationHelper already initialized!?", ex); + Logger.getLogger(PersistProviderConfiguration.class.getName()) + .log(Level.SEVERE, "Unexpectedly ConfigurationHelper already initialized!?", ex); } } this.archiveService = archiveService; this.confId = confId; this.reconfigurableServices = provider.getServices(); - this.executor = Executors.newSingleThreadExecutor(new ConfigurationThreadFactory()); // Guarantees sequential order + this.executor + = Executors.newSingleThreadExecutor(new ConfigurationThreadFactory()); // Guarantees sequential order - final ArchivePersistenceObject comObjectProvider = HelperArchive.getArchiveCOMObject(archiveService, - ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, confId.getKey().getDomain(), confId.getKey() - .getInstId()); + final ArchivePersistenceObject comObjectProvider + = HelperArchive.getArchiveCOMObject(archiveService, + ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, + confId.getKey().getDomain(), confId.getKey().getInstId()); // Does the providerConfiguration object exists? if (comObjectProvider != null) { - final ArchivePersistenceObject comObjectConfs = HelperArchive.getArchiveCOMObject(archiveService, - ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, - confId.getKey() - .getDomain(), - comObjectProvider.getArchiveDetails() - .getDetails() - .getRelated()); - - if(comObjectConfs != null) { + final ArchivePersistenceObject comObjectConfs = HelperArchive.getArchiveCOMObject( + archiveService, + ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, + confId.getKey() + .getDomain(), + comObjectProvider.getArchiveDetails() + .getDetails() + .getRelated()); + + if (comObjectConfs != null) { ConfigurationObjectDetails conf = (ConfigurationObjectDetails) comObjectConfs.getObject(); ConfigurationObjectSetList sets = conf.getConfigObjects(); objIds = sets.get(0).getObjInstIds(); return; } else { Logger.getLogger(PersistProviderConfiguration.class.getName()).log( - Level.WARNING, "The Configuration objects could not be retrieved!"); + Level.WARNING, "The Configuration objects could not be retrieved!"); } } @@ -117,8 +121,10 @@ public PersistProviderConfiguration(final ReconfigurableProvider provider, final for (int i = 0; i < reconfigurableServices.size(); i++) { Long confObjId = (long) (i + 1); - final PersistLatestServiceConfigurationAdapter persistLatestConfig = new PersistLatestServiceConfigurationAdapter( - reconfigurableServices.get(i), confObjId, this.archiveService, this.executor); + final PersistLatestServiceConfigurationAdapter persistLatestConfig + = new PersistLatestServiceConfigurationAdapter( + reconfigurableServices.get(i), confObjId, + this.archiveService, this.executor); persistLatestConfig.storeDefaultServiceConfiguration(confObjId, reconfigurableServices.get(i)); objIds.add(confObjId); // Will work for now @@ -137,20 +143,27 @@ public PersistProviderConfiguration(final ReconfigurableProvider provider, final providerObjects.setConfigObjects(setList); archObj.add(providerObjects); - LongList objIds3 = this.archiveService.store(true, ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, - ConfigurationProviderSingleton.getDomain(), HelperArchive.generateArchiveDetailsList(null, null, - ConfigurationProviderSingleton.getNetwork(), new URI("")), archObj, null); + LongList objIds3 = this.archiveService.store(true, + ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + HelperArchive.generateArchiveDetailsList(null, null, + ConfigurationProviderSingleton.getNetwork(), + new URI("")), archObj, + null); // Store the provider configuration // Related points to the Provider's Configuration Object - ArchiveDetailsList details = HelperArchive.generateArchiveDetailsList(objIds3.get(0), null, - ConfigurationProviderSingleton.getNetwork(), new URI("")); + ArchiveDetailsList details = HelperArchive.generateArchiveDetailsList( + objIds3.get(0), + null, + ConfigurationProviderSingleton.getNetwork(), + new URI("")); details.get(0).setInstId(confId.getKey().getInstId()); IdentifierList providerNameList = new IdentifierList(1); providerNameList.add(provider.getProviderName()); this.archiveService.store(false, ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, - ConfigurationProviderSingleton.getDomain(), details, providerNameList, null); + ConfigurationProviderSingleton.getDomain(), details, providerNameList, null); } catch (MALException | MALInteractionException ex) { Logger.getLogger(PersistProviderConfiguration.class.getName()).log(Level.SEVERE, null, ex); } @@ -165,26 +178,32 @@ public void loadPreviousConfigurations() throws IOException { this.reloadServiceConfigurations(reconfigurableServices, objIds); Logger.getLogger(PersistProviderConfiguration.class.getName()).log(Level.FINER, - "The size of the objIds list is: " + objIds.size() + " and the size of the reconfigurableServices is: " + - reconfigurableServices.size()); + "The size of the objIds list is: " + + objIds.size() + + " and the size of the reconfigurableServices is: " + + reconfigurableServices.size()); for (int i = 0; i < objIds.size(); i++) { final ReconfigurableService providerService = reconfigurableServices.get(i); - final PersistLatestServiceConfigurationAdapter persistLatestConfig = new PersistLatestServiceConfigurationAdapter( - providerService, objIds.get(i), this.archiveService, this.executor); + final PersistLatestServiceConfigurationAdapter persistLatestConfig + = new PersistLatestServiceConfigurationAdapter(providerService, + objIds.get(i), this.archiveService, this.executor); providerService.setOnConfigurationChangeListener(persistLatestConfig); } } - private void reloadServiceConfigurations(final ArrayList services, final LongList objIds) - throws IOException { + private void reloadServiceConfigurations(final ArrayList services, + final LongList objIds) throws IOException { // Retrieve the COM object of the service - List comObjects = HelperArchive.getArchiveCOMObjectList(archiveService, - ConfigurationHelper.SERVICECONFIGURATION_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), objIds); + List comObjects = HelperArchive.getArchiveCOMObjectList( + archiveService, + ConfigurationHelper.SERVICECONFIGURATION_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + objIds); if (comObjects == null) { // Could not be found, return Logger.getLogger(PersistProviderConfiguration.class.getName()).log(Level.INFO, - "The service configuration object of one of the services does not exist in the Archive."); + "The service configuration object of one of the services does not exist in the Archive."); return; } @@ -196,22 +215,25 @@ private void reloadServiceConfigurations(final ArrayList } // Retrieve it from the Archive - List confObjs = HelperArchive.getArchiveCOMObjectList(archiveService, - ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), relateds); + List confObjs = HelperArchive.getArchiveCOMObjectList( + archiveService, + ConfigurationHelper.CONFIGURATIONOBJECTS_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + relateds); if (confObjs == null) { Logger.getLogger(PersistProviderConfiguration.class.getName()).log(Level.SEVERE, - "The configuration object of one of the services does not exist in the Archive."); + "The configuration object of one of the services does not exist in the Archive."); return; } for (int i = 0; i < confObjs.size(); i++) { - ConfigurationObjectDetails configurationObjectDetails = (ConfigurationObjectDetails) confObjs.get(i) - .getObject(); + ConfigurationObjectDetails configurationObjectDetails + = (ConfigurationObjectDetails) confObjs.get(i).getObject(); if (configurationObjectDetails == null) { // Could not be found, throw error! - // If the object above exists, this one should also! - throw new IOException("An error happened while reloading the service configuration: " + services.get(i) - .getCOMService().getName()); + // If the object above exists, this one should also! + throw new IOException("An error happened while reloading the service " + + "configuration: " + services.get(i).getCOMService().getName()); } // Reload the previous Configuration From 2a582fa800c1aa617565cee1ae9ea9afdac3b1fa Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 18 Nov 2022 22:10:33 +0100 Subject: [PATCH 146/173] Code cleanup --- .../mo/nmf/ctt/utils/ProviderTabPanel.java | 130 ++++++++++-------- 1 file changed, 70 insertions(+), 60 deletions(-) diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java index 07bf180b9..97c4ca58a 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ProviderTabPanel.java @@ -20,9 +20,9 @@ */ package esa.mo.nmf.ctt.utils; +import esa.mo.com.impl.util.COMServicesConsumer; import esa.mo.helpertools.clock.PlatformClockCallback; import esa.mo.helpertools.clock.SystemClock; -import esa.mo.helpertools.connections.ConnectionConsumer; import esa.mo.helpertools.helpers.HelperTime; import esa.mo.helpertools.misc.TaskScheduler; import esa.mo.nmf.ctt.services.com.ArchiveConsumerManagerPanel; @@ -49,6 +49,7 @@ import esa.mo.nmf.ctt.services.sm.PackageManagementConsumerPanel; import esa.mo.nmf.groundmoadapter.GroundMOAdapterImpl; import esa.mo.sm.impl.consumer.HeartbeatConsumerServiceImpl; +import esa.mo.sm.impl.util.SMServicesConsumer; import java.awt.Color; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -60,6 +61,7 @@ import org.ccsds.moims.mo.mal.MALInteractionException; import org.ccsds.moims.mo.mal.structures.Blob; import org.ccsds.moims.mo.mal.structures.Time; +import org.ccsds.moims.mo.platform.clock.consumer.ClockStub; import org.ccsds.moims.mo.softwaremanagement.heartbeat.consumer.HeartbeatAdapter; /** @@ -100,8 +102,8 @@ protected void startTabs() { // Common if (services.getCommonServices() != null) { if (services.getCommonServices().getConfigurationService() != null) { - ConfigurationConsumerPanel panel = new ConfigurationConsumerPanel(services.getCommonServices() - .getConfigurationService(), providerSummary); + ConfigurationConsumerPanel panel = new ConfigurationConsumerPanel( + services.getCommonServices().getConfigurationService(), providerSummary); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Configuration service", null, panel, "Configuration Tab", count); } @@ -109,33 +111,32 @@ protected void startTabs() { // Software Management if (services.getSMServices() != null) { - if (services.getSMServices().getHeartbeatService() != null) { - HeartbeatConsumerServiceImpl heartbeat = services.getSMServices().getHeartbeatService(); + SMServicesConsumer sm = services.getSMServices(); + + if (sm.getHeartbeatService() != null) { + HeartbeatConsumerServiceImpl heartbeat = sm.getHeartbeatService(); ProviderStatusAdapter providerStatusAdapter = new ProviderStatusAdapter(heartbeat); heartbeat.startListening(providerStatusAdapter); } else { status.setText("Heartbeat service not available."); } - if (services.getSMServices().getAppsLauncherService() != null) { - AppsLauncherConsumerPanel panel = new AppsLauncherConsumerPanel(services.getSMServices() - .getAppsLauncherService()); + if (sm.getAppsLauncherService() != null) { + AppsLauncherConsumerPanel panel = new AppsLauncherConsumerPanel(sm.getAppsLauncherService()); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Apps Launcher service", null, panel, "Apps Launcher Tab", count); panel.init(); } - if (services.getSMServices().getCommandExecutorService() != null) { - CommandExecutorConsumerPanel panel = new CommandExecutorConsumerPanel(services.getSMServices() - .getCommandExecutorService()); + if (sm.getCommandExecutorService() != null) { + CommandExecutorConsumerPanel panel = new CommandExecutorConsumerPanel(sm.getCommandExecutorService()); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Command Executor service", null, panel, "Command Executor Tab", count); panel.init(); } - if (services.getSMServices().getPackageManagementService() != null) { - PackageManagementConsumerPanel panel = new PackageManagementConsumerPanel(services.getSMServices() - .getPackageManagementService()); + if (sm.getPackageManagementService() != null) { + PackageManagementConsumerPanel panel = new PackageManagementConsumerPanel(sm.getPackageManagementService()); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Package Management service", null, panel, "Package Management Tab", count); panel.init(); @@ -144,9 +145,9 @@ protected void startTabs() { // COM if (services.getCOMServices() != null) { - if (services.getCOMServices().getArchiveService() != null) { - ArchiveConsumerManagerPanel panel = new ArchiveConsumerManagerPanel(services.getCOMServices() - .getArchiveService()); + COMServicesConsumer com = services.getCOMServices(); + if (com.getArchiveService() != null) { + ArchiveConsumerManagerPanel panel = new ArchiveConsumerManagerPanel(com.getArchiveService()); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Archive Manager", null, panel, "Archive Tab", count); panel.setArchiveSyncConfigs(count + 1, serviceTabs, services); @@ -154,14 +155,13 @@ protected void startTabs() { /* if (services.getCOMServices().getArchiveSyncService() != null) { - ArchiveSyncConsumerManagerPanel panel = new ArchiveSyncConsumerManagerPanel(services.getCOMServices().getArchiveService(), services.getCOMServices().getArchiveSyncService()); + ArchiveSyncConsumerManagerPanel panel = new ArchiveSyncConsumerManagerPanel(com.getArchiveService(), com.getArchiveSyncService()); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("ArchiveSync service", null, panel, "ArchiveSync Tab", count); } */ - if (services.getCOMServices().getEventService() != null) { - EventConsumerPanel panel = new EventConsumerPanel(services.getCOMServices().getEventService(), - services.getCOMServices().getArchiveService()); + if (com.getEventService() != null) { + EventConsumerPanel panel = new EventConsumerPanel(com.getEventService(), com.getArchiveService()); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Event service", null, panel, "Event Tab", count); panel.init(); @@ -230,10 +230,11 @@ protected void startTabs() { } if (services.getMPServices().getPlanningRequestService() != null) { - PlanningRequestConsumerPanel consumerPanel = new PlanningRequestConsumerPanel(services - .getMPServices().getPlanningRequestService()); - PublishedRequestsPanel publishedPanel = new PublishedRequestsPanel(services.getCOMServices() - .getArchiveService(), services.getMPServices().getPlanningRequestService()); + PlanningRequestConsumerPanel consumerPanel = new PlanningRequestConsumerPanel(services.getMPServices().getPlanningRequestService()); + PublishedRequestsPanel publishedPanel = new PublishedRequestsPanel( + services.getCOMServices().getArchiveService(), + services.getMPServices().getPlanningRequestService() + ); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Planning Request service", null, consumerPanel, "PRS Tab", count); serviceTabs.insertTab("Published planning requests", null, publishedPanel, "Published Requests Tab", @@ -242,12 +243,15 @@ protected void startTabs() { } if (services.getMPServices().getPlanDistributionService() != null) { - PlanDistributionConsumerPanel consumerPanel = new PlanDistributionConsumerPanel(services - .getMPServices().getPlanDistributionService()); - PublishedPlansPanel publishedPlansPanel = new PublishedPlansPanel(services.getCOMServices() - .getArchiveService(), services.getMPServices().getPlanDistributionService()); - PublishedPlanStatusesPanel publishedPlanStatusesPanel = new PublishedPlanStatusesPanel(services - .getCOMServices().getArchiveService(), services.getMPServices().getPlanDistributionService()); + PlanDistributionConsumerPanel consumerPanel = new PlanDistributionConsumerPanel(services.getMPServices().getPlanDistributionService()); + PublishedPlansPanel publishedPlansPanel = new PublishedPlansPanel( + services.getCOMServices().getArchiveService(), + services.getMPServices().getPlanDistributionService() + ); + PublishedPlanStatusesPanel publishedPlanStatusesPanel = new PublishedPlanStatusesPanel( + services.getCOMServices().getArchiveService(), + services.getMPServices().getPlanDistributionService() + ); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Plan Distribution service", null, consumerPanel, "PDS Tab", count); serviceTabs.insertTab("Published plan versions", null, publishedPlansPanel, "Published Plans Tab", @@ -266,9 +270,10 @@ protected void startTabs() { } if (services.getMPServices().getPlanExecutionControlService() != null) { - PublishedActivityUpdatesPanel publishedPanel = new PublishedActivityUpdatesPanel(services - .getCOMServices().getArchiveService(), services.getMPServices() - .getPlanExecutionControlService()); + PublishedActivityUpdatesPanel publishedPanel = new PublishedActivityUpdatesPanel( + services.getCOMServices().getArchiveService(), + services.getMPServices().getPlanExecutionControlService() + ); int count = serviceTabs.getTabCount(); serviceTabs.insertTab("Published activity updates", null, publishedPanel, "Published activity updates", count); @@ -277,40 +282,45 @@ protected void startTabs() { // Platform if (services.getPlatformServices() != null) { - if (services.getPlatformServices().getClockService() != null) { - System.setProperty("esa.mo.nmf.app.systemTimeProvidedByPlatformClockService", "true"); - SystemClock.setPlatformClockCallback(new PlatformClockCallback() { - @Override - public Time getPlatformTime() { - try { - return services.getPlatformServices().getClockService().getTime(); - } catch (MALInteractionException | MALException | IOException e) { - LOGGER.log(Level.SEVERE, null, e); + try { + ClockStub clock = services.getPlatformServices().getClockService(); + + if (clock != null) { + System.setProperty("esa.mo.nmf.app.systemTimeProvidedByPlatformClockService", "true"); + SystemClock.setPlatformClockCallback(new PlatformClockCallback() { + @Override + public Time getPlatformTime() { + try { + return clock.getTime(); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, null, e); + } + return new Time(System.currentTimeMillis()); } - return new Time(System.currentTimeMillis()); - } - @Override - public int getPlatformTimeFactor() { - try { - return services.getPlatformServices().getClockService().getTimeFactor(); - } catch (MALInteractionException | MALException | IOException e) { - LOGGER.log(Level.SEVERE, null, e); + @Override + public int getPlatformTimeFactor() { + try { + return clock.getTimeFactor(); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, null, e); + } + return 1; } - return 1; - } - }); + }); - ClockConsumerPanel consumerPanel = new ClockConsumerPanel(services.getPlatformServices() - .getClockService()); - int count = serviceTabs.getTabCount(); - serviceTabs.insertTab("Clock service", null, consumerPanel, "Clock Tab", count); - consumerPanel.init(); + ClockConsumerPanel consumerPanel = new ClockConsumerPanel(clock); + int count = serviceTabs.getTabCount(); + serviceTabs.insertTab("Clock service", null, consumerPanel, "Clock Tab", count); + consumerPanel.init(); + } + } catch (IOException ex) { + LOGGER.log(Level.INFO, "The Clock Service is not available"); } } } catch (MALInteractionException ex) { LOGGER.log(Level.SEVERE, "Could not connect to the provider.", ex); - } catch (MALException | IOException ex) { + } catch (MALException ex) { LOGGER.log(Level.SEVERE, null, ex); } } From d992ad080169e4c1970c447d97f0d1a021a83ee3 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 18 Nov 2022 22:11:40 +0100 Subject: [PATCH 147/173] Adds a mechanism to configure the transport dispatcher executor threads. --- .../src/main/java/esa/mo/nmf/NMFProvider.java | 15 ++++++++++++++- .../NanoSatMOConnectorImpl.java | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java index 9a3c554c8..4761e35aa 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java @@ -207,6 +207,19 @@ public final void startMPServices(MissionPlanningNMFAdapter mpAdapter) throws MA } } + /** + * Sets the transport dispatcher executor threads configurations. + */ + public void configureTransportThreads() { + System.setProperty("org.ccsds.moims.mo.mal.transport.gen.inputprocessors", "5"); + + // Clean up idle threads after 2 seconds: (does not seem to work) + // System.setProperty("org.ccsds.moims.mo.mal.transport.gen.idleinputprocessors", "2"); + + // let's have a minimum of 2 threads: (does not seem to work) + // System.setProperty("org.ccsds.moims.mo.mal.transport.gen.mininputprocessors", "2"); + } + @Override public void setOnConfigurationChangeListener(ConfigurationChangeListener configurationAdapter) { this.providerConfigurationAdapter = configurationAdapter; @@ -309,7 +322,7 @@ public final void writeCentralDirectoryServiceURI(final String centralDirectoryU /** * Generates a starting Banner that can be used for NMF Providers. - * + * * @return The banner. */ protected String generateStartBanner() { diff --git a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java index f4dd0ab06..af3772091 100644 --- a/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java +++ b/core/nmf-composites/nanosat-mo-connector/src/main/java/esa/mo/nmf/nanosatmoconnector/NanoSatMOConnectorImpl.java @@ -100,6 +100,7 @@ public void init(final MonitorAndControlNMFAdapter mcAdapter) { // Loads: provider.properties; settings.properties; transport.properties HelperMisc.loadPropertiesFile(); ConnectionProvider.resetURILinks(); // Resets the URIs file + super.configureTransportThreads(); // Create provider name to be registerd on the Directory service... this.providerName = this.determineAppName(); From 08ef8fbdfb9c06f05d0a7fc162fa5eaf3bb4e6fd Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 20 Nov 2022 15:15:57 +0100 Subject: [PATCH 148/173] Code refactoring --- .../impl/util/PlatformServicesConsumer.java | 8 +- .../esa/mo/nmf/nmfpackage/Deployment.java | 5 + .../mo/nmf/nmfpackage/NMFPackageManager.java | 40 ++-- .../nmfpackage/utils/AuxFilesGenerator.java | 215 ++++++++++++++++++ .../nmfpackage/utils/HelperNMFPackage.java | 194 ---------------- 5 files changed, 250 insertions(+), 212 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java index 42b654ba3..13cc6c503 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesConsumer.java @@ -98,14 +98,14 @@ public void init(ConnectionConsumer connectionConsumer, // Initialize the Camera service details = connectionConsumer.getServicesDetails().get(CameraHelper.CAMERA_SERVICE_NAME); if (details != null) { - cameraService = new CameraConsumerServiceImpl(details, + cameraService = new CameraConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); } // Initialize the GPS service details = connectionConsumer.getServicesDetails().get(GPSHelper.GPS_SERVICE_NAME); if (details != null) { - gpsService = new GPSConsumerServiceImpl(details, + gpsService = new GPSConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); } @@ -129,7 +129,7 @@ public void init(ConnectionConsumer connectionConsumer, details = connectionConsumer.getServicesDetails().get( PowerControlHelper.POWERCONTROL_SERVICE_NAME); if (details != null) { - powerControlService = new PowerControlConsumerServiceImpl(details, + powerControlService = new PowerControlConsumerServiceImpl(details, comServices, authenticationID, localNamePrefix); } @@ -151,7 +151,7 @@ public ArtificialIntelligenceStub getAIService() throws IOException { return this.aiService.getArtificialIntelligenceStub(); } - + @Override public AutonomousADCSStub getAutonomousADCSService() throws IOException { if (this.autonomousADCSService == null) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index fb71b7dee..24e3ab59b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -20,6 +20,7 @@ */ package esa.mo.nmf.nmfpackage; +import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; import java.io.File; import java.io.FileInputStream; @@ -119,6 +120,10 @@ public static File getLogsDirForApp(String appName) { return new File(getLogsDir(), "app_" + appName); } + public static File getTransportFile() { + return new File(getEtcDir(), HelperMisc.TRANSPORT_PROPERTIES_FILE); + } + public static File getInstallationsTrackerDir() { // Default location of the folder File folder = new File(getEtcDir(), DIR_INSTALLATIONS_TRACKER); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 5c4780b45..5bc7985bd 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -27,6 +27,7 @@ import esa.mo.helpertools.misc.OSValidator; import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.metadata.MetadataApp; +import esa.mo.nmf.nmfpackage.utils.AuxFilesGenerator; import esa.mo.sm.impl.provider.AppsLauncherProviderServiceImpl; import java.io.File; import java.io.FileInputStream; @@ -114,7 +115,7 @@ public void install(final String packageLocation, String password = null; File appDir = new File(Deployment.getAppsDir(), packageName); - HelperNMFPackage.generateStartScript(metadata.castToApp(), appDir, nmfDir); + AuxFilesGenerator.generateStartScript(metadata.castToApp(), appDir, nmfDir); createAuxiliaryFiles(appDir, username); File logDir = Deployment.getLogsDirForApp(packageName); logDir.mkdirs(); @@ -308,17 +309,17 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx newPack.extractFiles(nmfDir); if (isApp) { - File installationDir = new File(Deployment.getAppsDir(), packageName); + File appDir = new File(Deployment.getAppsDir(), packageName); String username = generateUsername(packageName); MetadataApp appMetadata = newPackMetadata.castToApp(); - HelperNMFPackage.generateStartScript(appMetadata, installationDir, nmfDir); - createAuxiliaryFiles(installationDir, username); + AuxFilesGenerator.generateStartScript(appMetadata, appDir, nmfDir); + createAuxiliaryFiles(appDir, username); File logDir = Deployment.getLogsDirForApp(packageName); logDir.mkdirs(); if (OS.isUnix()) { // Change Group owner of the appDir - changeGroupAndSetPermissions(installationDir, username, "750"); + changeGroupAndSetPermissions(appDir, username, "750"); try { changeGroupAndSetPermissions(logDir, username, "770"); @@ -457,16 +458,27 @@ private static void removeAuxiliaryFiles(File folder, String appName) throws IOE NMFPackageManager.removeFile(windows.exists() ? windows : linux); } - private static void createAuxiliaryFiles(File installationDir, String username) throws IOException { + private static void createAuxiliaryFiles(File appDir, String username) throws IOException { + File globalTransport = Deployment.getTransportFile(); + String transport; + + // Generate a dedicated transport.properties for + // the App if the Global transport file does not exist + if (globalTransport.exists()) { + transport = globalTransport.getAbsolutePath(); + } else { + // Generates the transport file in the folder of the App! + File file = new File(appDir, HelperMisc.TRANSPORT_PROPERTIES_FILE); + String transportContent = AuxFilesGenerator.generateTransportProperties(); + AuxFilesGenerator.writeFile(file, transportContent); + transport = HelperMisc.TRANSPORT_PROPERTIES_FILE; + } + // Generate provider.properties - File providerFile = new File(installationDir, HelperMisc.PROVIDER_PROPERTIES_FILE); - String providerContent = HelperNMFPackage.generateProviderProperties(username); - HelperNMFPackage.writeFile(providerFile, providerContent); - - // Generate transport.properties - File transportFile = new File(installationDir, HelperMisc.TRANSPORT_PROPERTIES_FILE); - String transportContent = HelperNMFPackage.generateTransportProperties(); - HelperNMFPackage.writeFile(transportFile, transportContent); + File providerFile = new File(appDir, HelperMisc.PROVIDER_PROPERTIES_FILE); + String providerContent = AuxFilesGenerator.generateProviderProperties(username, transport); + AuxFilesGenerator.writeFile(providerFile, providerContent); + } private static void removeFiles(Metadata metadata) throws IOException { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java new file mode 100644 index 000000000..0539fb39c --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java @@ -0,0 +1,215 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package esa.mo.nmf.nmfpackage.utils; + +import esa.mo.helpertools.helpers.HelperMisc; +import esa.mo.helpertools.misc.OSValidator; +import esa.mo.nmf.nmfpackage.Deployment; +import esa.mo.nmf.nmfpackage.metadata.MetadataApp; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Generates the necessary auxiliary files. + * + * @author Cesar Coelho + */ +public class AuxFilesGenerator { + + private static String getBanner() { + StringBuilder str = new StringBuilder(); + str.append("########################################################\n"); + str.append("# This file was auto-generated by the NMF\n"); + str.append("# during the installation of this App\n"); + str.append("# We do not advise to change it directly!\n"); + str.append("# The file is generated by the class: AuxFilesGenerator\n"); + str.append("########################################################\n"); + str.append("\n"); + return str.toString(); + } + + public static String generateLinuxStartAppScript(String javaCommand, + MetadataApp meta) throws IOException { + StringBuilder str = new StringBuilder(); + str.append("#!/bin/sh\n"); + str.append(getBanner()); + str.append("cd ${0%/*}\n\n"); + + str.append("# Java Runtime Environment:\n"); + str.append("JAVA_CMD=").append(javaCommand).append("\n\n"); + str.append("# App-related constants:\n"); + str.append("MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); + str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); + str.append("MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); + + str.append("# Jars from: App, NMF, and Shared dependencies:\n"); + str.append("JAR_APP=").append(meta.getAppMainJar()).append("\n"); + // The following code must be changed: + str.append("JARS_NMF=").append(Deployment.getJarsNMFDir()).append("\n"); + String shared = ""; + + if (meta.hasDependencies()) { + File sharedLibs = Deployment.getJarsSharedDir(); + String paths = meta.getAppDependenciesFullPaths(sharedLibs); + str.append("JARS_SHARED=").append(paths); + shared = ":$JARS_SHARED"; + } + str.append("\n\nJARS_ALL=$JAR_APP:$JARS_NMF/*").append(shared); + str.append("\n\n"); + + str.append("if [ -z \"$JAVA_OPTS\" ] ; then\n"); + str.append(" JAVA_OPTS=\"-Xms$MIN_HEAP -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); + str.append("fi\n\n"); + + str.append("export JAVA_OPTS\n"); + str.append("export NMF_LIB\n\n"); + + str.append("NOW=$(date +\"%F\")\n"); + String appName = meta.getPackageName(); + str.append("FILENAME=").append(appName).append("_$NOW.log\n"); + String logPath = Deployment.getLogsDirForApp(appName).getAbsolutePath(); + str.append("LOG_PATH=").append(logPath).append("\n"); + str.append("mkdir -p $LOG_PATH\n\n"); + + // The command "exec" spawns the execution in a different process + // str.append("exec -a MyUniqueProcessName "); + str.append("$JAVA_CMD $JAVA_OPTS \\\n"); + str.append(" -classpath \"$JARS_ALL\" \\\n"); + str.append(" \"$MAIN_CLASS\" \\\n"); + str.append(" \"$@\" \\\n"); + str.append(" 2>&1 | tee -a $LOG_PATH/$FILENAME \n"); + + return str.toString(); + } + + public static String generateWindowsStartAppScript(String javaCommand, + String jarFilename, MetadataApp meta) throws IOException { + StringBuilder str = new StringBuilder(); + str.append("@echo off\n\n"); + str.append(":: Java Runtime Environment:\n"); + str.append("set JAVA_CMD=").append(javaCommand).append("\n\n"); + + str.append(":: App-related constants:\n"); + str.append("set MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); + str.append("set MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); + str.append("set MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); + + str.append(":: Jars from: App, NMF, and Shared dependencies:\n"); + str.append("set JAR_APP=").append(jarFilename).append("\n"); + + str.append("set BASEDIR=%~dp0\\..\\..\\..").append("\n"); + str.append("set JARS_NMF=").append("%BASEDIR%\\lib\\*").append("\n"); + + str.append("\n\nset JARS_ALL=\"%JAR_APP%;%JARS_NMF%\""); + str.append("\n\n"); + + str.append("%JAVA_CMD% %JAVA_OPTS% -classpath %JARS_ALL%"); + str.append(" -Dapp.name=\"").append(meta.getPackageName()); + str.append("\" ").append(meta.getAppMainclass()); + return str.toString(); + } + + public static String generateProviderProperties(String runAs, String transportPath) throws IOException { + StringBuilder str = new StringBuilder(); + str.append(getBanner()); + str.append("# MO App configurations\n"); + str.append(HelperMisc.PROP_ORGANIZATION_NAME).append("=").append("esa\n"); + str.append(HelperMisc.APP_CATEGORY).append("=").append("NMF_App\n"); + if (runAs != null) { + str.append(HelperMisc.APP_USER).append("=").append(runAs).append("\n"); + } + str.append("\n"); + + str.append("# Enables the new Home directory mode: \n"); + str.append(HelperMisc.PROP_WORK_DIR_STORAGE_MODE + "=" + "2\n\n"); + + str.append("# NanoSat MO Framework transport configuration\n"); + str.append("helpertools.configurations.provider.transportfilepath="); + str.append(transportPath); + str.append("\n\n"); + + str.append("# NanoSat MO Framework Settings\n"); + str.append("esa.mo.nanosatmoframework.provider.settings=settings.properties"); + str.append("\n\n"); + + str.append("# NanoSat MO Framework dynamic configurations\n"); + str.append("esa.mo.nanosatmoframework.provider.dynamicchanges=true"); + str.append("\n\n"); + + str.append("# Cleanup space archive from synchronised objects\n"); + str.append("esa.mo.nanosatmoframework.archivesync.purgearchive=true\n"); + + return str.toString(); + } + + public static String generateTransportProperties() throws IOException { + StringBuilder str = new StringBuilder(); + str.append(getBanner()); + str.append("# The following property sets the protocol to be used:\n"); + str.append("org.ccsds.moims.mo.mal.transport.default.protocol = maltcp://\n"); + str.append("\n"); + + str.append("# TCP/IP protocol properties:\n"); + str.append("org.ccsds.moims.mo.mal.transport.protocol.maltcp=esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl\n"); + str.append("org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); + + // Bind to localhost + /* + str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); + */ + str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); + str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=127.0.0.1\n"); + str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); + + return str.toString(); + } + + public static void generateStartScript(MetadataApp appDetails, + File appDir, File nmfDir) throws IOException { + String name = appDetails.getPackageName(); + String jarName = appDetails.getAppMainJar(); + + if (jarName.equals("")) { + File jar = HelperNMFPackage.findAppJarInFolder(appDir); + jarName = jar.getName(); + } + + // The Java version for now will be forced to 8, however in + // the future the package should recommend a version + String javaCMD = Deployment.findJREPath(8, 8, 8); + + OSValidator os = new OSValidator(); + + if (os.isUnix() || os.isMac()) { + String content = generateLinuxStartAppScript(javaCMD, appDetails); + File startApp = new File(appDir, "start_" + name + ".sh"); + writeFile(startApp, content); + startApp.setExecutable(true, true); + } + + if (os.isWindows()) { + String content = generateWindowsStartAppScript( + javaCMD, jarName, appDetails); + File startApp = new File(appDir, "start_" + name + ".bat"); + writeFile(startApp, content); + } + } + + public static void writeFile(File file, String content) { + System.out.println(" >> Creating file on: " + file); + + try (FileWriter writer = new FileWriter(file)) { + writer.write(content); + writer.flush(); + writer.close(); + } catch (IOException e) { + // Handle the exception + } + } +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 1449f66d0..a028863ec 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -21,14 +21,9 @@ */ package esa.mo.nmf.nmfpackage.utils; -import esa.mo.helpertools.helpers.HelperMisc; -import esa.mo.helpertools.misc.OSValidator; -import esa.mo.nmf.nmfpackage.Deployment; -import esa.mo.nmf.nmfpackage.metadata.MetadataApp; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -64,152 +59,6 @@ public static long calculateCRCFromInputStream(final InputStream inputStream) th return crc.getValue(); } - private static String getBanner() { - StringBuilder str = new StringBuilder(); - str.append("#######################################################\n"); - str.append("# This file was auto-generated by the NMF\n"); - str.append("# during the installation of this App\n"); - str.append("# We do not advise to change it directly!\n"); - str.append("# The file is generated by the class: HelperNMFPackage\n"); - str.append("#######################################################\n"); - str.append("\n"); - return str.toString(); - } - - public static String generateLinuxStartAppScript(String javaCommand, - MetadataApp meta) throws IOException { - StringBuilder str = new StringBuilder(); - str.append("#!/bin/sh\n"); - str.append(getBanner()); - str.append("cd ${0%/*}\n\n"); - - str.append("# Java Runtime Environment:\n"); - str.append("JAVA_CMD=").append(javaCommand).append("\n\n"); - str.append("# App-related constants:\n"); - str.append("MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); - str.append("MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); - str.append("MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); - - str.append("# Jars from: App, NMF, and Shared dependencies:\n"); - str.append("JAR_APP=").append(meta.getAppMainJar()).append("\n"); - // The following code must be changed: - str.append("JARS_NMF=").append(Deployment.getJarsNMFDir()).append("\n"); - String shared = ""; - - if (meta.hasDependencies()) { - File sharedLibs = Deployment.getJarsSharedDir(); - String paths = meta.getAppDependenciesFullPaths(sharedLibs); - str.append("JARS_SHARED=").append(paths); - shared = ":$JARS_SHARED"; - } - str.append("\n\nJARS_ALL=$JAR_APP:$JARS_NMF/*").append(shared); - str.append("\n\n"); - - str.append("if [ -z \"$JAVA_OPTS\" ] ; then\n"); - str.append(" JAVA_OPTS=\"-Xms$MIN_HEAP -Xmx$MAX_HEAP $JAVA_OPTS\"\n"); - str.append("fi\n\n"); - - str.append("export JAVA_OPTS\n"); - str.append("export NMF_LIB\n\n"); - - str.append("NOW=$(date +\"%F\")\n"); - String appName = meta.getPackageName(); - str.append("FILENAME=").append(appName).append("_$NOW.log\n"); - String logPath = Deployment.getLogsDirForApp(appName).getAbsolutePath(); - str.append("LOG_PATH=").append(logPath).append("\n"); - str.append("mkdir -p $LOG_PATH\n\n"); - - // The command "exec" spawns the execution in a different process - // str.append("exec -a MyUniqueProcessName "); - str.append("$JAVA_CMD $JAVA_OPTS \\\n"); - str.append(" -classpath \"$JARS_ALL\" \\\n"); - str.append(" \"$MAIN_CLASS\" \\\n"); - str.append(" \"$@\" \\\n"); - str.append(" 2>&1 | tee -a $LOG_PATH/$FILENAME \n"); - - return str.toString(); - } - - public static String generateWindowsStartAppScript(String javaCommand, - String jarFilename, MetadataApp meta) throws IOException { - StringBuilder str = new StringBuilder(); - str.append("@echo off\n\n"); - str.append(":: Java Runtime Environment:\n"); - str.append("set JAVA_CMD=").append(javaCommand).append("\n\n"); - - str.append(":: App-related constants:\n"); - str.append("set MAIN_CLASS=").append(meta.getAppMainclass()).append("\n"); - str.append("set MAX_HEAP=").append(meta.getAppMaxHeap()).append("\n"); - str.append("set MIN_HEAP=").append(meta.getAppMinHeap()).append("\n\n"); - - str.append(":: Jars from: App, NMF, and Shared dependencies:\n"); - str.append("set JAR_APP=").append(jarFilename).append("\n"); - - str.append("set BASEDIR=%~dp0\\..\\..\\..").append("\n"); - str.append("set JARS_NMF=").append("%BASEDIR%\\lib\\*").append("\n"); - - str.append("\n\nset JARS_ALL=\"%JAR_APP%;%JARS_NMF%\""); - str.append("\n\n"); - - str.append("%JAVA_CMD% %JAVA_OPTS% -classpath %JARS_ALL%"); - str.append(" -Dapp.name=\"").append(meta.getPackageName()); - str.append("\" ").append(meta.getAppMainclass()); - return str.toString(); - } - - public static String generateProviderProperties(String runAs) throws IOException { - StringBuilder str = new StringBuilder(); - str.append(getBanner()); - str.append("# MO App configurations\n"); - str.append(HelperMisc.PROP_ORGANIZATION_NAME).append("=").append("esa\n"); - str.append(HelperMisc.APP_CATEGORY).append("=").append("NMF_App\n"); - if (runAs != null) { - str.append(HelperMisc.APP_USER).append("=").append(runAs).append("\n"); - } - str.append("\n"); - - str.append("# Enables the new Home directory mode: \n"); - str.append(HelperMisc.PROP_WORK_DIR_STORAGE_MODE + "=" + "2\n"); - str.append("\n"); - str.append("# NanoSat MO Framework transport configuration\n"); - str.append("helpertools.configurations.provider.transportfilepath=transport.properties\n"); - str.append("\n"); - str.append("# NanoSat MO Framework Settings\n"); - str.append("esa.mo.nanosatmoframework.provider.settings=settings.properties\n"); - str.append("\n"); - str.append("# NanoSat MO Framework dynamic configurations\n"); - str.append("esa.mo.nanosatmoframework.provider.dynamicchanges=true\n"); - str.append("\n"); - str.append("# Cleanup space archive from synchronised objects\n"); - str.append("esa.mo.nanosatmoframework.archivesync.purgearchive=true\n"); - - return str.toString(); - } - - public static String generateTransportProperties() throws IOException { - StringBuilder str = new StringBuilder(); - str.append(getBanner()); - str.append("# The following property sets the protocol to be used:\n"); - str.append("org.ccsds.moims.mo.mal.transport.default.protocol = maltcp://\n"); - str.append("\n"); - - str.append("# TCP/IP protocol properties:\n"); - str.append("org.ccsds.moims.mo.mal.transport.protocol.maltcp=esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl\n"); - str.append("org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); - - // Bind to localhost - /* - str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); - str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); - str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); - */ - str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); - str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=127.0.0.1\n"); - str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); - - return str.toString(); - } - public static File findAppJarInFolder(File folder) throws IOException { File[] fList = folder.listFiles(); @@ -250,49 +99,6 @@ public static File findAppJarInFolder(File folder) throws IOException { throw new IOException("There are too many jars inside the target folder!"); } - public static void generateStartScript(MetadataApp appDetails, - File appDir, File nmfDir) throws IOException { - String name = appDetails.getPackageName(); - String jarName = appDetails.getAppMainJar(); - - if (jarName.equals("")) { - File jar = HelperNMFPackage.findAppJarInFolder(appDir); - jarName = jar.getName(); - } - - // The Java version for now will be forced to 8, however in - // the future the package should recommend a version - String javaCMD = Deployment.findJREPath(8, 8, 8); - - OSValidator os = new OSValidator(); - - if (os.isUnix() || os.isMac()) { - String content = generateLinuxStartAppScript(javaCMD, appDetails); - File startApp = new File(appDir, "start_" + name + ".sh"); - HelperNMFPackage.writeFile(startApp, content); - startApp.setExecutable(true, true); - } - - if (os.isWindows()) { - String content = HelperNMFPackage.generateWindowsStartAppScript( - javaCMD, jarName, appDetails); - File startApp = new File(appDir, "start_" + name + ".bat"); - HelperNMFPackage.writeFile(startApp, content); - } - } - - public static void writeFile(File file, String content) { - System.out.println(" >> Creating file on: " + file); - - try (FileWriter writer = new FileWriter(file)) { - writer.write(content); - writer.flush(); - writer.close(); - } catch (IOException e) { - // Handle the exception - } - } - public static String generateFilePathForSystem(final String path) throws IOException { // Sanitize the path to prevent a ZipSlip attack: if (path.contains("..")) { From 271c002453d83e4e1b5ec8a38005f2f0b1028c5d Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 20 Nov 2022 15:17:01 +0100 Subject: [PATCH 149/173] Fixes the License Headers --- .../nmfpackage/utils/AuxFilesGenerator.java | 23 +++++++++++++++---- .../nmfpackage/utils/HelperNMFPackage.java | 1 - 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java index 0539fb39c..b92e5e8b8 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java @@ -1,7 +1,22 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- */ package esa.mo.nmf.nmfpackage.utils; diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index a028863ec..5edf0c43f 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -1,4 +1,3 @@ - /* ---------------------------------------------------------------------------- * Copyright (C) 2021 European Space Agency * European Space Operations Centre From 533486b5d6bf745286a62d760b67852f97dc5ded Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 20 Nov 2022 16:35:55 +0100 Subject: [PATCH 150/173] Prioritize the new jars-nmf folder over the old one & Set autohost as default when the transport needs to be generated --- .../src/main/java/esa/mo/nmf/nmfpackage/Deployment.java | 9 +++++---- .../esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index 24e3ab59b..49d39fb9b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -91,13 +91,14 @@ public static File getEtcDir() { } public static File getJarsNMFDir() { - File deprecatedFolder = new File(getNMFRootDir(), DIR_JARS_NMF_OLD); + File newFolder = new File(getNMFRootDir(), DIR_JARS_NMF); - if (deprecatedFolder.exists()) { - return deprecatedFolder; + if (newFolder.exists()) { + return newFolder; } - return new File(getNMFRootDir(), DIR_JARS_NMF); + // Otherwise return the old folder: + return new File(getNMFRootDir(), DIR_JARS_NMF_OLD); } public static File getJarsSharedDir() { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java index b92e5e8b8..b68f526e3 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/AuxFilesGenerator.java @@ -173,14 +173,14 @@ public static String generateTransportProperties() throws IOException { str.append("org.ccsds.moims.mo.mal.encoding.protocol.maltcp=esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory\n"); // Bind to localhost + str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=true\n"); + str.append("#org.ccsds.moims.mo.mal.transport.tcpip.host=xxx.xxx.xxx.xxx\n"); + str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=1024\n"); /* str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); - str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=localhost\n"); - str.append("org.ccsds.moims.mo.mal.transport.tcpip.port=1025\n"); - */ - str.append("org.ccsds.moims.mo.mal.transport.tcpip.autohost=false\n"); str.append("org.ccsds.moims.mo.mal.transport.tcpip.host=127.0.0.1\n"); str.append("#org.ccsds.moims.mo.mal.transport.tcpip.port=54321\n"); + */ return str.toString(); } From ba02a19538a3c362adb123478687c0b6bee6c499 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 20 Nov 2022 22:57:17 +0100 Subject: [PATCH 151/173] Adds capability to create NMF Packages with Java inside --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 137 +--------- .../metadata/MetadataDependency.java | 11 +- .../nmf/nmfpackage/metadata/MetadataJava.java | 46 ++++ .../myApp.filetype | 0 core/nmf-package-maven-plugin/pom.xml | 6 + .../nmfpackage/GenerateNMFPackageMojo.java | 45 ++-- .../mo/nmf/nmfpackage/NMFPackageBuilder.java | 237 ++++++++++++++++++ .../tests/SimpleDemoPackageAppCreation.java} | 51 ++-- .../SimpleDemoPackageAppInstallation.java} | 8 +- .../tests/SimpleDemoPackageJavaCreation.java | 160 ++++++++++++ .../mo/nmf/nmfpackage/tests/package-info.java | 0 11 files changed, 500 insertions(+), 201 deletions(-) create mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataJava.java rename core/{nmf-package-lib => nmf-package-maven-plugin}/myApp.filetype (100%) create mode 100644 core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java rename core/{nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java => nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java} (60%) rename core/{nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java => nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppInstallation.java} (87%) create mode 100644 core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java rename core/{nmf-package-lib => nmf-package-maven-plugin}/src/main/java/esa/mo/nmf/nmfpackage/tests/package-info.java (100%) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java index 46f786d66..a7d74b5e2 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java @@ -43,38 +43,8 @@ */ public class NMFPackageCreator { - private static final int BUFFER = 2048; - private static void zipFiles(String outputPath, ArrayList from, - ArrayList newLocations) { - try { - BufferedInputStream origin; - FileOutputStream dest = new FileOutputStream(outputPath); - ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); - byte[] data = new byte[BUFFER]; - for (int i = 0; i < from.size(); i++) { - String file = from.get(i); - String newPath = newLocations.get(i); - System.out.println(" (" + i + ") Selecting file: " + file - + "\n (" + i + ") To NMF Package path: " + newPath); - origin = new BufferedInputStream(new FileInputStream(file), BUFFER); - - ZipEntry entry = new ZipEntry(newPath); - out.putNextEntry(entry); - - int count; - while ((count = origin.read(data, 0, BUFFER)) != -1) { - out.write(data, 0, count); - } - origin.close(); - } - out.close(); - } catch (IOException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log( - Level.SEVERE, "The Files could not be zipped!", ex); - } - } @Deprecated public static String nmfPackageCreator(DetailsApp details, @@ -87,111 +57,8 @@ public static String nmfPackageCreator(DetailsApp details, ArrayList filesInput, ArrayList newLocationsInput, String destinationFolder) { Metadata metadata = new Metadata(details.getProperties()); - return NMFPackageCreator.create(metadata, filesInput, newLocationsInput, destinationFolder); - } - - public static String create(Metadata metadata, ArrayList filesInput, - ArrayList newLocationsInput, String destinationFolder) { - final ArrayList files = new ArrayList<>(filesInput); - final ArrayList newLocations = new ArrayList<>(newLocationsInput); - int size = newLocations.size(); - - for (int i = 0; i < size; i++) { - try { - String path = newLocations.get(i); - long crc = HelperNMFPackage.calculateCRCFromFile(files.get(i)); - //descriptor.addFile(new NMFPackageFile(path, crc)); - metadata.addProperty(Metadata.FILE_PATH + "." + i, path); - metadata.addProperty(Metadata.FILE_CRC + "." + i, String.valueOf(crc)); - } catch (IOException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, - "There was a problem during the CRC calculation.", ex); - } - } - - metadata.addProperty(Metadata.FILE_COUNT, String.valueOf(size)); - - // Generate metadata.properties - Logger.getLogger(NMFPackageCreator.class.getName()).log( - Level.INFO, "Generating metadata file..."); - - File metadataFile = new File(Metadata.FILENAME); - - try { - metadata.store(metadataFile); // Store the metadata file - } catch (IOException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log( - Level.SEVERE, "The file could not be stored!", ex); - } - - // Add the metadata file to the list of Files to be zipped - files.add(metadataFile.getPath()); - newLocations.add(Metadata.FILENAME); - // ------------------------------------------------------------------- - - // ------------------------------------------------------------------- - // Generate digital signature - /* - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "Generating digital signature..."); - - // Generate Public and Private keys - KeyPair pair = NMFDigitalSignature.generateKeyPar(); - - // Generate the SHA (can only be done after having the receipt file) - byte[] signature = NMFDigitalSignature.signWithData(pair.getPrivate(), HelperNMFPackage.RECEIPT_FILENAME); - - // Write the signature to the file: DS_FILENAME - try { - FileOutputStream sigfos = new FileOutputStream(HelperNMFPackage.DS_FILENAME); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sigfos)); - bw.write(javax.xml.bind.DatatypeConverter.printHexBinary(signature)); - bw.flush(); - sigfos.close(); - } catch (FileNotFoundException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, null, ex); - } - // ------------------------------------------------------------------- - - // Add the signature file to the list of Files to be zipped - File digitalSignature = new File(HelperNMFPackage.DS_FILENAME); - files.add((new File(HelperNMFPackage.DS_FILENAME)).getPath()); - newLocations.add(HelperNMFPackage.DS_FILENAME); - */ - // ------------------------------------------------------------------- - // ------------------------------------------------------------------- - // Compress: - Logger.getLogger(NMFPackageCreator.class.getName()).log( - Level.INFO, "Creating compressed NMF Package..."); - - String name = metadata.getPackageName() + "-" - + metadata.getPackageVersion() + "." + Const.NMF_PACKAGE_SUFFIX; - String destinationPath = (destinationFolder == null) ? name - : destinationFolder + File.separator + name; - NMFPackageCreator.zipFiles(destinationPath, files, newLocations); - - // Output the secret privateKey into a file - /* - try { - byte[] key = pair.getPrivate().getEncoded(); - FileOutputStream keyfos = new FileOutputStream(HelperNMFPackage.PRIVATE_KEY_FILENAME); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(keyfos)); - bw.write(javax.xml.bind.DatatypeConverter.printHexBinary(key)); - bw.flush(); - keyfos.close(); - } catch (FileNotFoundException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.SEVERE, null, ex); - } - */ - // Delete temporary files: - metadataFile.delete(); - //digitalSignature.delete(); - - return destinationPath; + return null; + // return NMFPackageCreator.create(metadata, filesInput, newLocationsInput, destinationFolder); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java index c7d4c18f3..1fbc36ace 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataDependency.java @@ -23,17 +23,24 @@ import java.util.Properties; /** - * The MetadataApp class holds the metadata of a Dependency in a NMF Package. + * The MetadataDependency class holds the metadata of a Dependency in a NMF + * Package. * * @author Cesar Coelho */ public class MetadataDependency extends Metadata { + /** + * Constructor for the MetadataDependency class. + * + * @param packageName The name of the package. + * @param version The version of the package. + */ public MetadataDependency(String packageName, String version) { super(new Properties()); properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_DEPENDENCY); properties.put(Metadata.PACKAGE_NAME, packageName); properties.put(Metadata.PACKAGE_VERSION, version); } - + } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataJava.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataJava.java new file mode 100644 index 000000000..1915bf5c8 --- /dev/null +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/MetadataJava.java @@ -0,0 +1,46 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage.metadata; + +import java.util.Properties; + +/** + * The MetadataJava class holds the metadata of a Java Runtime Environment (JRE) + * or Java Development Kit (JDK) in a NMF Package. + * + * @author Cesar Coelho + */ +public class MetadataJava extends Metadata { + + /** + * Constructor for the MetadataJava class. + * + * @param packageName The name of the package. + * @param version The version of the package. + */ + public MetadataJava(String packageName, String version) { + super(new Properties()); + properties.put(Metadata.PACKAGE_TYPE, Metadata.TYPE_UPDATE_JAVA); + properties.put(Metadata.PACKAGE_NAME, packageName); + properties.put(Metadata.PACKAGE_VERSION, version); + } + +} diff --git a/core/nmf-package-lib/myApp.filetype b/core/nmf-package-maven-plugin/myApp.filetype similarity index 100% rename from core/nmf-package-lib/myApp.filetype rename to core/nmf-package-maven-plugin/myApp.filetype diff --git a/core/nmf-package-maven-plugin/pom.xml b/core/nmf-package-maven-plugin/pom.xml index b7050203d..b26ebe651 100644 --- a/core/nmf-package-maven-plugin/pom.xml +++ b/core/nmf-package-maven-plugin/pom.xml @@ -73,6 +73,12 @@ maven-plugin-annotations 3.6.0 + + org.apache.commons + commons-compress + 1.19 + jar + diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 8732547b3..9f47abefd 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -111,29 +111,26 @@ public enum Privilege { @Parameter(property = "generate-nmf-package.privilege", defaultValue = "normal") private Privilege privilege; - private final static String TARGET_FOLDER = "target"; - final ArrayList inputFiles = new ArrayList<>(); - final ArrayList locations = new ArrayList<>(); - String appPath = "no-path"; + private final static File TARGET_FOLDER = new File("target"); @Override public void execute() throws MojoExecutionException { getLog().info("Generating NMF Package..."); - appPath = Deployment.DIR_APPS + File.separator + name + File.separator; + + String path = Deployment.DIR_APPS + File.separator + name; + NMFPackageBuilder builder = new NMFPackageBuilder(path); String mainJar = ""; try { - File target = new File(TARGET_FOLDER); - File myAppFilename = HelperNMFPackage.findAppJarInFolder(target); + File myAppFilename = HelperNMFPackage.findAppJarInFolder(TARGET_FOLDER); mainJar = myAppFilename.getName(); - inputFiles.add(myAppFilename.getAbsolutePath()); - locations.add(appPath + myAppFilename.getName()); + builder.addFileOrDirectory(myAppFilename); // Add the external libs or files if (libs != null) { for (String lib : libs) { getLog().info(">> lib: " + lib); - addFileOrDirectory(lib, ""); + builder.addFileOrDirectory(lib, ""); } } } catch (IOException ex) { @@ -207,11 +204,12 @@ public void execute() throws MojoExecutionException { // Package MetadataApp metadata = new MetadataApp(name, version, mainClass, mainJar, maxHeap, minHeap, dependencies); - NMFPackageCreator.create(metadata, inputFiles, locations, TARGET_FOLDER); + builder.createPackage(metadata, TARGET_FOLDER); } private String packageJarDependency(Artifact artifact) { File file = artifact.getFile(); + /* ArrayList files = new ArrayList<>(); files.add(file.toPath().toString()); @@ -220,22 +218,17 @@ private String packageJarDependency(Artifact artifact) { ArrayList newLocations = new ArrayList<>(); newLocations.add(Deployment.DIR_JARS_SHARED + File.separator + file.getName()); NMFPackageCreator.create(metadata, files, newLocations, TARGET_FOLDER); - return file.getName(); - } - - private void addFileOrDirectory(String path, String nest) { - File f = new File(path); - - if (f.isDirectory()) { - nest += f.getName() + File.separator; + */ - for (File n : f.listFiles()) { - addFileOrDirectory(n.getAbsolutePath(), nest); - } - } else { - inputFiles.add(f.getAbsolutePath()); - locations.add(appPath + nest + f.getName()); - } + String artifactId = artifact.getArtifactId(); + String ver = artifact.getVersion(); + MetadataDependency metadata = new MetadataDependency(artifactId, ver); + + NMFPackageBuilder builder = new NMFPackageBuilder(Deployment.DIR_JARS_SHARED); + builder.addFileOrDirectory(file); + builder.createPackage(metadata, TARGET_FOLDER); + + return file.getName(); } } diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java new file mode 100644 index 000000000..56d8548a6 --- /dev/null +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java @@ -0,0 +1,237 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2022 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage; + +import esa.mo.helpertools.misc.Const; +import esa.mo.nmf.nmfpackage.metadata.Metadata; +import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * The NMF Package Builder class. + * + * @author Cesar Coelho + */ +public class NMFPackageBuilder { + + private static final int BUFFER = 2048; + final ArrayList inputFiles = new ArrayList<>(); + final ArrayList locations = new ArrayList<>(); + final String appPath; + + /** + * The Constructor for the PackageBuilder class. + * + * @param folderType The type of folder that the file should be. + */ + public NMFPackageBuilder(String folderType) { + this.appPath = folderType + File.separator; + } + + /** + * Adds a File or Directory to the builder. + * + * @param path The path to the file or directory. + * @param nest The nest of the file or directory. + */ + public void addFileOrDirectory(String path, String nest) { + File f = new File(path); + + if (f.isDirectory()) { + nest += f.getName() + File.separator; + + for (File n : f.listFiles()) { + addFileOrDirectory(n.getAbsolutePath(), nest); + } + } else { + inputFiles.add(f.getAbsolutePath()); + locations.add(appPath + nest + f.getName()); + } + } + + public void addFileOrDirectory(String path) { + addFileOrDirectory(new File(path)); + } + + public void addFileOrDirectory(File file) { + addFileOrDirectory(file.getAbsolutePath(), ""); + } + + /** + * Creates an NMF Package with the selected metadata in the selected + * destination folder. + * + * @param metadata The metadata of the NMF Package. + * @param destinationFolder The destination folder where to store the NMF + * Package. + * @return The created NMF Package File. + */ + public File createPackage(Metadata metadata, File destinationFolder) { + String path = destinationFolder.getAbsolutePath(); + String out = create(metadata, inputFiles, locations, path); + return new File(out); + } + + private static String create(Metadata metadata, ArrayList filesInput, + ArrayList newLocationsInput, String destinationFolder) { + final ArrayList files = new ArrayList<>(filesInput); + final ArrayList newLocations = new ArrayList<>(newLocationsInput); + int size = newLocations.size(); + + for (int i = 0; i < size; i++) { + try { + String path = newLocations.get(i); + long crc = HelperNMFPackage.calculateCRCFromFile(files.get(i)); + //descriptor.addFile(new NMFPackageFile(path, crc)); + metadata.addProperty(Metadata.FILE_PATH + "." + i, path); + metadata.addProperty(Metadata.FILE_CRC + "." + i, String.valueOf(crc)); + } catch (IOException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.SEVERE, + "There was a problem during the CRC calculation.", ex); + } + } + + metadata.addProperty(Metadata.FILE_COUNT, String.valueOf(size)); + + // Generate metadata.properties + Logger.getLogger(NMFPackageBuilder.class.getName()).log( + Level.INFO, "Generating metadata file..."); + + File metadataFile = new File(Metadata.FILENAME); + + try { + metadata.store(metadataFile); // Store the metadata file + } catch (IOException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log( + Level.SEVERE, "The file could not be stored!", ex); + } + + // Add the metadata file to the list of Files to be zipped + files.add(metadataFile.getPath()); + newLocations.add(Metadata.FILENAME); + // ------------------------------------------------------------------- + + // ------------------------------------------------------------------- + // Generate digital signature + /* + Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.INFO, + "Generating digital signature..."); + + // Generate Public and Private keys + KeyPair pair = NMFDigitalSignature.generateKeyPar(); + + // Generate the SHA (can only be done after having the receipt file) + byte[] signature = NMFDigitalSignature.signWithData(pair.getPrivate(), HelperNMFPackage.RECEIPT_FILENAME); + + // Write the signature to the file: DS_FILENAME + try { + FileOutputStream sigfos = new FileOutputStream(HelperNMFPackage.DS_FILENAME); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sigfos)); + bw.write(javax.xml.bind.DatatypeConverter.printHexBinary(signature)); + bw.flush(); + sigfos.close(); + } catch (FileNotFoundException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.SEVERE, null, ex); + } + // ------------------------------------------------------------------- + + // Add the signature file to the list of Files to be zipped + File digitalSignature = new File(HelperNMFPackage.DS_FILENAME); + files.add((new File(HelperNMFPackage.DS_FILENAME)).getPath()); + newLocations.add(HelperNMFPackage.DS_FILENAME); + */ + // ------------------------------------------------------------------- + // ------------------------------------------------------------------- + // Compress: + Logger.getLogger(NMFPackageBuilder.class.getName()).log( + Level.INFO, "Creating compressed NMF Package..."); + + String name = metadata.getPackageName() + "-" + + metadata.getPackageVersion() + "." + Const.NMF_PACKAGE_SUFFIX; + String destinationPath = (destinationFolder == null) ? name + : destinationFolder + File.separator + name; + zipFiles(destinationPath, files, newLocations); + + // Output the secret privateKey into a file + /* + try { + byte[] key = pair.getPrivate().getEncoded(); + FileOutputStream keyfos = new FileOutputStream(HelperNMFPackage.PRIVATE_KEY_FILENAME); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(keyfos)); + bw.write(javax.xml.bind.DatatypeConverter.printHexBinary(key)); + bw.flush(); + keyfos.close(); + } catch (FileNotFoundException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.SEVERE, null, ex); + } + */ + // Delete temporary files: + metadataFile.delete(); + //digitalSignature.delete(); + + return destinationPath; + } + + private static void zipFiles(String outputPath, ArrayList from, + ArrayList newLocations) { + try { + BufferedInputStream origin; + FileOutputStream dest = new FileOutputStream(outputPath); + ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); + byte[] data = new byte[BUFFER]; + + for (int i = 0; i < from.size(); i++) { + String file = from.get(i); + String newPath = newLocations.get(i); + System.out.println(" (" + i + ") Selecting file: " + file + + "\n (" + i + ") To NMF Package path: " + newPath); + origin = new BufferedInputStream(new FileInputStream(file), BUFFER); + + ZipEntry entry = new ZipEntry(newPath); + out.putNextEntry(entry); + + int count; + while ((count = origin.read(data, 0, BUFFER)) != -1) { + out.write(data, 0, count); + } + origin.close(); + } + out.close(); + } catch (IOException ex) { + Logger.getLogger(NMFPackageBuilder.class.getName()).log( + Level.SEVERE, "The Files could not be zipped!", ex); + } + } +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java similarity index 60% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java rename to core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java index 12ee957f8..1e309f8e4 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageCreation.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java @@ -21,9 +21,13 @@ package esa.mo.nmf.nmfpackage.tests; import esa.mo.helpertools.helpers.HelperTime; +import esa.mo.nmf.nmfpackage.Deployment; import esa.mo.nmf.nmfpackage.NMFPackageCreator; +import esa.mo.nmf.nmfpackage.NMFPackageBuilder; import esa.mo.nmf.nmfpackage.receipt.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; +import esa.mo.nmf.nmfpackage.metadata.MetadataApp; +import esa.mo.nmf.nmfpackage.metadata.MetadataDependency; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -37,7 +41,7 @@ * * @author Cesar Coelho */ -public class SimpleDemoPackageCreation { +public class SimpleDemoPackageAppCreation { /** * Main command line entry point. @@ -45,45 +49,24 @@ public class SimpleDemoPackageCreation { * @param args the command line arguments */ public static void main(final String[] args) { - SimpleDemoPackageCreation.createPackage(); + SimpleDemoPackageAppCreation.createPackage(); } public static void createPackage() { - ArrayList files = new ArrayList<>(); - ArrayList newLocations = new ArrayList<>(); - - String myAppFilename = "myApp.filetype"; - String dummyFolder = "myInstalledApp"; - files.add(myAppFilename); - newLocations.add("apps" + File.separator + dummyFolder + File.separator + myAppFilename); - - final Time time = new Time(System.currentTimeMillis()); - final String timestamp = HelperTime.time2readableString(time); - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, "\n------------- Package 1 Generation -------------\n"); // Package 1 - DetailsApp details = new DetailsApp("TestPackage", "1.0", - timestamp, "noclass", "", "96m", null); - - NMFPackageCreator.nmfPackageCreator(details, files, newLocations); - - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "\n------------- Package 2 Generation -------------\n"); - - // Package 2 - DetailsApp details2 = new DetailsApp("TestPackage", "2.0", - timestamp, "noclass", "", "96m", null); - NMFPackageCreator.nmfPackageCreator(details2, files, newLocations); + String myAppFilename = "myApp.filetype"; + String appName = "my-test-app"; + String path = Deployment.DIR_APPS + File.separator + appName; - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "\n------------- Package 3 Generation -------------\n"); + MetadataApp metadata = new MetadataApp(appName, "1.0.0", + "noclass", "myJarFile.jar", "128m", "16m", null); - // Package 3 - DetailsApp details3 = new DetailsApp("TestPackage", "3.0", - timestamp, "noclass", "", "96m", null); - String location = NMFPackageCreator.nmfPackageCreator(details3, files, newLocations); + NMFPackageBuilder builder = new NMFPackageBuilder(path); + builder.addFileOrDirectory(myAppFilename); + File location = builder.createPackage(metadata, new File("target")); try { // Test if the created file can be parsed @@ -91,10 +74,10 @@ public static void createPackage() { // Try to open the the metadata file inside the Zip file // and parse it into a Metadata object - Metadata metadata = Metadata.parseZipFile(writtenFile); - metadata = null; + Metadata metadataInFile = Metadata.parseZipFile(writtenFile); + metadataInFile = null; } catch (IOException ex) { - Logger.getLogger(SimpleDemoPackageCreation.class.getName()).log( + Logger.getLogger(SimpleDemoPackageAppCreation.class.getName()).log( Level.SEVERE, "The file could not be processed!", ex); } } diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppInstallation.java similarity index 87% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java rename to core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppInstallation.java index 556874da3..e1c613078 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageInstallation.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppInstallation.java @@ -30,7 +30,7 @@ * * @author Cesar Coelho */ -public class SimpleDemoPackageInstallation { +public class SimpleDemoPackageAppInstallation { /** * Main command line entry point. @@ -38,7 +38,7 @@ public class SimpleDemoPackageInstallation { * @param args the command line arguments */ public static void main(final String[] args) { - SimpleDemoPackageInstallation.installPackage(); + SimpleDemoPackageAppInstallation.installPackage(); } public static void installPackage() { @@ -49,8 +49,8 @@ public static void installPackage() { try { manager.install(packagePath, new File(destinationFolder)); } catch (IOException ex) { - Logger.getLogger(SimpleDemoPackageInstallation.class.getName()).log(Level.SEVERE, - "The package could not be installed!", ex); + Logger.getLogger(SimpleDemoPackageAppInstallation.class.getName()).log( + Level.SEVERE, "The package could not be installed!", ex); } } } diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java new file mode 100644 index 000000000..4dbae6fe0 --- /dev/null +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java @@ -0,0 +1,160 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.nmfpackage.tests; + +import esa.mo.nmf.nmfpackage.Deployment; +import esa.mo.nmf.nmfpackage.NMFPackageCreator; +import esa.mo.nmf.nmfpackage.NMFPackageBuilder; +import esa.mo.nmf.nmfpackage.metadata.MetadataJava; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.zip.GZIPInputStream; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.codehaus.plexus.util.FileUtils; + +/** + * A simple demo code to test the generation of NMF Packages. + * + * @author Cesar Coelho + */ +public class SimpleDemoPackageJavaCreation { + + /** + * Main command line entry point. + * + * @param args the command line arguments + */ + public static void main(final String[] args) { + SimpleDemoPackageJavaCreation.createPackages(); + } + + public static File downloadFile(URL url) throws IOException { + ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream()); + String filename = new File(url.getPath()).getName(); + FileOutputStream fileOutputStream = new FileOutputStream(filename); + + Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + "Downloading file: " + url.toString()); + + long timestamp = System.currentTimeMillis(); + fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); + timestamp = System.currentTimeMillis() - timestamp; + Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + "Downloaded in " + timestamp + " ms!"); + + return new File(filename); + } + + public static void extractFileTo(File input, File outputFolder) throws IOException { + GZIPInputStream zipIS = new GZIPInputStream(new FileInputStream(input)); + TarArchiveInputStream tarInput = new TarArchiveInputStream(zipIS); + outputFolder.mkdirs(); + String outputPath = outputFolder.getAbsolutePath(); + + TarArchiveEntry entry; + int BUFFER_SIZE = 1024; + + while ((entry = tarInput.getNextTarEntry()) != null) { + File newFile = new File(outputPath, entry.getName()); + + //Create directories as required + if (entry.isDirectory()) { + newFile.mkdirs(); + } else { + int count; + byte data[] = new byte[BUFFER_SIZE]; + FileOutputStream fos = new FileOutputStream(newFile); + BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE); + while ((count = tarInput.read(data, 0, BUFFER_SIZE)) != -1) { + dest.write(data, 0, count); + } + dest.close(); + } + } + } + + public static void createJavaPackage(String link) { + try { + // Download files + URL url = new URL(link); + File downloadedFile = downloadFile(url); + Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + "The file was downloaded in path: " + downloadedFile.getAbsolutePath()); + + // Extract them + File extractionTarget = new File("temp_extracted_files"); + Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + "Extracting files: " + extractionTarget.getAbsolutePath()); + extractFileTo(downloadedFile, extractionTarget); + + for (File javaDir : extractionTarget.listFiles()) { + Logger.getLogger(NMFPackageCreator.class.getName()).log( + Level.INFO, "Generating NMF Package..."); + + // Package them + MetadataJava metadata = new MetadataJava(downloadedFile.getName(), "1.0"); + NMFPackageBuilder builder = new NMFPackageBuilder(Deployment.DIR_JAVA); + builder.addFileOrDirectory(javaDir); + File location = builder.createPackage(metadata, new File("target")); + Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + "NMF Package in: " + location.getAbsolutePath()); + } + + Logger.getLogger(NMFPackageCreator.class.getName()).log( + Level.INFO, "Deleting files..."); + + // Delete the downloaded file + FileUtils.forceDelete(downloadedFile); + + // Delete the extracted folder: + FileUtils.forceDelete(extractionTarget); + } catch (IOException ex) { + Logger.getLogger(SimpleDemoPackageJavaCreation.class + .getName()).log(Level.SEVERE, null, ex); + } + } + + public static void createPackages() { + // Files can be downloaded from: + // https://adoptium.net/temurin/archive/ + + // url = new URL("https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jdk_arm_linux_hotspot_8u292b10.tar.gz"); + String jdk8 = "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u352-b08/OpenJDK8U-jdk_arm_linux_hotspot_8u352b08.tar.gz"; + //createJavaPackage(jdk8); + + // Repo here: https://github.com/AdoptOpenJDK/openjdk11-binaries + String jdk11 = "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9.1%2B1/OpenJDK11U-jdk_arm_linux_hotspot_11.0.9.1_1.tar.gz"; + createJavaPackage(jdk11); + + // Repo here: https://github.com/AdoptOpenJDK/openjdk17-binaries + String jdk17 = "https://github.com/AdoptOpenJDK/openjdk17-binaries/releases/download/jdk-2021-05-07-13-31/OpenJDK-debugimage_aarch64_linux_hotspot_2021-05-06-23-30.tar.gz"; + + } +} diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/package-info.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/package-info.java similarity index 100% rename from core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/tests/package-info.java rename to core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/package-info.java From 893c1906185d395c5f245afd005df7489fff0bda Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Sun, 20 Nov 2022 23:08:40 +0100 Subject: [PATCH 152/173] Code cleanup --- .../mo/nmf/nmfpackage/NMFPackageCreator.java | 64 ------------------- .../nmfpackage/GenerateNMFPackageMojo.java | 11 ---- .../tests/SimpleDemoPackageAppCreation.java | 10 +-- .../tests/SimpleDemoPackageJavaCreation.java | 25 ++++---- 4 files changed, 14 insertions(+), 96 deletions(-) delete mode 100644 core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java deleted file mode 100644 index a7d74b5e2..000000000 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageCreator.java +++ /dev/null @@ -1,64 +0,0 @@ -/* ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework - * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 - * You may not use this file except in compliance with the License. - * - * Except as expressly set forth in this License, the Software is provided to - * You on an "as is" basis and without warranties of any kind, including without - * limitation merchantability, fitness for a particular purpose, absence of - * defects or errors, accuracy or non-infringement of intellectual property rights. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * ---------------------------------------------------------------------------- - */ -package esa.mo.nmf.nmfpackage; - -import esa.mo.nmf.nmfpackage.utils.HelperNMFPackage; -import esa.mo.helpertools.misc.Const; -import esa.mo.nmf.nmfpackage.receipt.DetailsApp; -import esa.mo.nmf.nmfpackage.metadata.Metadata; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -/** - * The NMF Package Creator class. - * - * @author Cesar Coelho - */ -public class NMFPackageCreator { - - - - - @Deprecated - public static String nmfPackageCreator(DetailsApp details, - ArrayList filesInput, ArrayList newLocationsInput) { - return NMFPackageCreator.nmfPackageCreator(details, filesInput, newLocationsInput, null); - } - - @Deprecated - public static String nmfPackageCreator(DetailsApp details, - ArrayList filesInput, ArrayList newLocationsInput, - String destinationFolder) { - Metadata metadata = new Metadata(details.getProperties()); - return null; - // return NMFPackageCreator.create(metadata, filesInput, newLocationsInput, destinationFolder); - } - -} diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 9f47abefd..7837bc823 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -209,17 +209,6 @@ public void execute() throws MojoExecutionException { private String packageJarDependency(Artifact artifact) { File file = artifact.getFile(); - /* - ArrayList files = new ArrayList<>(); - files.add(file.toPath().toString()); - - String id = artifact.getArtifactId(); - MetadataDependency metadata = new MetadataDependency(id, artifact.getVersion()); - ArrayList newLocations = new ArrayList<>(); - newLocations.add(Deployment.DIR_JARS_SHARED + File.separator + file.getName()); - NMFPackageCreator.create(metadata, files, newLocations, TARGET_FOLDER); - */ - String artifactId = artifact.getArtifactId(); String ver = artifact.getVersion(); MetadataDependency metadata = new MetadataDependency(artifactId, ver); diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java index 1e309f8e4..ea4ece30f 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java @@ -20,21 +20,15 @@ */ package esa.mo.nmf.nmfpackage.tests; -import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.nmfpackage.Deployment; -import esa.mo.nmf.nmfpackage.NMFPackageCreator; import esa.mo.nmf.nmfpackage.NMFPackageBuilder; -import esa.mo.nmf.nmfpackage.receipt.DetailsApp; import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.metadata.MetadataApp; -import esa.mo.nmf.nmfpackage.metadata.MetadataDependency; import java.io.File; import java.io.IOException; -import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipFile; -import org.ccsds.moims.mo.mal.structures.Time; /** * A simple demo code to test the generation of NMF Packages. @@ -53,8 +47,8 @@ public static void main(final String[] args) { } public static void createPackage() { - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "\n------------- Package 1 Generation -------------\n"); + Logger.getLogger(SimpleDemoPackageAppCreation.class.getName()).log( + Level.INFO, "\n----------- Package 1 Generation -----------\n"); // Package 1 String myAppFilename = "myApp.filetype"; diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java index 4dbae6fe0..ec0d26d22 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java @@ -21,7 +21,6 @@ package esa.mo.nmf.nmfpackage.tests; import esa.mo.nmf.nmfpackage.Deployment; -import esa.mo.nmf.nmfpackage.NMFPackageCreator; import esa.mo.nmf.nmfpackage.NMFPackageBuilder; import esa.mo.nmf.nmfpackage.metadata.MetadataJava; import java.io.BufferedOutputStream; @@ -60,14 +59,14 @@ public static File downloadFile(URL url) throws IOException { String filename = new File(url.getPath()).getName(); FileOutputStream fileOutputStream = new FileOutputStream(filename); - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "Downloading file: " + url.toString()); + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( + Level.INFO, "Downloading file: " + url.toString()); long timestamp = System.currentTimeMillis(); fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); timestamp = System.currentTimeMillis() - timestamp; - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "Downloaded in " + timestamp + " ms!"); + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( + Level.INFO, "Downloaded in " + timestamp + " ms!"); return new File(filename); } @@ -105,17 +104,17 @@ public static void createJavaPackage(String link) { // Download files URL url = new URL(link); File downloadedFile = downloadFile(url); - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log(Level.INFO, "The file was downloaded in path: " + downloadedFile.getAbsolutePath()); // Extract them File extractionTarget = new File("temp_extracted_files"); - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log(Level.INFO, "Extracting files: " + extractionTarget.getAbsolutePath()); extractFileTo(downloadedFile, extractionTarget); for (File javaDir : extractionTarget.listFiles()) { - Logger.getLogger(NMFPackageCreator.class.getName()).log( + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( Level.INFO, "Generating NMF Package..."); // Package them @@ -123,11 +122,11 @@ public static void createJavaPackage(String link) { NMFPackageBuilder builder = new NMFPackageBuilder(Deployment.DIR_JAVA); builder.addFileOrDirectory(javaDir); File location = builder.createPackage(metadata, new File("target")); - Logger.getLogger(NMFPackageCreator.class.getName()).log(Level.INFO, - "NMF Package in: " + location.getAbsolutePath()); + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( + Level.INFO, "NMF Package in: " + location.getAbsolutePath()); } - Logger.getLogger(NMFPackageCreator.class.getName()).log( + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( Level.INFO, "Deleting files..."); // Delete the downloaded file @@ -136,8 +135,8 @@ public static void createJavaPackage(String link) { // Delete the extracted folder: FileUtils.forceDelete(extractionTarget); } catch (IOException ex) { - Logger.getLogger(SimpleDemoPackageJavaCreation.class - .getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( + Level.SEVERE, "Something went wrong...", ex); } } From 5ec5c4042e89a4ed7c523a6e2e9f500d7183e84f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Mon, 21 Nov 2022 22:51:24 +0100 Subject: [PATCH 153/173] [nmf-package] Constructor of the NMFPackageBuilder has now a Metadata argument object. --- .../mo/nmf/nmfpackage/metadata/Metadata.java | 27 ++++++-- .../nmfpackage/GenerateNMFPackageMojo.java | 68 +++++++++---------- .../mo/nmf/nmfpackage/NMFPackageBuilder.java | 41 ++++++----- .../tests/SimpleDemoPackageAppCreation.java | 14 ++-- .../tests/SimpleDemoPackageJavaCreation.java | 11 ++- 5 files changed, 89 insertions(+), 72 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java index 8cc5d6c0c..c2a626033 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/metadata/Metadata.java @@ -79,6 +79,11 @@ public class Metadata { protected final Properties properties; private ArrayList files; + /** + * Constructor of the Metadata class. + * + * @param properties The properties to be part of the metadata. + */ public Metadata(final Properties properties) { this(properties, null); } @@ -98,8 +103,10 @@ public Metadata(Properties properties, ArrayList files) { for (int i = 0; i < files.size(); i++) { NMFPackageFile file = files.get(i); - this.properties.put(FILE_PATH + "." + i, file.getPath()); - this.properties.put(FILE_CRC + "." + i, String.valueOf(file.getCRC())); + String index = "." + i; + String crc = String.valueOf(file.getCRC()); + this.properties.put(FILE_PATH + index, file.getPath()); + this.properties.put(FILE_CRC + index, crc); } } } @@ -145,8 +152,9 @@ public synchronized ArrayList getFiles() { int count = Integer.parseInt(properties.getProperty(FILE_COUNT, "0")); for (int i = 0; i < count; i++) { - String path = properties.getProperty(FILE_PATH + "." + i); - long crc = Long.parseLong(properties.getProperty(FILE_CRC + "." + i)); + String index = "." + i; + String path = properties.getProperty(FILE_PATH + index); + long crc = Long.parseLong(properties.getProperty(FILE_CRC + index)); files.add(new NMFPackageFile(path, crc)); } @@ -240,8 +248,15 @@ public boolean isApp() { return true; } - String type = this.getPackageType(); - return TYPE_APP.equals(type); + return TYPE_APP.equals(this.getPackageType()); + } + + public boolean isJava() { + return TYPE_UPDATE_JAVA.equals(this.getPackageType()); + } + + public boolean isDependency() { + return TYPE_DEPENDENCY.equals(this.getPackageType()); } public boolean sameAs(Metadata other) { diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java index 7837bc823..70b0b5638 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/GenerateNMFPackageMojo.java @@ -116,39 +116,16 @@ public enum Privilege { @Override public void execute() throws MojoExecutionException { getLog().info("Generating NMF Package..."); - - String path = Deployment.DIR_APPS + File.separator + name; - NMFPackageBuilder builder = new NMFPackageBuilder(path); - String mainJar = ""; - - try { - File myAppFilename = HelperNMFPackage.findAppJarInFolder(TARGET_FOLDER); - mainJar = myAppFilename.getName(); - builder.addFileOrDirectory(myAppFilename); - - // Add the external libs or files - if (libs != null) { - for (String lib : libs) { - getLog().info(">> lib: " + lib); - builder.addFileOrDirectory(lib, ""); - } - } - } catch (IOException ex) { - String error = "A problem occurred while trying to find the Jar file!"; - Logger.getLogger(GenerateNMFPackageMojo.class.getName()).log( - Level.SEVERE, error, ex); - throw new MojoExecutionException(error, ex); - } getLog().info("\n---------- NMF Package - Generator ----------\n"); getLog().info("Input values:"); getLog().info(">> name = " + name); getLog().info(">> version = " + version); getLog().info(">> mainClass = " + mainClass); - getLog().info(">> mainJar = " + mainJar); getLog().info(">> privilege = " + privilege); getLog().info(">> nmfVersion = " + nmfVersion); getLog().info(">> maxHeap = " + maxHeap); + getLog().info(">> minHeap = " + minHeap); if (mainClass == null) { throw new MojoExecutionException("The mainClass tag is not defined!" @@ -168,7 +145,21 @@ public void execute() throws MojoExecutionException { + " tag!\n"); } - // Now let's take care of the project dependencies + File myAppFilename; + String mainJar; + + try { + myAppFilename = HelperNMFPackage.findAppJarInFolder(TARGET_FOLDER); + mainJar = myAppFilename.getName(); + getLog().info(">> mainJar = " + mainJar); + } catch (IOException ex) { + String error = "A problem occurred while trying to find the Jar file!"; + Logger.getLogger(GenerateNMFPackageMojo.class.getName()).log( + Level.SEVERE, error, ex); + throw new MojoExecutionException(error, ex); + } + + // Let's start by taking care of the project dependencies // They must also be packaged as NMF Packages that will be shared libraries getLog().info("------\nGenerating shared libraries...\n"); ArrayList dependencies = new ArrayList<>(); @@ -198,13 +189,23 @@ public void execute() throws MojoExecutionException { dependencies.add(packageJarDependency(artifact)); } } - - getLog().info("------\nGenerating project NMF Package...\n"); - - // Package + MetadataApp metadata = new MetadataApp(name, version, mainClass, mainJar, maxHeap, minHeap, dependencies); - builder.createPackage(metadata, TARGET_FOLDER); + + NMFPackageBuilder builder = new NMFPackageBuilder(metadata); + builder.addFileOrDirectory(myAppFilename); + + // Add the external libs or files + if (libs != null) { + for (String lib : libs) { + getLog().info(">> lib: " + lib); + builder.addFileOrDirectory(lib, ""); + } + } + + getLog().info("------\nGenerating project NMF Package...\n"); + builder.createPackage(TARGET_FOLDER); } private String packageJarDependency(Artifact artifact) { @@ -212,12 +213,9 @@ private String packageJarDependency(Artifact artifact) { String artifactId = artifact.getArtifactId(); String ver = artifact.getVersion(); MetadataDependency metadata = new MetadataDependency(artifactId, ver); - - NMFPackageBuilder builder = new NMFPackageBuilder(Deployment.DIR_JARS_SHARED); + NMFPackageBuilder builder = new NMFPackageBuilder(metadata); builder.addFileOrDirectory(file); - builder.createPackage(metadata, TARGET_FOLDER); - + builder.createPackage(TARGET_FOLDER); return file.getName(); } - } diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java index 56d8548a6..39528dedf 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java @@ -43,17 +43,31 @@ public class NMFPackageBuilder { private static final int BUFFER = 2048; - final ArrayList inputFiles = new ArrayList<>(); - final ArrayList locations = new ArrayList<>(); - final String appPath; + private final ArrayList inputFiles = new ArrayList<>(); + private final ArrayList locations = new ArrayList<>(); + private final Metadata metadata; + private final String rootPath; /** * The Constructor for the PackageBuilder class. * - * @param folderType The type of folder that the file should be. + * @param metadata The metadata of the package. */ - public NMFPackageBuilder(String folderType) { - this.appPath = folderType + File.separator; + public NMFPackageBuilder(Metadata metadata) { + this.metadata = metadata; + String path = ""; + + if(metadata.isApp()) { + path = Deployment.DIR_APPS + File.separator + metadata.getPackageName(); + } + if(metadata.isJava()) { + path = Deployment.DIR_JAVA; + } + if(metadata.isDependency()) { + path = Deployment.DIR_JARS_SHARED; + } + + this.rootPath = path + File.separator; } /** @@ -73,14 +87,10 @@ public void addFileOrDirectory(String path, String nest) { } } else { inputFiles.add(f.getAbsolutePath()); - locations.add(appPath + nest + f.getName()); + locations.add(rootPath + nest + f.getName()); } } - public void addFileOrDirectory(String path) { - addFileOrDirectory(new File(path)); - } - public void addFileOrDirectory(File file) { addFileOrDirectory(file.getAbsolutePath(), ""); } @@ -89,12 +99,11 @@ public void addFileOrDirectory(File file) { * Creates an NMF Package with the selected metadata in the selected * destination folder. * - * @param metadata The metadata of the NMF Package. * @param destinationFolder The destination folder where to store the NMF * Package. * @return The created NMF Package File. */ - public File createPackage(Metadata metadata, File destinationFolder) { + public File createPackage(File destinationFolder) { String path = destinationFolder.getAbsolutePath(); String out = create(metadata, inputFiles, locations, path); return new File(out); @@ -110,9 +119,9 @@ private static String create(Metadata metadata, ArrayList filesInput, try { String path = newLocations.get(i); long crc = HelperNMFPackage.calculateCRCFromFile(files.get(i)); - //descriptor.addFile(new NMFPackageFile(path, crc)); - metadata.addProperty(Metadata.FILE_PATH + "." + i, path); - metadata.addProperty(Metadata.FILE_CRC + "." + i, String.valueOf(crc)); + String index = "." + i; + metadata.addProperty(Metadata.FILE_PATH + index, path); + metadata.addProperty(Metadata.FILE_CRC + index, String.valueOf(crc)); } catch (IOException ex) { Logger.getLogger(NMFPackageBuilder.class.getName()).log(Level.SEVERE, "There was a problem during the CRC calculation.", ex); diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java index ea4ece30f..eebd6fbfa 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageAppCreation.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.tests; -import esa.mo.nmf.nmfpackage.Deployment; import esa.mo.nmf.nmfpackage.NMFPackageBuilder; import esa.mo.nmf.nmfpackage.metadata.Metadata; import esa.mo.nmf.nmfpackage.metadata.MetadataApp; @@ -51,16 +50,14 @@ public static void createPackage() { Level.INFO, "\n----------- Package 1 Generation -----------\n"); // Package 1 - String myAppFilename = "myApp.filetype"; - String appName = "my-test-app"; - String path = Deployment.DIR_APPS + File.separator + appName; + File myAppFile = new File("myApp.filetype"); - MetadataApp metadata = new MetadataApp(appName, "1.0.0", + MetadataApp metadata = new MetadataApp("my-test-app", "1.0.0", "noclass", "myJarFile.jar", "128m", "16m", null); - NMFPackageBuilder builder = new NMFPackageBuilder(path); - builder.addFileOrDirectory(myAppFilename); - File location = builder.createPackage(metadata, new File("target")); + NMFPackageBuilder builder = new NMFPackageBuilder(metadata); + builder.addFileOrDirectory(myAppFile); + File location = builder.createPackage(new File("target")); try { // Test if the created file can be parsed @@ -75,5 +72,4 @@ public static void createPackage() { Level.SEVERE, "The file could not be processed!", ex); } } - } diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java index ec0d26d22..b21a8ee7f 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/tests/SimpleDemoPackageJavaCreation.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.nmfpackage.tests; -import esa.mo.nmf.nmfpackage.Deployment; import esa.mo.nmf.nmfpackage.NMFPackageBuilder; import esa.mo.nmf.nmfpackage.metadata.MetadataJava; import java.io.BufferedOutputStream; @@ -119,9 +118,9 @@ public static void createJavaPackage(String link) { // Package them MetadataJava metadata = new MetadataJava(downloadedFile.getName(), "1.0"); - NMFPackageBuilder builder = new NMFPackageBuilder(Deployment.DIR_JAVA); + NMFPackageBuilder builder = new NMFPackageBuilder(metadata); builder.addFileOrDirectory(javaDir); - File location = builder.createPackage(metadata, new File("target")); + File location = builder.createPackage(new File("target")); Logger.getLogger(SimpleDemoPackageJavaCreation.class.getName()).log( Level.INFO, "NMF Package in: " + location.getAbsolutePath()); } @@ -146,14 +145,14 @@ public static void createPackages() { // url = new URL("https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jdk_arm_linux_hotspot_8u292b10.tar.gz"); String jdk8 = "https://github.com/adoptium/temurin8-binaries/releases/download/jdk8u352-b08/OpenJDK8U-jdk_arm_linux_hotspot_8u352b08.tar.gz"; - //createJavaPackage(jdk8); + createJavaPackage(jdk8); // Repo here: https://github.com/AdoptOpenJDK/openjdk11-binaries String jdk11 = "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.9.1%2B1/OpenJDK11U-jdk_arm_linux_hotspot_11.0.9.1_1.tar.gz"; - createJavaPackage(jdk11); + //createJavaPackage(jdk11); // Repo here: https://github.com/AdoptOpenJDK/openjdk17-binaries String jdk17 = "https://github.com/AdoptOpenJDK/openjdk17-binaries/releases/download/jdk-2021-05-07-13-31/OpenJDK-debugimage_aarch64_linux_hotspot_2021-05-06-23-30.tar.gz"; - + //createJavaPackage(jdk17); } } From f6ae25e47f962a782e8db57647534b4423dcbd9e Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 23 Nov 2022 10:35:46 +0100 Subject: [PATCH 154/173] Disables the support for a dedicated nmf-apps group from the installation --- .../mo/nmf/nmfpackage/NMFPackageManager.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 5bc7985bd..1c4a3a3da 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -56,6 +56,11 @@ public class NMFPackageManager { // This must match the group_nmf_apps value in the fresh_install.sh file private static final String GROUP_NMF_APPS = "nmf-apps"; + // The groups will be disbled in the current state of the NMF because there + // is no need for it at the moment and it is not supported by the Phi-Sat-2 + // mission on-board computer. This might have to be revised in the future... + private static final boolean GROUP_FLAG = false; + private static final String USER_NMF_ADMIN = "nmf-admin"; private static final String USER_NMF_APP_PREFIX = "app-"; @@ -126,13 +131,15 @@ public void install(final String packageLocation, boolean withGroup = true; LinuxUsersGroups.adduser(username, password, withGroup); - try { // Handle it seperately! - LinuxUsersGroups.addUserToGroup(username, GROUP_NMF_APPS); - } catch (IOException ex) { - Logger.getLogger(NMFPackageManager.class.getName()).log( - Level.INFO, "The User " + username - + " could not be added to the Group: " - + GROUP_NMF_APPS, ex); + if (GROUP_FLAG) { + try { + LinuxUsersGroups.addUserToGroup(username, GROUP_NMF_APPS); + } catch (IOException ex) { + Logger.getLogger(NMFPackageManager.class.getName()).log( + Level.INFO, "The User " + username + + " could not be added to the Group: " + + GROUP_NMF_APPS, ex); + } } // Set the right Group and Permissions to the Home Directory From 241889b2fd59c36060fbef506b418058a4d5ff9f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 23 Nov 2022 11:45:08 +0100 Subject: [PATCH 155/173] Makes the JRE executable & After deliting a file, delete also the parent folder if it is empty --- .../src/main/java/esa/mo/nmf/nmfpackage/Deployment.java | 7 ++++++- .../main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index 49d39fb9b..e8858793b 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -214,11 +214,16 @@ public static String findJREPath(int recommended, int min, int max) { String jre = dir.getAbsolutePath() + File.separator + "bin" + File.separator + "java"; - if (!(new File(jre)).exists()) { + File jreExec = new File(jre); + + if (!jreExec.exists()) { Logger.getLogger(HelperNMFPackage.class.getName()).log( Level.WARNING, "The JRE could not be found in directory: " + path); continue; + } else { + // The file exists, make sure it is executable: + jreExec.setExecutable(true); } if (java_version == recommended) { diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index 1c4a3a3da..da7338b58 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -498,6 +498,12 @@ private static void removeFiles(Metadata metadata) throws IOException { String path = HelperNMFPackage.generateFilePathForSystem(packageFile.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); NMFPackageManager.removeFile(file); + File parent = file.getParentFile(); + + // Delete the parent folder if it is empty after removing the file: + if (parent.isDirectory() && parent.list().length == 0) { + folder.delete(); + } } } From 63ed970fb685768316b3aca4d81f90255e7c55ee Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 23 Nov 2022 13:23:52 +0100 Subject: [PATCH 156/173] Fixes the permissions to make the java JRE executable --- .../src/main/java/esa/mo/nmf/nmfpackage/Deployment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java index e8858793b..4dc4993d2 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/Deployment.java @@ -223,7 +223,7 @@ public static String findJREPath(int recommended, int min, int max) { continue; } else { // The file exists, make sure it is executable: - jreExec.setExecutable(true); + boolean isSet = jreExec.setExecutable(true, false); } if (java_version == recommended) { From 61e5fd4f641098f4f51facaa0b2c814e86423de7 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 23 Nov 2022 13:24:43 +0100 Subject: [PATCH 157/173] Adds a timestamp for the installation/uninstallation/upgrade of NMF Packages --- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 2 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 26 +++++++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 5bb394a24..517ae5267 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -144,7 +144,7 @@ public void verifyPackageIntegrity() throws IOException { */ public void extractFiles(File toFolder) throws IOException { File newFile; - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[8192]; // Iterate through the files, unpack them into the right folders ArrayList files = this.getMetadata().getFiles(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index da7338b58..ddd5cb929 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -89,6 +89,7 @@ public void setAppsLauncher(AppsLauncherProviderServiceImpl appsLauncher) { */ public void install(final String packageLocation, final File nmfDir) throws FileNotFoundException, IOException { + long timestamp = System.currentTimeMillis(); System.out.printf(SEPARATOR); Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Reading the package on: " + packageLocation); @@ -184,8 +185,10 @@ public void install(final String packageLocation, appsLauncher.refresh(); } + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Package successfully installed from: {0}", packageLocation); + "Package successfully installed in " + timestamp + + " ms!\nFrom: " + packageLocation); System.out.printf(SEPARATOR); } @@ -199,6 +202,7 @@ public void install(final String packageLocation, */ public void uninstall(final Metadata packageMetadata, final boolean keepUserData) throws IOException { + long timestamp = System.currentTimeMillis(); System.out.printf(SEPARATOR); String packageName = packageMetadata.getPackageName(); @@ -242,8 +246,10 @@ public void uninstall(final Metadata packageMetadata, appsLauncher.refresh(); } + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Package successfully uninstalled: " + packageName); + "Package successfully uninstalled in " + timestamp + + " ms!\nPackage name: " + packageName); System.out.printf(SEPARATOR); } @@ -256,8 +262,8 @@ public void uninstall(final Metadata packageMetadata, * @throws IOException if the package could not be upgraded */ public void upgrade(final String packageLocation, final File nmfDir) throws IOException { + long timestamp = System.currentTimeMillis(); System.out.printf(SEPARATOR); - Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, "Reading the receipt file that includes the list of files to be upgraded..."); @@ -344,8 +350,10 @@ public void upgrade(final String packageLocation, final File nmfDir) throws IOEx appsLauncher.refresh(); } + timestamp = System.currentTimeMillis() - timestamp; Logger.getLogger(NMFPackageManager.class.getName()).log(Level.INFO, - "Package successfully upgraded from location: " + packageLocation); + "Package successfully upgraded in " + timestamp + + " ms!\nFrom: " + packageLocation); System.out.printf(SEPARATOR); } @@ -461,8 +469,10 @@ private static void removeAuxiliaryFiles(File folder, String appName) throws IOE // Remove the transport.properties // Remove the start_myAppName.sh or start_myAppName.bat NMFPackageManager.removeFile(provider); - NMFPackageManager.removeFile(transport); NMFPackageManager.removeFile(windows.exists() ? windows : linux); + if (transport.exists()) { + NMFPackageManager.removeFile(transport); + } } private static void createAuxiliaryFiles(File appDir, String username) throws IOException { @@ -494,15 +504,15 @@ private static void removeFiles(Metadata metadata) throws IOException { // Do the files actually match the descriptor? for (int i = 0; i < metadata.getFiles().size(); i++) { - NMFPackageFile packageFile = metadata.getFiles().get(i); - String path = HelperNMFPackage.generateFilePathForSystem(packageFile.getPath()); + NMFPackageFile entry = metadata.getFiles().get(i); + String path = HelperNMFPackage.generateFilePathForSystem(entry.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); NMFPackageManager.removeFile(file); File parent = file.getParentFile(); // Delete the parent folder if it is empty after removing the file: if (parent.isDirectory() && parent.list().length == 0) { - folder.delete(); + NMFPackageManager.removeFile(parent); } } } From 5c975926c31167fd313609ee3d3bbfd47aa0ff5e Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 23 Nov 2022 16:37:59 +0100 Subject: [PATCH 158/173] Code cleanup --- .../esa/mo/nmf/nmfpackage/NMFPackage.java | 2 +- .../mo/nmf/nmfpackage/NMFPackageManager.java | 2 +- .../nmfpackage/utils/HelperNMFPackage.java | 2 +- .../mo/nmf/nmfpackage/NMFPackageBuilder.java | 21 +++++++++---------- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java index 517ae5267..db589391e 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackage.java @@ -153,7 +153,7 @@ public void extractFiles(File toFolder) throws IOException { NMFPackageFile file = files.get(i); ZipEntry entry = this.getZipFileEntry(file.getPath()); - String path = HelperNMFPackage.generateFilePathForSystem(entry.getName()); + String path = HelperNMFPackage.sanitizePath(entry.getName()); newFile = new File(toFolder.getCanonicalPath() + File.separator + path); File parent = newFile.getParentFile(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java index ddd5cb929..4073437c5 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageManager.java @@ -505,7 +505,7 @@ private static void removeFiles(Metadata metadata) throws IOException { // Do the files actually match the descriptor? for (int i = 0; i < metadata.getFiles().size(); i++) { NMFPackageFile entry = metadata.getFiles().get(i); - String path = HelperNMFPackage.generateFilePathForSystem(entry.getPath()); + String path = HelperNMFPackage.sanitizePath(entry.getPath()); file = new File(folder.getCanonicalPath() + File.separator + path); NMFPackageManager.removeFile(file); File parent = file.getParentFile(); diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java index 5edf0c43f..d1ed02d83 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/HelperNMFPackage.java @@ -98,7 +98,7 @@ public static File findAppJarInFolder(File folder) throws IOException { throw new IOException("There are too many jars inside the target folder!"); } - public static String generateFilePathForSystem(final String path) throws IOException { + public static String sanitizePath(final String path) throws IOException { // Sanitize the path to prevent a ZipSlip attack: if (path.contains("..")) { throw new IOException("Warning! A ZipSlip attack was detected!"); diff --git a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java index 39528dedf..24b4ad80a 100644 --- a/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java +++ b/core/nmf-package-maven-plugin/src/main/java/esa/mo/nmf/nmfpackage/NMFPackageBuilder.java @@ -56,14 +56,14 @@ public class NMFPackageBuilder { public NMFPackageBuilder(Metadata metadata) { this.metadata = metadata; String path = ""; - - if(metadata.isApp()) { + + if (metadata.isApp()) { path = Deployment.DIR_APPS + File.separator + metadata.getPackageName(); } - if(metadata.isJava()) { + if (metadata.isJava()) { path = Deployment.DIR_JAVA; } - if(metadata.isDependency()) { + if (metadata.isDependency()) { path = Deployment.DIR_JARS_SHARED; } @@ -105,11 +105,10 @@ public void addFileOrDirectory(File file) { */ public File createPackage(File destinationFolder) { String path = destinationFolder.getAbsolutePath(); - String out = create(metadata, inputFiles, locations, path); - return new File(out); + return create(metadata, inputFiles, locations, path); } - private static String create(Metadata metadata, ArrayList filesInput, + private static File create(Metadata metadata, ArrayList filesInput, ArrayList newLocationsInput, String destinationFolder) { final ArrayList files = new ArrayList<>(filesInput); final ArrayList newLocations = new ArrayList<>(newLocationsInput); @@ -127,7 +126,7 @@ private static String create(Metadata metadata, ArrayList filesInput, "There was a problem during the CRC calculation.", ex); } } - + metadata.addProperty(Metadata.FILE_COUNT, String.valueOf(size)); // Generate metadata.properties @@ -135,7 +134,7 @@ private static String create(Metadata metadata, ArrayList filesInput, Level.INFO, "Generating metadata file..."); File metadataFile = new File(Metadata.FILENAME); - + try { metadata.store(metadataFile); // Store the metadata file } catch (IOException ex) { @@ -210,7 +209,7 @@ private static String create(Metadata metadata, ArrayList filesInput, metadataFile.delete(); //digitalSignature.delete(); - return destinationPath; + return new File(destinationPath); } private static void zipFiles(String outputPath, ArrayList from, @@ -242,5 +241,5 @@ private static void zipFiles(String outputPath, ArrayList from, Logger.getLogger(NMFPackageBuilder.class.getName()).log( Level.SEVERE, "The Files could not be zipped!", ex); } - } + } } From 367edc6f2cba858746211461f65979f329962f7b Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 30 Nov 2022 18:28:30 +0100 Subject: [PATCH 159/173] Small code improvements --- .../src/main/java/esa/mo/nmf/NMFProvider.java | 2 +- .../esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java index 4761e35aa..c66b6afa5 100644 --- a/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java +++ b/core/nmf-composites/generic-composite-model/src/main/java/esa/mo/nmf/NMFProvider.java @@ -258,7 +258,7 @@ public CloseAppListener getCloseAppListener() { * Hints the GC to do Garbage Collection and also hints it to go through the * finalization method of the pending finalization objects. */ - public static void hintGC() { + public void hintGC() { System.gc(); System.runFinalization(); } diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index 5e131c5d3..8c0e048ee 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -32,7 +32,6 @@ import esa.mo.nmf.MonitorAndControlNMFAdapter; import esa.mo.nmf.CloseAppListener; import esa.mo.nmf.MCRegistration; -import esa.mo.nmf.MissionPlanningNMFAdapter; import esa.mo.nmf.NMFException; import esa.mo.nmf.OneInstanceLock; import esa.mo.nmf.nmfpackage.Deployment; From c6a68436fe4359e66d1d6abd462f187267a72e2f Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 1 Dec 2022 11:14:24 +0100 Subject: [PATCH 160/173] Improves the doComputerVision error --- .../src/main/resources/xml/ServiceDefPLATFORM.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml index 8473a70cc..ce55fd305 100644 --- a/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml +++ b/core/mo-services-xml/src/main/resources/xml/ServiceDefPLATFORM.xml @@ -2258,8 +2258,11 @@ - + + + + From a8a0c1a3f6a2a0786aa80a371d50cab326e0abbd Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 1 Dec 2022 14:21:10 +0100 Subject: [PATCH 161/173] Better username lookup from the /etc/passwd file --- .../esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java index fdac3df43..64717c826 100644 --- a/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java +++ b/core/nmf-package-lib/src/main/java/esa/mo/nmf/nmfpackage/utils/LinuxUsersGroups.java @@ -230,8 +230,12 @@ public static String findHomeDir(String username) throws IOException { String[] lines = out.split("\\R"); for (String line : lines) { - if (line.contains(username)) { - return line.split(":")[5]; + String[] entries = line.split(":"); + + if (entries.length >= 5) { + if (entries[0].equals(username)) { + return line.split(":")[5]; + } } } From 37a1148bbbf9c60de1463e3f4326b3f43cbba2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Coelho?= Date: Fri, 3 Feb 2023 14:28:07 +0100 Subject: [PATCH 162/173] The supervisor will exit if ran as root user --- .../NanoSatMOSupervisor.java | 379 +++++++++--------- 1 file changed, 196 insertions(+), 183 deletions(-) diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java index 8c0e048ee..e4c4d562a 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/NanoSatMOSupervisor.java @@ -54,74 +54,84 @@ import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; /** - * The implementation of the NanoSat MO Supervisor that can be extended by particular - * implementations. + * The implementation of the NanoSat MO Supervisor that can be extended by + * particular implementations. * * @author Cesar Coelho */ public abstract class NanoSatMOSupervisor extends NMFProvider { - - private static final Logger LOGGER = Logger.getLogger(NanoSatMOSupervisor.class.getName()); - - private final PackageManagementProviderServiceImpl packageManagementService - = new PackageManagementProviderServiceImpl(); - private final AppsLauncherProviderServiceImpl appsLauncherService - = new AppsLauncherProviderServiceImpl(); - private final CommandExecutorProviderServiceImpl commandExecutorService - = new CommandExecutorProviderServiceImpl(); - - /** - * Initializes the NanoSat MO Supervisor. The MonitorAndControlAdapter adapter class can be - * extended for remote monitoring and control with the CCSDS Monitor and Control services. One can - * also extend the SimpleMonitorAndControlAdapter class which contains a simpler interface. - * - * @param mcAdapter The adapter to connect the actions and parameters to the - * corresponding methods and variables of a specific entity. - * @param platformServices The Platform services consumer stubs - * @param packageManagementBackend The Package Management services backend. - */ - public void init(MonitorAndControlNMFAdapter mcAdapter, - PlatformServicesConsumer platformServices, - PMBackend packageManagementBackend) { - super.startTime = System.currentTimeMillis(); - OneInstanceLock lock = new OneInstanceLock(); - HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties - ConnectionProvider.resetURILinks(); - - // Enforce the App Name property to be Const.NANOSAT_MO_SUPERVISOR_NAME - System.setProperty(HelperMisc.PROP_MO_APP_NAME, Const.NANOSAT_MO_SUPERVISOR_NAME); - - // Provider name to be used on the Directory service... - this.providerName = System.getProperty(HelperMisc.PROP_MO_APP_NAME); - - this.platformServices = platformServices; - - try { - Quota stdQuota = new Quota(); - this.comServices.init(); - this.heartbeatService.init(); - this.directoryService.init(comServices); - this.appsLauncherService.init(comServices, directoryService); - this.commandExecutorService.init(comServices); - this.packageManagementService.init(comServices, packageManagementBackend); - this.comServices.initArchiveSync(); - super.reconfigurableServices.add(this.appsLauncherService); - this.appsLauncherService.setStdQuotaPerApp(stdQuota); - this.appsLauncherService.addFolderWithApps(Deployment.getAppsDir()); - this.comServices.getArchiveSyncService().setStdQuota(stdQuota); - this.startMCServices(mcAdapter); - this.initPlatformServices(comServices); - } catch (MALException ex) { - LOGGER.log(Level.SEVERE, - "The services could not be initialized. " - + "Perhaps there's something wrong with the Transport Layer.", ex); - return; - } - - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - //Your 'pos' shutdown code goes here... + + private static final Logger LOGGER = Logger.getLogger(NanoSatMOSupervisor.class.getName()); + + private final PackageManagementProviderServiceImpl packageManagementService + = new PackageManagementProviderServiceImpl(); + private final AppsLauncherProviderServiceImpl appsLauncherService + = new AppsLauncherProviderServiceImpl(); + private final CommandExecutorProviderServiceImpl commandExecutorService + = new CommandExecutorProviderServiceImpl(); + + /** + * Initializes the NanoSat MO Supervisor. The MonitorAndControlAdapter + * adapter class can be extended for remote monitoring and control with the + * CCSDS Monitor and Control services. One can also extend the + * SimpleMonitorAndControlAdapter class which contains a simpler interface. + * + * @param mcAdapter The adapter to connect the actions and parameters to the + * corresponding methods and variables of a specific entity. + * @param platformServices The Platform services consumer stubs + * @param packageManagementBackend The Package Management services backend. + */ + public void init(MonitorAndControlNMFAdapter mcAdapter, + PlatformServicesConsumer platformServices, + PMBackend packageManagementBackend) { + super.startTime = System.currentTimeMillis(); + this.generateStartBanner(); + OneInstanceLock lock = new OneInstanceLock(); + HelperMisc.loadPropertiesFile(); // Loads: provider.properties; settings.properties; transport.properties + ConnectionProvider.resetURILinks(); + + // Check if we are running as root when we have the NMF in Mode 2 + String user = System.getProperties().getProperty("user.name", "?"); + String mode = System.getProperties().getProperty(HelperMisc.PROP_WORK_DIR_STORAGE_MODE, "?"); + + if ("root".equals(user) && mode.equals("2")) { + throw new RuntimeException("Do not run the NanoSat MO Supervisor as root!"); + } + + // Enforce the App Name property to be Const.NANOSAT_MO_SUPERVISOR_NAME + System.setProperty(HelperMisc.PROP_MO_APP_NAME, Const.NANOSAT_MO_SUPERVISOR_NAME); + + // Provider name to be used on the Directory service... + this.providerName = System.getProperty(HelperMisc.PROP_MO_APP_NAME); + + this.platformServices = platformServices; + + try { + Quota stdQuota = new Quota(); + this.comServices.init(); + this.heartbeatService.init(); + this.directoryService.init(comServices); + this.appsLauncherService.init(comServices, directoryService); + this.commandExecutorService.init(comServices); + this.packageManagementService.init(comServices, packageManagementBackend); + this.comServices.initArchiveSync(); + super.reconfigurableServices.add(this.appsLauncherService); + this.appsLauncherService.setStdQuotaPerApp(stdQuota); + this.appsLauncherService.addFolderWithApps(Deployment.getAppsDir()); + this.comServices.getArchiveSyncService().setStdQuota(stdQuota); + this.startMCServices(mcAdapter); + this.initPlatformServices(comServices); + } catch (MALException ex) { + LOGGER.log(Level.SEVERE, + "The services could not be initialized. " + + "Perhaps there's something wrong with the Transport Layer.", ex); + return; + } + + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + //Your 'pos' shutdown code goes here... Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( Level.INFO, "Shutting down Supervisor..."); @@ -132,16 +142,16 @@ public void run() { ListAppResponse response = appsLauncherService.listApp(allApps, new Identifier("*"), null); LongList runningApps = new LongList(); - for(int i = 0; i < response.getBodyElement0().size(); i++) { + for (int i = 0; i < response.getBodyElement0().size(); i++) { Long appId = response.getBodyElement0().get(i); - if(response.getBodyElement1().get(i)){ - runningApps.add(appId); + if (response.getBodyElement1().get(i)) { + runningApps.add(appId); } } Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( - Level.SEVERE, "Stopping " + runningApps.size() + " App(s)!"); - + Level.SEVERE, "Stopping {0} App(s)!", runningApps.size()); + appsLauncherService.stopApp(runningApps, null); } catch (MALInteractionException ex) { Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( @@ -150,29 +160,59 @@ public void run() { Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( Level.SEVERE, "(2) Something went wrong...", ex); } - + Logger.getLogger(NanoSatMOSupervisor.class.getName()).log( Level.INFO, "Done!"); - } - }); - - // Are the dynamic changes enabled? - if ("true".equals(System.getProperty(Const.DYNAMIC_CHANGES_PROPERTY))) { - LOGGER.log(Level.INFO, "Loading previous configurations..."); - - // Activate the previous configuration - final ObjectId confId = new ObjectId(ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, - new ObjectKey(ConfigurationProviderSingleton.getDomain(), - DEFAULT_PROVIDER_CONFIGURATION_OBJID)); - - super.providerConfiguration = new PersistProviderConfiguration(this, confId, - comServices.getArchiveService()); - - try { - super.providerConfiguration.loadPreviousConfigurations(); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } + } + }); + + // Are the dynamic changes enabled? + if ("true".equals(System.getProperty(Const.DYNAMIC_CHANGES_PROPERTY))) { + LOGGER.log(Level.INFO, "Loading previous configurations..."); + + // Activate the previous configuration + final ObjectId confId = new ObjectId(ConfigurationHelper.PROVIDERCONFIGURATION_OBJECT_TYPE, + new ObjectKey(ConfigurationProviderSingleton.getDomain(), + DEFAULT_PROVIDER_CONFIGURATION_OBJID)); + + super.providerConfiguration = new PersistProviderConfiguration(this, confId, + comServices.getArchiveService()); + + try { + super.providerConfiguration.loadPreviousConfigurations(); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + } + + if (mcAdapter != null) { + MCRegistration registration + = new MCRegistration(comServices, mcServices.getParameterService(), + mcServices.getAggregationService(), mcServices.getAlertService(), + mcServices.getActionService()); + mcAdapter.initialRegistrations(registration); + } + + // Populate the Directory service with the entries from the URIs File + LOGGER.log(Level.INFO, "Populating Directory service..."); + directoryService.loadURIs(Const.NANOSAT_MO_SUPERVISOR_NAME); + + String primaryURI + = directoryService.getConnection().getPrimaryConnectionDetails().getProviderURI().toString(); + + SingleConnectionDetails det + = directoryService.getConnection().getSecondaryConnectionDetails(); + String secondaryURI = (det != null) ? det.getProviderURI().toString() : null; + writeCentralDirectoryServiceURI(primaryURI, secondaryURI); + + LOGGER.log(Level.INFO, "NanoSat MO Supervisor initialized in " + + (((float) (System.currentTimeMillis() - super.startTime)) / 1000) + + " seconds!"); + LOGGER.log(Level.INFO, "URI: {0}\n", primaryURI); + } + + public AppsLauncherProviderServiceImpl getAppsLauncherService() { + return appsLauncherService; } @Override @@ -180,102 +220,75 @@ public void setCloseAppListener(final CloseAppListener closeAppAdapter) { this.closeAppAdapter = closeAppAdapter; } - // Populate the Directory service with the entries from the URIs File - LOGGER.log(Level.INFO, "Populating Directory service..."); - directoryService.loadURIs(Const.NANOSAT_MO_SUPERVISOR_NAME); - - String primaryURI - = directoryService.getConnection().getPrimaryConnectionDetails().getProviderURI().toString(); - - SingleConnectionDetails det - = directoryService.getConnection().getSecondaryConnectionDetails(); - String secondaryURI = (det != null) ? det.getProviderURI().toString() : null; - writeCentralDirectoryServiceURI(primaryURI, secondaryURI); - - LOGGER.log(Level.INFO, "NanoSat MO Supervisor initialized in " - + (((float) (System.currentTimeMillis() - super.startTime)) / 1000) - + " seconds!"); - LOGGER.log(Level.INFO, "URI: {0}\n", primaryURI); - } - - public AppsLauncherProviderServiceImpl getAppsLauncherService() { - return appsLauncherService; - } - - @Override - public void setCloseAppListener(final CloseAppListener closeAppAdapter) { - this.closeAppAdapter = closeAppAdapter; - } - - /** - * It closes the App gracefully. - * - * @param source The source of the triggering. Can be null - */ - @Override - public final void closeGracefully(final ObjectId source) { - try { - AppShutdownGuard.start(); - long timestamp = System.currentTimeMillis(); - - // Acknowledge the reception of the request to close (Closing...) - Long eventId = this.getCOMServices().getEventService().generateAndStoreEvent( - AppsLauncherHelper.STOPPING_OBJECT_TYPE, - ConfigurationProviderSingleton.getDomain(), - null, - null, - source, - null); - - final URI uri - = this.getCOMServices().getEventService().getConnectionProvider().getConnectionDetails().getProviderURI(); - - try { - this.getCOMServices().getEventService().publishEvent(uri, eventId, - AppsLauncherHelper.STOPPING_OBJECT_TYPE, null, source, null); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - - // Close the app... - // Make a call on the app layer to close nicely... - if (this.closeAppAdapter != null) { - LOGGER.log(Level.INFO, - "Triggering the closeAppAdapter of the app business logic..."); - this.closeAppAdapter.onClose(); // Time to sleep, boy! - } - - Long eventId2 = this.getCOMServices().getEventService().generateAndStoreEvent( - AppsLauncherHelper.STOPPED_OBJECT_TYPE, - ConfigurationProviderSingleton.getDomain(), - null, - null, - source, - null); - - try { - this.getCOMServices().getEventService().publishEvent(uri, eventId2, - AppsLauncherHelper.STOPPED_OBJECT_TYPE, null, source, null); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - - // Should close them safely as well... + /** + * It closes the App gracefully. + * + * @param source The source of the triggering. Can be null + */ + @Override + public final void closeGracefully(final ObjectId source) { + try { + AppShutdownGuard.start(); + long timestamp = System.currentTimeMillis(); + + // Acknowledge the reception of the request to close (Closing...) + Long eventId = this.getCOMServices().getEventService().generateAndStoreEvent( + AppsLauncherHelper.STOPPING_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + null, + null, + source, + null); + + final URI uri + = this.getCOMServices().getEventService().getConnectionProvider().getConnectionDetails().getProviderURI(); + + try { + this.getCOMServices().getEventService().publishEvent(uri, eventId, + AppsLauncherHelper.STOPPING_OBJECT_TYPE, null, source, null); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + + // Close the app... + // Make a call on the app layer to close nicely... + if (this.closeAppAdapter != null) { + LOGGER.log(Level.INFO, + "Triggering the closeAppAdapter of the app business logic..."); + this.closeAppAdapter.onClose(); // Time to sleep, boy! + } + + Long eventId2 = this.getCOMServices().getEventService().generateAndStoreEvent( + AppsLauncherHelper.STOPPED_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + null, + null, + source, + null); + + try { + this.getCOMServices().getEventService().publishEvent(uri, eventId2, + AppsLauncherHelper.STOPPED_OBJECT_TYPE, null, source, null); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + + // Should close them safely as well... // provider.getMCServices().closeServices(); // provider.getCOMServices().closeServices(); - this.getCOMServices().closeAll(); - - // Exit the Java application - long duration = System.currentTimeMillis() - timestamp; - LOGGER.log(Level.INFO, - "Success! The currently running Java Virtual Machine will now terminate. " - + "(NanoSat MO Supervisor closed in: " + duration + " ms)\n"); - } catch (NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } + this.getCOMServices().closeAll(); - System.exit(0); - } + // Exit the Java application + long duration = System.currentTimeMillis() - timestamp; + LOGGER.log(Level.INFO, + "Success! The currently running Java Virtual Machine will now terminate. " + + "(NanoSat MO Supervisor closed in: " + duration + " ms)\n"); + } catch (NMFException ex) { + LOGGER.log(Level.SEVERE, null, ex); + } + + System.exit(0); + } public abstract void initPlatformServices(COMServicesProvider comServices); From 6115fde20d82457a8fcb294a02b18847da48fd44 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 23 Feb 2023 16:26:05 +0100 Subject: [PATCH 163/173] Updates on the code to fix the auto rebasing mistakes --- .../mo/helpertools/helpers/HelperMisc.java | 453 +++++------ .../DirectoryProviderServiceImpl.java | 352 ++++----- .../provider/gen/GPSProviderServiceImpl.java | 712 +++++++----------- .../parameter/OBSWParameterManager.java | 124 +-- .../commonmoadapter/CommonMOAdapterImpl.java | 377 +++------- .../util/PlatformServicesProviderSoftSim.java | 206 ++--- parent/pom.xml | 2 +- .../CameraAcquisitorSystemCameraHandler.java | 190 +++-- ...raAcquisitorSystemCameraTargetHandler.java | 73 +- .../esa/mo/nmf/apps/MCSnapNMFAdapter.java | 115 +-- .../nmf/apps/PayloadsTestActionsHandler.java | 120 ++- .../DirectoryConnectionConsumerPanel.java | 456 +++++------ 12 files changed, 1386 insertions(+), 1794 deletions(-) diff --git a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java index 05ff35de2..c9172e417 100644 --- a/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java +++ b/core/helper-tools/src/main/java/esa/mo/helpertools/helpers/HelperMisc.java @@ -48,172 +48,94 @@ */ public class HelperMisc { - private static final Set LOADED_PROPERTIES = new TreeSet(); - - public static final String TRANSPORT_PROPERTIES_FILE = "transport.properties"; - public static final String PROVIDER_PROPERTIES_FILE = "provider.properties"; - public static final String CONSUMER_PROPERTIES_FILE = "consumer.properties"; - public static final String SHARED_BROKER_PROPERTIES = "sharedBroker.properties"; - public static final String SHARED_BROKER_URI = "sharedBrokerURI.properties"; - public static final String PROVIDER_URIS_PROPERTIES_FILENAME = "providerURIs.properties"; - public static final String PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME = "providerURIsSecondary.properties"; - public static final String PROPERTY_SHARED_BROKER_URI = "esa.mo.helpertools.connections.SharedBrokerURI"; - - // These are used by the Apps Launcher service - public final static String APP_VERSION = "helpertools.configurations.provider.app.version"; - public final static String APP_CATEGORY = "helpertools.configurations.provider.app.category"; - public final static String APP_COPYRIGHT = "helpertools.configurations.provider.app.copyright"; - public final static String APP_DESCRIPTION = "helpertools.configurations.provider.app.description"; - public final static String APP_USER = "helpertools.configurations.provider.app.user"; - - public static final String PROP_MO_APP_NAME = "helpertools.configurations.MOappName"; - public static final String PROP_DOMAIN = "helpertools.configurations.provider.Domain"; - public static final String PROP_NETWORK = "helpertools.configurations.Network"; - public static final String PROP_WORK_DIR_STORAGE_MODE = "helpertools.configurations.workdirstorage"; - - // Fine-tunning Network properties (only works if the NETWORK is not set) - public static final String PROP_ORGANIZATION_NAME = "helpertools.configurations.OrganizationName"; - public static final String PROP_MISSION_NAME = "helpertools.configurations.MissionName"; - public static final String PROP_NETWORK_ZONE = "helpertools.configurations.NetworkZone"; - public static final String PROP_DEVICE_NAME = "helpertools.configurations.DeviceName"; - - public static final String PROP_GPS_POLL_RATE_MS = "helpertools.configurations.gpspollrate"; - public static final String PROP_GPS_POLLING_ACTIVE = "helpertools.configurations.pollgps"; - - private static final String PROP_TRANSPORT_ID = "helpertools.configurations.provider.transportfilepath"; - private static final String SETTINGS_PROPERTY = "esa.mo.nanosatmoframework.provider.settings"; - public static final String SECONDARY_PROTOCOL = "org.ccsds.moims.mo.mal.transport.secondary.protocol"; - public static final String PROP_PROVIDERURIS_PATH = "helpertools.configurations.provider.providerurispath"; - public static final String PROP_PROVIDERURIS_SEC_PATH = "helpertools.configurations.provider.providerurispathsecondary"; - - public static final String PROPERTY_APID_QUALIFIER = "org.ccsds.moims.mo.malspp.apidQualifier"; - public static final String PROPERTY_APID = "org.ccsds.moims.mo.malspp.apid"; - - public static final String PROP_INIT_URI_FILES = "helpertools.initurifiles"; - - public static final Identifier SESSION_NAME = new Identifier("LIVE"); - - /** - * Clears the list of loaded property files. - */ - public static void clearLoadedPropertiesList() { - LOADED_PROPERTIES.clear(); - } - - /** - * Loads in a property file and optionally searches for a contained property - * that contains the next file to load. - * - * @param configFile The name of the property file to load. May be null, in - * which case nothing is loaded. - * @param chainProperty The property name that contains the name of the next - * file to load. - * @return The loaded properties or an empty list if no file loaded. - */ - private static Properties loadProperties(final String configFile, final String chainProperty) { - Properties topProps = new Properties(); - - if (null != configFile) { - topProps = loadProperties(ClassLoader.getSystemClassLoader().getResource(configFile), - chainProperty); + private static final Set LOADED_PROPERTIES = new TreeSet(); + + public static final String TRANSPORT_PROPERTIES_FILE = "transport.properties"; + public static final String PROVIDER_PROPERTIES_FILE = "provider.properties"; + public static final String CONSUMER_PROPERTIES_FILE = "consumer.properties"; + public static final String SHARED_BROKER_PROPERTIES = "sharedBroker.properties"; + public static final String SHARED_BROKER_URI = "sharedBrokerURI.properties"; + public static final String PROVIDER_URIS_PROPERTIES_FILENAME = "providerURIs.properties"; + public static final String PROVIDER_URIS_SECONDARY_PROPERTIES_FILENAME = "providerURIsSecondary.properties"; + public static final String PROPERTY_SHARED_BROKER_URI = "esa.mo.helpertools.connections.SharedBrokerURI"; + + // These are used by the Apps Launcher service + public final static String APP_VERSION = "helpertools.configurations.provider.app.version"; + public final static String APP_CATEGORY = "helpertools.configurations.provider.app.category"; + public final static String APP_COPYRIGHT = "helpertools.configurations.provider.app.copyright"; + public final static String APP_DESCRIPTION = "helpertools.configurations.provider.app.description"; + public final static String APP_USER = "helpertools.configurations.provider.app.user"; + + public static final String PROP_MO_APP_NAME = "helpertools.configurations.MOappName"; + public static final String PROP_DOMAIN = "helpertools.configurations.provider.Domain"; + public static final String PROP_NETWORK = "helpertools.configurations.Network"; + public static final String PROP_WORK_DIR_STORAGE_MODE = "helpertools.configurations.workdirstorage"; + + // Fine-tunning Network properties (only works if the NETWORK is not set) + public static final String PROP_ORGANIZATION_NAME = "helpertools.configurations.OrganizationName"; + public static final String PROP_MISSION_NAME = "helpertools.configurations.MissionName"; + public static final String PROP_NETWORK_ZONE = "helpertools.configurations.NetworkZone"; + public static final String PROP_DEVICE_NAME = "helpertools.configurations.DeviceName"; + + public static final String PROP_GPS_POLL_RATE_MS = "helpertools.configurations.gpspollrate"; + public static final String PROP_GPS_POLLING_ACTIVE = "helpertools.configurations.pollgps"; + + private static final String PROP_TRANSPORT_ID = "helpertools.configurations.provider.transportfilepath"; + private static final String SETTINGS_PROPERTY = "esa.mo.nanosatmoframework.provider.settings"; + public static final String SECONDARY_PROTOCOL = "org.ccsds.moims.mo.mal.transport.secondary.protocol"; + public static final String PROP_PROVIDERURIS_PATH = "helpertools.configurations.provider.providerurispath"; + public static final String PROP_PROVIDERURIS_SEC_PATH = "helpertools.configurations.provider.providerurispathsecondary"; + + public static final String PROPERTY_APID_QUALIFIER = "org.ccsds.moims.mo.malspp.apidQualifier"; + public static final String PROPERTY_APID = "org.ccsds.moims.mo.malspp.apid"; + + public static final String PROP_INIT_URI_FILES = "helpertools.initurifiles"; + + public static final Identifier SESSION_NAME = new Identifier("LIVE"); + + /** + * Clears the list of loaded property files. + */ + public static void clearLoadedPropertiesList() { + LOADED_PROPERTIES.clear(); } /** * Loads in a property file and optionally searches for a contained property * that contains the next file to load. * - * @param configFile The name of the property file to load. May be null, in - * which case nothing is loaded. + * @param configFile The name of the property file to load. May be null, in + * which case nothing is loaded. * @param chainProperty The property name that contains the name of the next - * file to load. + * file to load. * @return The loaded properties or an empty list if no file loaded. */ private static Properties loadProperties(final String configFile, final String chainProperty) { Properties topProps = new Properties(); if (null != configFile) { - topProps = loadProperties(ClassLoader.getSystemClassLoader().getResource(configFile), chainProperty); + topProps = loadProperties(ClassLoader.getSystemClassLoader().getResource(configFile), + chainProperty); } - System.setProperties(sysProps); - } - - /** - * Loads in a property file and optionally searches for a contained property - * that contains the next file to load. - * - * @param url The URL of the property file to load. May be null, in - * which case nothing is loaded. - * @param chainProperty The property name that contains the name of the next - * file to load. - * @return The loaded properties or an empty list if no file loaded. - * @throws java.lang.IllegalArgumentException If chainProperty == null. - */ - public static Properties loadProperties(final java.net.URL url, final String chainProperty) - throws IllegalArgumentException { - final Properties topProps = new Properties(); - if (chainProperty == null) { - throw new IllegalArgumentException( - "ChainProperty must not be null. " - + "Provide an empty String if you do not want to provide a chainProperty."); + return topProps; } /** * Loads the properties for the consumer * * @throws java.net.MalformedURLException - * @throws IOException The file consumer properties file does - * no exist + * @throws IOException The file consumer properties file does no exist */ public static void loadConsumerProperties() throws MalformedURLException, IOException { final Properties sysProps = System.getProperties(); final File file = new File(System.getProperty("consumer.properties", CONSUMER_PROPERTIES_FILE)); - return topProps; - } - - /** - * Loads in a property file. - * - * @param path The path of the property file to load. - * @return The loaded properties or an empty list if no file loaded. - * @throws IOException The file could not be loaded. - * @throws IllegalArgumentException If path == null - */ - public static Properties loadProperties(final String path) - throws IOException, IllegalArgumentException { - if (path == null) { - throw new IllegalArgumentException("Filepath must not be null."); - } - final File file = new File(path); - final FileInputStream inputStream = new FileInputStream(file); - final Properties ret = new Properties(); - ret.load(inputStream); - inputStream.close(); - return ret; - } - - /** - * Loads the provider properties file - */ - public static void loadPropertiesFile() { - HelperMisc.loadPropertiesFile(false); - } - - /** - * Loads the provider properties file and the properties for the shared broker - * - * @param useSharedBroker Flag that determines if the properties in the - * SHARED_BROKER_PROPERTIES file will be read - */ - public static void loadPropertiesFile(Boolean useSharedBroker) { - // Were they loaded already? - String propAreLoaded = System.getProperty("PropertiesLoadedFlag"); - if (propAreLoaded != null) { - if (System.getProperty("PropertiesLoadedFlag").equals("true")) { - return; - } - } + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "consumer.properties")); + } else { + throw new IOException("The file " + file.getName() + " does not exist."); + } System.setProperties(sysProps); } @@ -222,42 +144,60 @@ public static void loadPropertiesFile(Boolean useSharedBroker) { * Loads in a property file and optionally searches for a contained property * that contains the next file to load. * - * @param url The URL of the property file to load. May be null, in - * which case nothing is loaded. + * @param url The URL of the property file to load. May be null, in which + * case nothing is loaded. * @param chainProperty The property name that contains the name of the next - * file to load. + * file to load. * @return The loaded properties or an empty list if no file loaded. * @throws java.lang.IllegalArgumentException If chainProperty == null. */ public static Properties loadProperties(final java.net.URL url, final String chainProperty) - throws IllegalArgumentException { + throws IllegalArgumentException { final Properties topProps = new Properties(); if (chainProperty == null) { throw new IllegalArgumentException( - "ChainProperty must not be null. Provide an empty String if you do not want to provide a chainProperty."); + "ChainProperty must not be null. " + + "Provide an empty String if you do not want to provide a chainProperty."); } - if (providerFile != null) { - file = new File(providerFile); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "provider.properties")); - } else { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, - "The file provider.properties does not exist on the path: {0}\n" - + "Is the application working directory configured properly?", providerFile); + if (null != url) { + try { + final Properties myProps = new Properties(); + InputStream stream = url.openStream(); + myProps.load(stream); + stream.close(); + + final Properties subProps = loadProperties(myProps.getProperty(chainProperty), chainProperty); + + String loadingString = (LOADED_PROPERTIES.contains(url.toString())) + ? "Reloading properties " + url.toString() + : "Loading properties " + url.toString(); + + Logger.getLogger(HelperMisc.class.getName()).log(Level.INFO, loadingString); + topProps.putAll(subProps); + topProps.putAll(myProps); + LOADED_PROPERTIES.add(url.toString()); + } catch (IOException ex) { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "Failed to load properties " + url, ex); + } } return topProps; } - if (settingsFile != null) { - file = new File(settingsFile); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "settings.properties")); - } else { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, - "The file settings.properties does not exist on the path: {0}\n" - + "Is the application working directory configured properly?", settingsFile); + /** + * Loads in a property file. + * + * @param path The path of the property file to load. + * @return The loaded properties or an empty list if no file loaded. + * @throws IOException The file could not be loaded. + * @throws IllegalArgumentException If path == null + */ + public static Properties loadProperties(final String path) + throws IOException, IllegalArgumentException { + if (path == null) { + throw new IllegalArgumentException("Filepath must not be null."); } final File file = new File(path); final FileInputStream inputStream = new FileInputStream(file); @@ -275,13 +215,13 @@ public static void loadPropertiesFile() { } /** - * Loads the provider properties file and the properties for the shared broker + * Loads the provider properties file and the properties for the shared + * broker. * * @param useSharedBroker Flag that determines if the properties in the - * SHARED_BROKER_PROPERTIES file will be read + * SHARED_BROKER_PROPERTIES file will be read */ public static void loadPropertiesFile(Boolean useSharedBroker) { - // Were they loaded already? String propAreLoaded = System.getProperty("PropertiesLoadedFlag"); if (propAreLoaded != null) { @@ -290,15 +230,73 @@ public static void loadPropertiesFile(Boolean useSharedBroker) { } } - file = new File(System.getProperty("transport.properties", transport_file_path)); - if (file.exists()) { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "transport.properties")); - } else { - Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, - "The file transport.properties does not exist on the path: {0}\n" - + "The App will fallback to the default TCP/IP Transport!", transport_file_path); - sysProps.putAll(getTransportDefaults()); - } + try { + final java.util.Properties sysProps = System.getProperties(); + + File file; + final String providerFile = System.getProperty("provider.properties", PROVIDER_PROPERTIES_FILE); + + if (providerFile != null) { + file = new File(providerFile); + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "provider.properties")); + } else { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "The file provider.properties does not exist on the path: {0}\n" + + "Is the application working directory configured properly?", providerFile); + } + } + + final String settingsFile = System.getProperty(SETTINGS_PROPERTY, "settings.properties"); + + if (settingsFile != null) { + file = new File(settingsFile); + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "settings.properties")); + } else { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "The file settings.properties does not exist on the path: {0}\n" + + "Is the application working directory configured properly?", settingsFile); + } + } + + String transport_file_path = TRANSPORT_PROPERTIES_FILE; + String trans_path_prop = System.getProperty(PROP_TRANSPORT_ID); + + if (trans_path_prop != null) { + transport_file_path = trans_path_prop; + } + + file = new File(System.getProperty("transport.properties", transport_file_path)); + if (file.exists()) { + sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), "transport.properties")); + } else { + Logger.getLogger(HelperMisc.class.getName()).log(Level.WARNING, + "The file transport.properties does not exist on the path: {0}\n" + + "The App will fallback to the default TCP/IP Transport!", transport_file_path); + sysProps.putAll(getTransportDefaults()); + } + + if (useSharedBroker) { + file = new File(System.getProperty("sharedBroker.properties", SHARED_BROKER_PROPERTIES)); + if (file.exists()) { + sysProps + .putAll(HelperMisc.loadProperties(file.toURI().toURL(), "sharedBroker.properties")); + } + + file = new File(System.getProperty("sharedBrokerURI.properties", SHARED_BROKER_URI)); + if (file.exists()) { + sysProps.putAll( + HelperMisc.loadProperties(file.toURI().toURL(), "sharedBrokerURI.properties")); + } + } + + System.setProperties(sysProps); + System.setProperty("PropertiesLoadedFlag", "true"); + + } catch (MalformedURLException ex) { + Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); + } } @@ -308,7 +306,8 @@ public static void loadPropertiesFile(Boolean useSharedBroker) { * @param propertiesFileName The name of the property file to load. * @throws java.lang.IllegalArgumentException If propertiesFileName == null */ - public static void loadThisPropertiesFile(final String propertiesFileName) throws IllegalArgumentException { + public static void loadThisPropertiesFile(final String propertiesFileName) + throws IllegalArgumentException { if (propertiesFileName == null) { throw new IllegalArgumentException("propertiesFileName must not be null."); } @@ -322,51 +321,17 @@ public static void loadThisPropertiesFile(final String propertiesFileName) throw Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); } } - } - - System.setProperties(sysProps); - System.setProperty("PropertiesLoadedFlag", "true"); - } catch (MalformedURLException ex) { - Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); - } - - } - - /** - * Loads in the properties of a file. - * - * @param propertiesFileName The name of the property file to load. - * @throws java.lang.IllegalArgumentException If propertiesFileName == null - */ - public static void loadThisPropertiesFile(final String propertiesFileName) - throws IllegalArgumentException { - if (propertiesFileName == null) { - throw new IllegalArgumentException("propertiesFileName must not be null."); - } - final java.util.Properties sysProps = System.getProperties(); - - File file = new File(propertiesFileName); - if (file.exists()) { - try { - sysProps.putAll(HelperMisc.loadProperties(file.toURI().toURL(), PROVIDER_PROPERTIES_FILE)); - } catch (MalformedURLException ex) { - Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, null, ex); - } + System.setProperties(sysProps); } - System.setProperties(sysProps); - } - - private static Properties getTransportDefaults(){ - Properties props = new Properties(); - props.setProperty("org.ccsds.moims.mo.mal.transport.default.protocol", "maltcp://"); - props.setProperty("org.ccsds.moims.mo.mal.transport.protocol.maltcp", "esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl"); - props.setProperty("org.ccsds.moims.mo.mal.encoding.protocol.maltcp", "esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory"); - props.setProperty("org.ccsds.moims.mo.mal.transport.tcpip.autohost", "true"); - return props; - } - + private static Properties getTransportDefaults() { + Properties props = new Properties(); + props.setProperty("org.ccsds.moims.mo.mal.transport.default.protocol", "maltcp://"); + props.setProperty("org.ccsds.moims.mo.mal.transport.protocol.maltcp", "esa.mo.mal.transport.tcpip.TCPIPTransportFactoryImpl"); + props.setProperty("org.ccsds.moims.mo.mal.encoding.protocol.maltcp", "esa.mo.mal.encoder.binary.fixed.FixedBinaryStreamFactory"); + props.setProperty("org.ccsds.moims.mo.mal.transport.tcpip.autohost", "true"); + return props; } /** @@ -396,13 +361,15 @@ public static boolean isStringAttribute(Attribute obj) throws IllegalArgumentExc } /** - * Generates a corresponding, empty MAL Element List from a certain MAL Element + * Generates a corresponding, empty MAL Element List from a certain MAL + * Element * * @param obj The MAL Element * @return The MAL Element List * @throws org.ccsds.moims.mo.mal.MALException */ - public static ElementList element2elementList(Object obj) throws IllegalArgumentException, MALException { + public static ElementList element2elementList(Object obj) + throws IllegalArgumentException, MALException { if (obj == null) { return null; } @@ -415,9 +382,10 @@ public static ElementList element2elementList(Object obj) throws IllegalArgument if (eleFact == null) { Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, - "The element could not be found in the MAL ElementFactory! The object type is: ''{0}''." + - " Maybe the service Helper for this object was not initialized." + - " Try initializing the Service Helper of this object.", obj.getClass().getSimpleName()); + "The element could not be found in the MAL ElementFactory! The object type is: ''{0}''." + + " Maybe the service Helper for this object was not initialized." + + " Try initializing the Service Helper of this object.", + obj.getClass().getSimpleName()); throw new MALException("Cannot instantiate a list of " + obj.getClass().getSimpleName()); } return (ElementList) eleFact.createElement(); @@ -428,7 +396,8 @@ public static ElementList element2elementList(Object obj) throws IllegalArgument } /** - * Generates the corresponding, empty MAL Element from a certain MAL Element List + * Generates the corresponding, empty MAL Element from a certain MAL Element + * List * * @param obj The MAL Element List * @return The MAL Element @@ -445,28 +414,23 @@ public static Element elementList2element(ElementList obj) throws Exception { if (eleFact == null) { Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, - "The element could not be found in the MAL ElementFactory! The object type is: ''{0}''. Maybe the service Helper for this object was not initialized. Try initializing the Service Helper of this object.", - obj.getClass().getSimpleName()); + "The element could not be found in the MAL ElementFactory! " + + "The object type is: ''{0}''. " + + "Maybe the service Helper for this object was not initialized. " + + "Try initializing the Service Helper of this object.", + obj.getClass().getSimpleName()); } - if (eleFact == null) { - Logger.getLogger(HelperMisc.class.getName()).log(Level.SEVERE, - "The element could not be found in the MAL ElementFactory! " - + "The object type is: ''{0}''. " - + "Maybe the service Helper for this object was not initialized. " - + "Try initializing the Service Helper of this object.", - obj.getClass().getSimpleName()); - } - + return (Element) eleFact.createElement(); } /** - * Generates the domain field in an IdentifierList from a String separated by - * dots + * Generates the domain field in an IdentifierList from a String separated + * by dots * * @param domainId The domain Id - * @return The domain as IdentifierList or an empty IdentifierList if domainId - * == null OR domainId.isEmpty + * @return The domain as IdentifierList or an empty IdentifierList if + * domainId == null OR domainId.isEmpty */ public static IdentifierList domainId2domain(String domainId) { if (domainId == null || domainId.isEmpty()) { @@ -507,26 +471,27 @@ public static String domain2domainId(final IdentifierList domain) { /** * Finds the service name from the area, areaVersion and service numbers * - * @param area Area of the service + * @param area Area of the service * @param areaVersion Area version of the service - * @param service Service number + * @param service Service number * @return The name of the service * @throws org.ccsds.moims.mo.mal.MALException The area/service is Unknown */ public static String serviceKey2name(UShort area, UOctet areaVersion, UShort service) throws MALException { - MALArea malArea = MALContextFactory.lookupArea(area, areaVersion); if (malArea == null) { - throw new MALException("(" + area.getValue() + "," + areaVersion.getValue() + "," + service.getValue() + - ") " + "Unknown area to the MAL! Maybe the API was not initialized."); + throw new MALException("(" + area.getValue() + "," + + areaVersion.getValue() + "," + service.getValue() + ") " + + "Unknown area to the MAL! Maybe the API was not initialized."); } MALService malSer = malArea.getServiceByNumber(service); if (malSer == null) { - throw new MALException("(" + area.getValue() + "," + areaVersion.getValue() + "," + service.getValue() + - ") " + "Unknown service to the MAL! Maybe the API was not initialized."); + throw new MALException("(" + area.getValue() + "," + + areaVersion.getValue() + "," + service.getValue() + ") " + + "Unknown service to the MAL! Maybe the API was not initialized."); } return malSer.getName().toString(); diff --git a/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java b/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java index 809027e47..1eba740bb 100644 --- a/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java +++ b/core/mo-services-impl/ccsds-common-impl/src/main/java/esa/mo/common/impl/provider/DirectoryProviderServiceImpl.java @@ -76,84 +76,31 @@ /** * Directory service Provider. */ -public class DirectoryProviderServiceImpl extends DirectoryInheritanceSkeleton -{ - - public static final String CHAR_S2G = "s2g"; - private static final Logger LOGGER - = Logger.getLogger(DirectoryProviderServiceImpl.class.getName()); - - private MALProvider directoryServiceProvider; - private boolean initialiased = false; - private boolean running = false; - private final ConnectionProvider connection = new ConnectionProvider(); - protected final Map providersAvailable - = new ConcurrentHashMap<>(); - protected final Object MUTEX = new Object(); - private COMServicesProvider comServices; - - /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread - * - * @param comServices - * @throws MALException On initialisation error. - */ - public synchronized void init(COMServicesProvider comServices) throws MALException - { - long timestamp = System.currentTimeMillis(); - - if (!initialiased) { - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, COMHelper.COM_AREA_VERSION) == null) { - COMHelper.deepInit(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, - CommonHelper.COMMON_AREA_VERSION) == null) { - CommonHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) - .getServiceByName(DirectoryHelper.DIRECTORY_SERVICE_NAME) == null) { - DirectoryHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - } +public class DirectoryProviderServiceImpl extends DirectoryInheritanceSkeleton { - return null; // Not found! - } + public static final String CHAR_S2G = "s2g"; + private static final Logger LOGGER + = Logger.getLogger(DirectoryProviderServiceImpl.class.getName()); - public static ServiceKey generateServiceKey(final IntegerList keys) { - return new ServiceKey(new UShort(keys.get(0)), new UShort(keys.get(1)), new UOctet(keys.get(2).shortValue())); - } + private MALProvider directoryServiceProvider; + private boolean initialiased = false; + private boolean running = false; + private final ConnectionProvider connection = new ConnectionProvider(); + protected final Map providersAvailable + = new ConcurrentHashMap<>(); + protected final Object MUTEX = new Object(); + private COMServicesProvider comServices; - directoryServiceProvider = connection.startService( - DirectoryHelper.DIRECTORY_SERVICE_NAME.toString(), - DirectoryHelper.DIRECTORY_SERVICE, false, this); - - running = true; - initialiased = true; - timestamp = System.currentTimeMillis() - timestamp; - LOGGER.info("Directory service: READY! (" + timestamp + " ms)"); - } - - @Override - public ProviderSummaryList lookupProvider(final ServiceFilter filter, - final MALInteraction interaction) throws MALInteractionException, MALException - { - if (null == filter) { // Is the input null? - throw new IllegalArgumentException("filter argument must not be null"); - } - */ /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread * * @param comServices * @throws MALException On initialisation error. */ public synchronized void init(COMServicesProvider comServices) throws MALException { + long timestamp = System.currentTimeMillis(); + if (!initialiased) { if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, MALHelper.MAL_AREA_VERSION) == null) { MALHelper.init(MALContextFactory.getElementFactoryRegistry()); @@ -163,12 +110,13 @@ public synchronized void init(COMServicesProvider comServices) throws MALExcepti COMHelper.deepInit(MALContextFactory.getElementFactoryRegistry()); } - if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) == null) { + if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, + CommonHelper.COMMON_AREA_VERSION) == null) { CommonHelper.init(MALContextFactory.getElementFactoryRegistry()); } if (MALContextFactory.lookupArea(CommonHelper.COMMON_AREA_NAME, CommonHelper.COMMON_AREA_VERSION) - .getServiceByName(DirectoryHelper.DIRECTORY_SERVICE_NAME) == null) { + .getServiceByName(DirectoryHelper.DIRECTORY_SERVICE_NAME) == null) { DirectoryHelper.init(MALContextFactory.getElementFactoryRegistry()); } } @@ -180,38 +128,19 @@ public synchronized void init(COMServicesProvider comServices) throws MALExcepti connection.closeAll(); } - directoryServiceProvider = connection.startService(DirectoryHelper.DIRECTORY_SERVICE_NAME.toString(), - DirectoryHelper.DIRECTORY_SERVICE, false, this); + directoryServiceProvider = connection.startService( + DirectoryHelper.DIRECTORY_SERVICE_NAME.toString(), + DirectoryHelper.DIRECTORY_SERVICE, false, this); running = true; initialiased = true; - LOGGER.info("Directory service READY"); - - } - - /** - * Closes all running threads and releases the MAL resources. - */ - public void close() { - try { - if (null != directoryServiceProvider) { - directoryServiceProvider.close(); - } - - connection.closeAll(); - running = false; - } catch (MALException ex) { - LOGGER.log(Level.WARNING, "Exception during close down of the provider {0}", ex); - } - } - - public ConnectionProvider getConnection() { - return this.connection; + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("Directory service: READY! (" + timestamp + " ms)"); } @Override - public ProviderSummaryList lookupProvider(final ServiceFilter filter, final MALInteraction interaction) - throws MALInteractionException, MALException { + public ProviderSummaryList lookupProvider(final ServiceFilter filter, + final MALInteraction interaction) throws MALInteractionException, MALException { if (null == filter) { // Is the input null? throw new IllegalArgumentException("filter argument must not be null"); } @@ -272,8 +201,9 @@ public ProviderSummaryList lookupProvider(final ServiceFilter filter, final MALI // Check session name if (!filter.getSessionName().toString().equals("*")) { if (!CHAR_S2G.equals(filter.getSessionName().toString())) { - if (provider.getSourceSessionName() != null && !provider.getSourceSessionName().toString().equals( - filter.getSessionName().toString())) { + if (provider.getSourceSessionName() != null + && !provider.getSourceSessionName().toString().equals( + filter.getSessionName().toString())) { continue; } } @@ -287,7 +217,8 @@ public ProviderSummaryList lookupProvider(final ServiceFilter filter, final MALI // Check each service for (int j = 0; j < provider.getProviderDetails().getServiceCapabilities().size(); j++) { // Go through all the services - ServiceCapability serviceCapability = provider.getProviderDetails().getServiceCapabilities().get(j); + ServiceCapability serviceCapability + = provider.getProviderDetails().getServiceCapabilities().get(j); // Check service key - area field if (filter.getServiceKey().getKeyArea().getValue() != 0) { @@ -298,16 +229,16 @@ public ProviderSummaryList lookupProvider(final ServiceFilter filter, final MALI // Check service key - service field if (filter.getServiceKey().getKeyService().getValue() != 0) { - if (!serviceCapability.getServiceKey().getKeyService().equals(filter.getServiceKey() - .getKeyService())) { + if (!serviceCapability.getServiceKey().getKeyService().equals( + filter.getServiceKey().getKeyService())) { continue; } } // Check service key - version field if (filter.getServiceKey().getKeyAreaVersion().getValue() != 0) { - if (!serviceCapability.getServiceKey().getKeyAreaVersion().equals(filter.getServiceKey() - .getKeyAreaVersion())) { + if (!serviceCapability.getServiceKey().getKeyAreaVersion().equals( + filter.getServiceKey().getKeyAreaVersion())) { continue; } } @@ -331,9 +262,12 @@ public ProviderSummaryList lookupProvider(final ServiceFilter filter, final MALI } } - ServiceCapability newServiceCapability = new ServiceCapability(serviceCapability.getServiceKey(), - serviceCapability.getSupportedCapabilitySets(), serviceCapability.getServiceProperties(), - new AddressDetailsList()); + ServiceCapability newServiceCapability = new ServiceCapability( + serviceCapability.getServiceKey(), + serviceCapability.getSupportedCapabilitySets(), + serviceCapability.getServiceProperties(), + new AddressDetailsList() + ); // This is a workaround to save bandwidth on the downlink! It is not part of the standard if (CHAR_S2G.equals(filter.getSessionName().toString())) { @@ -371,7 +305,7 @@ public ProviderSummaryList lookupProvider(final ServiceFilter filter, final MALI @Override public PublishProviderResponse publishProvider(final PublishDetails newProviderDetails, - final MALInteraction interaction) throws MALInteractionException, MALException { + final MALInteraction interaction) throws MALInteractionException, MALException { Identifier serviceProviderName = newProviderDetails.getProviderId(); IdentifierList objBodies = new IdentifierList(); objBodies.add(serviceProviderName); @@ -387,15 +321,16 @@ public PublishProviderResponse publishProvider(final PublishDetails newProviderD if (serviceProviderName.getValue().equals(provider.getProviderId().getValue())) { // It is repeated!! - LOGGER.warning("There was already a provider with the same name in the Directory service. " + - "Removing the old one and adding the new one..."); + LOGGER.warning("There was already a provider with the same name in the " + + "Directory service. Removing the old one and adding the new one..."); withdrawProvider(key, null); } } - ArchiveDetailsList archDetails = (interaction == null) ? HelperArchive.generateArchiveDetailsList(null, - null, connection.getPrimaryConnectionDetails().getProviderURI()) : HelperArchive - .generateArchiveDetailsList((Long) null, null, interaction); + ArchiveDetailsList archDetails = (interaction == null) + ? HelperArchive.generateArchiveDetailsList(null, null, + connection.getPrimaryConnectionDetails().getProviderURI()) + : HelperArchive.generateArchiveDetailsList((Long) null, null, interaction); // Check if there are comServices... if (comServices == null) { @@ -408,9 +343,14 @@ public PublishProviderResponse publishProvider(final PublishDetails newProviderD } // Store in the Archive the ServiceProvider COM object and get an object instance identifier - final LongList returnedServProvObjIds = comServices.getArchiveService().store(true, - DirectoryHelper.SERVICEPROVIDER_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), archDetails, - objBodies, null); + final LongList returnedServProvObjIds = comServices.getArchiveService().store( + true, + DirectoryHelper.SERVICEPROVIDER_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + archDetails, + objBodies, + null + ); Long servProvObjId; @@ -421,16 +361,23 @@ public PublishProviderResponse publishProvider(final PublishDetails newProviderD } // related contains the objId of the ServiceProvider object - final ArchiveDetailsList archDetails1 = (interaction == null) ? HelperArchive.generateArchiveDetailsList( - servProvObjId, null, connection.getPrimaryConnectionDetails().getProviderURI()) : HelperArchive - .generateArchiveDetailsList(servProvObjId, null, interaction); + final ArchiveDetailsList archDetails1 = (interaction == null) + ? HelperArchive.generateArchiveDetailsList(servProvObjId, null, + connection.getPrimaryConnectionDetails().getProviderURI()) + : HelperArchive.generateArchiveDetailsList(servProvObjId, null, interaction); ProviderDetailsList capabilities = new ProviderDetailsList(1); capabilities.add(newProviderDetails.getProviderDetails()); // Store in the Archive the ProviderCapabilities COM object - comServices.getArchiveService().store(false, DirectoryHelper.PROVIDERCAPABILITIES_OBJECT_TYPE, - ConfigurationProviderSingleton.getDomain(), archDetails1, capabilities, null); + comServices.getArchiveService().store( + false, + DirectoryHelper.PROVIDERCAPABILITIES_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), + archDetails1, + capabilities, + null + ); this.providersAvailable.put(servProvObjId, newProviderDetails); response.setBodyElement0(servProvObjId); @@ -441,8 +388,8 @@ public PublishProviderResponse publishProvider(final PublishDetails newProviderD } @Override - public void withdrawProvider(Long providerObjectKey, MALInteraction interaction) throws MALInteractionException, - MALException { + public void withdrawProvider(Long providerObjectKey, + MALInteraction interaction) throws MALInteractionException, MALException { synchronized (MUTEX) { if (!this.providersAvailable.containsKey(providerObjectKey)) { // The requested provider does not exist throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, null)); @@ -452,7 +399,7 @@ public void withdrawProvider(Long providerObjectKey, MALInteraction interaction) IdentifierList domain = ConfigurationProviderSingleton.getDomain(); ArchiveQuery query = new ArchiveQuery(domain, null, null, providerObjectKey, null, null, null, null, null); List result = manager.query(DirectoryHelper.PROVIDERCAPABILITIES_OBJECT_TYPE, - query, null); + query, null); Long capabilityId = result.get(0).getArchiveDetails().getInstId(); // there should be only one object in the query result LongList providerIds = new LongList(); providerIds.add(providerObjectKey); @@ -465,104 +412,72 @@ public void withdrawProvider(Long providerObjectKey, MALInteraction interaction) } } - private static AddressDetails getServiceAddressDetails(final SingleConnectionDetails conn) - { - QoSLevelList qos = new QoSLevelList(); - qos.add(QoSLevel.ASSURED); - NamedValueList qosProperties = new NamedValueList(); // Nothing here for now... - - AddressDetails serviceAddress = new AddressDetails(); - serviceAddress.setSupportedLevels(qos); - serviceAddress.setQoSproperties(qosProperties); - serviceAddress.setPriorityLevels(new UInteger(1)); // hum? - serviceAddress.setServiceURI(conn.getProviderURI()); - serviceAddress.setBrokerURI(conn.getBrokerURI()); - serviceAddress.setBrokerProviderObjInstId(null); - - return serviceAddress; - } - - private static AddressDetailsList findAddressDetailsListOfService(final ServiceKey key, - final ServiceCapabilityList capabilities) - { - if (key == null) { - return null; + private static AddressDetails getServiceAddressDetails(final SingleConnectionDetails conn) { + QoSLevelList qos = new QoSLevelList(); + qos.add(QoSLevel.ASSURED); + NamedValueList qosProperties = new NamedValueList(); // Nothing here for now... + + AddressDetails serviceAddress = new AddressDetails(); + serviceAddress.setSupportedLevels(qos); + serviceAddress.setQoSproperties(qosProperties); + serviceAddress.setPriorityLevels(new UInteger(1)); // hum? + serviceAddress.setServiceURI(conn.getProviderURI()); + serviceAddress.setBrokerURI(conn.getBrokerURI()); + serviceAddress.setBrokerProviderObjInstId(null); + + return serviceAddress; } - // Iterate all capabilities until you find the serviceName - for (ServiceCapability capability : capabilities) { - if (capability != null) { - if (key.equals(capability.getServiceKey())) { - return capability.getServiceAddresses(); + private static AddressDetailsList findAddressDetailsListOfService( + final ServiceKey key, final ServiceCapabilityList capabilities) { + if (key == null) { + return null; } - } + + // Iterate all capabilities until you find the serviceName + for (ServiceCapability capability : capabilities) { + if (capability != null) { + if (key.equals(capability.getServiceKey())) { + return capability.getServiceAddresses(); + } + } + } + + return null; // Not found! } - return null; // Not found! - } - - public static ServiceKey generateServiceKey(final IntegerList keys) - { - return new ServiceKey(new UShort(keys.get(0)), new UShort(keys.get(1)), new UOctet( - keys.get(2).shortValue())); - } - - /** - * Closes all running threads and releases the MAL resources. - */ - public void close() - { - try { - if (null != directoryServiceProvider) { - directoryServiceProvider.close(); - } - - connection.closeAll(); - running = false; - } catch (MALException ex) { - LOGGER.log(Level.WARNING, - "Exception during close down of the provider {0}", ex); + public static ServiceKey generateServiceKey(final IntegerList keys) { + return new ServiceKey(new UShort(keys.get(0)), new UShort(keys.get(1)), + new UOctet(keys.get(2).shortValue())); + } + + /** + * Closes all running threads and releases the MAL resources. + */ + public void close() { + try { + if (null != directoryServiceProvider) { + directoryServiceProvider.close(); + } + + connection.closeAll(); + running = false; + } catch (MALException ex) { + LOGGER.log(Level.WARNING, + "Exception during close down of the provider {0}", ex); + } } - } - - public ConnectionProvider getConnection() - { - return this.connection; - } - - public void withdrawAllProviders() throws MALInteractionException, MALException - { - synchronized (MUTEX) { - for(Long key : providersAvailable.keySet()) { - withdrawProvider(key, null); - } + + public ConnectionProvider getConnection() { + return this.connection; } - } - - public PublishDetails loadURIs(final String providerName) - { - ServicesConnectionDetails primaryConnectionDetails = ConnectionProvider.getGlobalProvidersDetailsPrimary(); - ServicesConnectionDetails secondaryAddresses = ConnectionProvider.getGlobalProvidersDetailsSecondary(); - - // Services' connections - HashMap connsMap = primaryConnectionDetails.getServices(); - Object[] serviceNames = connsMap.keySet().toArray(); - - final ServiceCapabilityList capabilities = new ServiceCapabilityList(); - - // Iterate all the services and make them available... - for (Object serviceName : serviceNames) { - SingleConnectionDetails conn = connsMap.get((String) serviceName); - AddressDetails serviceAddress = DirectoryProviderServiceImpl.getServiceAddressDetails(conn); - AddressDetailsList serviceAddresses = new AddressDetailsList(); - serviceAddresses.add(serviceAddress); - ServiceKey key = DirectoryProviderServiceImpl.generateServiceKey(conn.getServiceKey()); - ServiceCapability capability = new ServiceCapability(); - capability.setServiceKey(key); - capability.setSupportedCapabilitySets(null); // "If NULL then all capabilities supported." - capability.setServiceProperties(new NamedValueList()); - capability.setServiceAddresses(serviceAddresses); - capabilities.add(capability); + + public void withdrawAllProviders() throws MALInteractionException, MALException { + synchronized (MUTEX) { + for (Long key : providersAvailable.keySet()) { + withdrawProvider(key, null); + } + } } public PublishDetails loadURIs(final String providerName) { @@ -599,8 +514,8 @@ public PublishDetails loadURIs(final String providerName) { SingleConnectionDetails conn2 = connsMap.get((String) serviceName); AddressDetails serviceAddress = DirectoryProviderServiceImpl.getServiceAddressDetails(conn2); ServiceKey key2 = DirectoryProviderServiceImpl.generateServiceKey(conn2.getServiceKey()); - AddressDetailsList serviceAddresses = DirectoryProviderServiceImpl.findAddressDetailsListOfService(key2, - capabilities); + AddressDetailsList serviceAddresses + = DirectoryProviderServiceImpl.findAddressDetailsListOfService(key2, capabilities); ServiceCapability capability; if (serviceAddresses == null) { // If not found @@ -627,7 +542,7 @@ public PublishDetails loadURIs(final String providerName) { newProviderDetails.setProviderId(new Identifier(providerName)); newProviderDetails.setDomain(ConfigurationProviderSingleton.getDomain()); newProviderDetails.setSessionType(ConfigurationProviderSingleton.getSession()); - // newProviderDetails.setSourceSessionName(ConfigurationProviderSingleton.getSourceSessionName()); +// newProviderDetails.setSourceSessionName(ConfigurationProviderSingleton.getSourceSessionName()); newProviderDetails.setSourceSessionName(null); // It just takes bandwidth, so just null it newProviderDetails.setNetwork(ConfigurationProviderSingleton.getNetwork()); newProviderDetails.setProviderDetails(serviceDetails); @@ -646,5 +561,4 @@ public PublishDetails loadURIs(final String providerName) { public FileList getServiceXML(Long l, MALInteraction mali) throws MALInteractionException, MALException { throw new UnsupportedOperationException("Not supported yet."); } - } diff --git a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java index dc18bc313..4c5959b00 100644 --- a/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java +++ b/core/mo-services-impl/nmf-platform-generic-impl/src/main/java/esa/mo/platform/impl/provider/gen/GPSProviderServiceImpl.java @@ -90,110 +90,70 @@ * GPS service Provider. */ public class GPSProviderServiceImpl extends GPSInheritanceSkeleton implements ReconfigurableService { - - protected static final Logger LOGGER = Logger.getLogger(GPSProviderServiceImpl.class.getName()); - private MALProvider gpsServiceProvider; - private boolean initialiased = false; - private boolean running = false; - private NearbyPositionPublisher publisher; - private boolean isRegistered = false; - private final Object lock = new Object(); - private GPSManager manager; - private PeriodicCurrentPosition periodicCurrentPosition; - private final ConnectionProvider connection = new ConnectionProvider(); - protected GPSAdapterInterface adapter; - private ConfigurationChangeListener configurationAdapter; - - protected final Object MUTEX = new Object(); - protected Position currentPosition = null; - protected VectorD3D currentCartesianPosition = null; - protected VectorF3D currentCartesianPositionDeviation = null; - protected VectorD3D currentCartesianVelocity = null; - protected VectorF3D currentCartesianVelocityDeviation = null; - - protected long timeOfCurrentPosition; - protected long timeOfCurrentPositionAndVelocity; - - /** - * creates the MAL objects, the publisher used to create updates and starts the publishing thread - * - * @param comServices - * @param adapter - * @throws MALException On initialisation error. - */ - public synchronized void init(final COMServicesProvider comServices, - final GPSAdapterInterface adapter) throws MALException - { - long timestamp = System.currentTimeMillis(); - - if (!initialiased) { - - if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, - MALHelper.MAL_AREA_VERSION) == null) { - MALHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, - PlatformHelper.PLATFORM_AREA_VERSION) == null) { - PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, - COMHelper.COM_AREA_VERSION) == null) { - COMHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - - if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, - PlatformHelper.PLATFORM_AREA_VERSION) - .getServiceByName(GPSHelper.GPS_SERVICE_NAME) == null) { - GPSHelper.init(MALContextFactory.getElementFactoryRegistry()); - } - } - publisher = createNearbyPositionPublisher(ConfigurationProviderSingleton.getDomain(), - ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, - ConfigurationProviderSingleton.getSourceSessionName(), QoSLevel.BESTEFFORT, null, - new UInteger(0)); + protected static final Logger LOGGER = Logger.getLogger(GPSProviderServiceImpl.class.getName()); + private MALProvider gpsServiceProvider; + private boolean initialiased = false; + private boolean running = false; + private NearbyPositionPublisher publisher; + private boolean isRegistered = false; + private final Object lock = new Object(); + private GPSManager manager; + private PeriodicCurrentPosition periodicCurrentPosition; + private final ConnectionProvider connection = new ConnectionProvider(); + protected GPSAdapterInterface adapter; + private ConfigurationChangeListener configurationAdapter; + + protected final Object MUTEX = new Object(); + protected Position currentPosition = null; + protected VectorD3D currentCartesianPosition = null; + protected VectorF3D currentCartesianPositionDeviation = null; + protected VectorD3D currentCartesianVelocity = null; + protected VectorF3D currentCartesianVelocityDeviation = null; + + protected long timeOfCurrentPosition; + protected long timeOfCurrentPositionAndVelocity; - // Shut down old service transport - if (null != gpsServiceProvider) { - connection.closeAll(); - } + /** + * creates the MAL objects, the publisher used to create updates and starts + * the publishing thread + * + * @param comServices + * @param adapter + * @throws MALException On initialisation error. + */ + public synchronized void init(final COMServicesProvider comServices, + final GPSAdapterInterface adapter) throws MALException { + long timestamp = System.currentTimeMillis(); - manager = new GPSManager(comServices); - this.adapter = adapter; - gpsServiceProvider = connection.startService(GPSHelper.GPS_SERVICE_NAME.toString(), - GPSHelper.GPS_SERVICE, this); - - if (Boolean.parseBoolean(System.getProperty(HelperMisc.PROP_GPS_POLLING_ACTIVE, "true"))) { - periodicCurrentPosition = new PeriodicCurrentPosition(); - periodicCurrentPosition.init(); - running = true; - initialiased = true; - periodicCurrentPosition.start(); - } - - timestamp = System.currentTimeMillis() - timestamp; - LOGGER.info("GPS service: READY! (" + timestamp + " ms)"); - } - - /** - * Closes all running threads and releases the MAL resources. - */ - public void close() - { - try { - if (null != gpsServiceProvider) { - gpsServiceProvider.close(); - } - - connection.closeAll(); - running = false; - } catch (MALException ex) { - LOGGER.log(Level.WARNING, - "Exception during close down of the provider {0}", ex); - } - } + if (!initialiased) { + + if (MALContextFactory.lookupArea(MALHelper.MAL_AREA_NAME, + MALHelper.MAL_AREA_VERSION) == null) { + MALHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) == null) { + PlatformHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(COMHelper.COM_AREA_NAME, + COMHelper.COM_AREA_VERSION) == null) { + COMHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + + if (MALContextFactory.lookupArea(PlatformHelper.PLATFORM_AREA_NAME, + PlatformHelper.PLATFORM_AREA_VERSION) + .getServiceByName(GPSHelper.GPS_SERVICE_NAME) == null) { + GPSHelper.init(MALContextFactory.getElementFactoryRegistry()); + } + } + + publisher = createNearbyPositionPublisher(ConfigurationProviderSingleton.getDomain(), + ConfigurationProviderSingleton.getNetwork(), SessionType.LIVE, + ConfigurationProviderSingleton.getSourceSessionName(), QoSLevel.BESTEFFORT, null, + new UInteger(0)); // Shut down old service transport if (null != gpsServiceProvider) { @@ -202,8 +162,8 @@ public void close() manager = new GPSManager(comServices); this.adapter = adapter; - gpsServiceProvider = connection.startService(GPSHelper.GPS_SERVICE_NAME.toString(), GPSHelper.GPS_SERVICE, - this); + gpsServiceProvider = connection.startService(GPSHelper.GPS_SERVICE_NAME.toString(), + GPSHelper.GPS_SERVICE, this); if (Boolean.parseBoolean(System.getProperty(HelperMisc.PROP_GPS_POLLING_ACTIVE, "true"))) { periodicCurrentPosition = new PeriodicCurrentPosition(); @@ -212,7 +172,9 @@ public void close() initialiased = true; periodicCurrentPosition.start(); } - LOGGER.info("GPS service READY"); + + timestamp = System.currentTimeMillis() - timestamp; + LOGGER.info("GPS service: READY! (" + timestamp + " ms)"); } /** @@ -227,7 +189,8 @@ public void close() { connection.closeAll(); running = false; } catch (MALException ex) { - LOGGER.log(Level.WARNING, "Exception during close down of the provider {0}", ex); + LOGGER.log(Level.WARNING, + "Exception during close down of the provider {0}", ex); } } @@ -248,8 +211,8 @@ private void publishNearbyPositionUpdate(final Long objId, final Boolean isInsid final URI uri = connection.getConnectionDetails().getProviderURI(); final Long pValObjId = manager.storeAndGenerateNearbyPositionAlertId(isInside, objId, uri); - final EntityKey ekey = new EntityKey(new Identifier(manager.get(objId).getName().toString()), objId, - pValObjId, null); + final EntityKey ekey = new EntityKey(new Identifier(manager.get(objId).getName().toString()), + objId, pValObjId, null); final Time timestamp = HelperTime.getTimestampMillis(); final UpdateHeaderList hdrlst = new UpdateHeaderList(); @@ -261,55 +224,46 @@ private void publishNearbyPositionUpdate(final Long objId, final Boolean isInsid publisher.publish(hdrlst, bools); } catch (IllegalArgumentException | MALException | MALInteractionException ex) { - LOGGER.log(Level.WARNING, "Exception during publishing process on the provider {0}", ex); + LOGGER.log(Level.WARNING, + "Exception during publishing process on the provider {0}", ex); } } /** * Ensures the NMEA request ends with a single endline + * * @param in input NMEA request * @return sanitized NMEA request */ private String sanitizeNMEARequest(String in) { - if (in.charAt(in.length() - 1) == '\n') + if (in.charAt(in.length() - 1) == '\n') { return in; + } return in + "\n"; } @Override public void getNMEASentence(String sentenceIdentifier, GetNMEASentenceInteraction interaction) - throws MALInteractionException, MALException { + throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { // Is the unit available? - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } - Position position = updateCurrentPosition(useTLEpropagation); - if (position == null) { - throw new MALInteractionException( - new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - } - interaction.sendResponse(position); - } - - @Override - public void getSatellitesInfo(GetSatellitesInfoInteraction interaction) - throws MALInteractionException, MALException - { - if (!adapter.isUnitAvailable()) { - throw new MALInteractionException( - new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - } - interaction.sendAcknowledgement(); - SatelliteInfoList sats = adapter.getSatelliteInfoList(); - if (sats == null) { - throw new MALInteractionException( - new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + interaction.sendAcknowledgement(); + + try { + String nmeaSentence = adapter.getNMEASentence(sanitizeNMEARequest(sentenceIdentifier)); + interaction.sendResponse(nmeaSentence); + } catch (IOException ex) { + LOGGER.log(Level.FINE, "getNMEASentence error", ex); + throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, null)); + } } @Override - public GetLastKnownPositionResponse getLastKnownPosition(MALInteraction interaction) throws MALInteractionException, - MALException { + public GetLastKnownPositionResponse getLastKnownPosition(MALInteraction interaction) + throws MALInteractionException, MALException { GetLastKnownPositionResponse response = new GetLastKnownPositionResponse(); final Position pos; final long startTime; @@ -324,90 +278,52 @@ public GetLastKnownPositionResponse getLastKnownPosition(MALInteraction interact } response.setBodyElement0(pos); - double elapsedTime = (System.currentTimeMillis() - startTime) / 1000.0; // convert from milli to + double elapsedTime = (System.currentTimeMillis() - startTime) / 1000; // convert from milli to // sec response.setBodyElement1(new Duration(elapsedTime)); return response; } @Override - public void getPosition(GetPositionInteraction interaction) throws MALInteractionException, MALException { + public void getPosition(GetPositionInteraction interaction) + throws MALInteractionException, MALException { boolean useTLEpropagation = false; try { useTLEpropagation = useTLEPropagation(); } catch (MALException | MALInteractionException e) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } interaction.sendAcknowledgement(); Position position = updateCurrentPosition(useTLEpropagation); if (position == null) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } interaction.sendResponse(position); } - /** - * Checks if TLE propagation should be used - * @return true if TLE propagation should be used, false otherwise - */ - - public boolean useTLEPropagation() throws MALInteractionException, MALException { - boolean useTLEpropagation = false; - if (!adapter.isUnitAvailable()) { - if (isTLEFallbackEnabled) { - useTLEpropagation = true; - } else { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); - } - } else if (!isPositionFixed()) { - useTLEpropagation = true; - } - return useTLEpropagation; - } - - /** - * Updates the current position using TLE if useTLEpropagation is true, - * or the GPS adapter if useTLEpropagation is false - * @param useTLEpropagation - * @return the updated position, or null if the methods that get latest position fail - */ - public Position updateCurrentPosition(boolean useTLEpropagation) { - Position position = useTLEpropagation ? getTLEPropagatedPosition() : adapter.getCurrentPosition(); - if (position == null) { - return null; - } - - synchronized (MUTEX) { // Store the latest Position - currentPosition = position; - timeOfCurrentPosition = System.currentTimeMillis(); - } - return position; - } - @Override - public void getSatellitesInfo(GetSatellitesInfoInteraction interaction) throws MALInteractionException, - MALException { + public void getSatellitesInfo(GetSatellitesInfoInteraction interaction) + throws MALInteractionException, MALException { if (!adapter.isUnitAvailable()) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } interaction.sendAcknowledgement(); SatelliteInfoList sats = adapter.getSatelliteInfoList(); if (sats == null) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } interaction.sendResponse(sats); } @Override - public LongList listNearbyPosition(IdentifierList names, MALInteraction interaction) throws MALInteractionException, - MALException { + public LongList listNearbyPosition(IdentifierList names, MALInteraction interaction) + throws MALInteractionException, MALException { LongList outLongLst = new LongList(); if (null == names) { // Is the input null? @@ -433,7 +349,7 @@ public LongList listNearbyPosition(IdentifierList names, MALInteraction interact @Override public LongList addNearbyPosition(final NearbyPositionDefinitionList nearbyPositionDefinitions, - final MALInteraction interaction) throws MALInteractionException, MALException { + final MALInteraction interaction) throws MALInteractionException, MALException { LongList outLongLst = new LongList(); UIntegerList invIndexList = new UIntegerList(); UIntegerList dupIndexList = new UIntegerList(); @@ -454,60 +370,22 @@ public LongList addNearbyPosition(final NearbyPositionDefinitionList nearbyPosit if (manager.list(name) == null) { // Is the supplied name unique? ObjectId source = manager.storeCOMOperationActivity(interaction); - outLongLst.add(manager.add(def, source, connection.getConnectionDetails().getProviderURI())); + outLongLst + .add(manager.add(def, source, connection.getConnectionDetails().getProviderURI())); } else { dupIndexList.add(new UInteger(index)); // requirement: 3.4.10.2.c } } - double elapsedTime = (System.currentTimeMillis() - startTime) / 1000; // convert from milli to sec - - return new GetLastKnownPositionAndVelocityResponse(position, positionDeviation, velocity, - velocityDeviation, new Duration(elapsedTime)); - } - - @Override - public void getPositionAndVelocity(GetPositionAndVelocityInteraction interaction) throws - MALInteractionException, MALException - { - boolean useTLEpropagation = false; - try{ - useTLEpropagation = useTLEPropagation(); - }catch (MALException | MALInteractionException e){ - throw new MALInteractionException( - new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - } - interaction.sendAcknowledgement(); - try{ - updateCurrentPositionAndVelocity(useTLEpropagation); - }catch(IOException | NumberFormatException e){ - interaction - .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - } - final VectorD3D position; - final VectorF3D positionDeviation; - final VectorD3D velocity; - final VectorF3D velocityDeviation; - - synchronized (MUTEX) { - position = currentCartesianPosition; - positionDeviation = currentCartesianPositionDeviation; - velocity = currentCartesianVelocity; - velocityDeviation = currentCartesianVelocityDeviation; - } - interaction.sendResponse(position, positionDeviation, velocity, velocityDeviation); - } - - @Override - public void getTLE(GetTLEInteraction interaction) throws MALInteractionException, MALException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public static final class PublishInteractionListener implements MALPublishInteractionListener - { + // Errors + if (!dupIndexList.isEmpty()) { // requirement: 3.4.10.3.1 + throw new MALInteractionException( + new MALStandardError(COMHelper.DUPLICATE_ERROR_NUMBER, dupIndexList)); + } if (!invIndexList.isEmpty()) { // requirement: 3.4.10.3.2 - throw new MALInteractionException(new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); + throw new MALInteractionException( + new MALStandardError(COMHelper.INVALID_ERROR_NUMBER, invIndexList)); } if (configurationAdapter != null) { @@ -518,8 +396,8 @@ public static final class PublishInteractionListener implements MALPublishIntera } @Override - public void removeNearbyPosition(LongList objInstIds, MALInteraction interaction) throws MALInteractionException, - MALException { + public void removeNearbyPosition(LongList objInstIds, MALInteraction interaction) + throws MALInteractionException, MALException { UIntegerList unkIndexList = new UIntegerList(); Long tempLong; LongList tempLongLst = new LongList(); @@ -547,7 +425,8 @@ public void removeNearbyPosition(LongList objInstIds, MALInteraction interaction // Errors if (!unkIndexList.isEmpty()) { - throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); + throw new MALInteractionException( + new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, unkIndexList)); } for (Long tempLong2 : tempLongLst) { @@ -560,8 +439,8 @@ public void removeNearbyPosition(LongList objInstIds, MALInteraction interaction } @Override - public GetLastKnownPositionAndVelocityResponse getLastKnownPositionAndVelocity(MALInteraction interaction) - throws MALInteractionException, MALException { + public GetLastKnownPositionAndVelocityResponse getLastKnownPositionAndVelocity( + MALInteraction interaction) throws MALInteractionException, MALException { final VectorD3D position; final VectorF3D positionDeviation; final VectorD3D velocity; @@ -580,27 +459,28 @@ public GetLastKnownPositionAndVelocityResponse getLastKnownPositionAndVelocity(M throw new MALInteractionException(new MALStandardError(MALHelper.UNKNOWN_ERROR_NUMBER, null)); } - double elapsedTime = (System.currentTimeMillis() - startTime) / 1000.0; // convert from milli to sec + double elapsedTime = (System.currentTimeMillis() - startTime) / 1000; // convert from milli to sec - return new GetLastKnownPositionAndVelocityResponse(position, positionDeviation, velocity, velocityDeviation, - new Duration(elapsedTime)); + return new GetLastKnownPositionAndVelocityResponse(position, positionDeviation, velocity, + velocityDeviation, new Duration(elapsedTime)); } @Override - public void getPositionAndVelocity(GetPositionAndVelocityInteraction interaction) throws MALInteractionException, - MALException { + public void getPositionAndVelocity(GetPositionAndVelocityInteraction interaction) throws + MALInteractionException, MALException { boolean useTLEpropagation = false; try { useTLEpropagation = useTLEPropagation(); } catch (MALException | MALInteractionException e) { - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } interaction.sendAcknowledgement(); try { updateCurrentPositionAndVelocity(useTLEpropagation); } catch (IOException | NumberFormatException e) { - interaction.sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + interaction + .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); } final VectorD3D position; final VectorF3D positionDeviation; @@ -616,103 +496,39 @@ public void getPositionAndVelocity(GetPositionAndVelocityInteraction interaction interaction.sendResponse(position, positionDeviation, velocity, velocityDeviation); } - /** - * Updates the current position/velocity - * @param useTLEpropagation - */ - public void updateCurrentPositionAndVelocity(boolean useTLEpropagation) throws IOException, NumberFormatException { - try { - final VectorD3D position; - final VectorF3D positionDeviation; - final VectorD3D velocity; - final VectorF3D velocityDeviation; - - if (useTLEpropagation) { - Calendar targetDate = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - SpacecraftState state = getSpacecraftState(targetDate); - Vector3D pos = state.getPVCoordinates().getPosition(); - position = new VectorD3D(pos.getX(), pos.getY(), pos.getZ()); - - positionDeviation = new VectorF3D(0f, 0f, 0f); - - Vector3D velocity3D = state.getPVCoordinates().getVelocity(); - velocity = new VectorD3D(velocity3D.getX(), velocity3D.getY(), velocity3D.getZ()); - - velocityDeviation = new VectorF3D(0f, 0f, 0f); - } else { - String bestxyz = adapter.getBestXYZSentence(); - - String[] fields = HelperGPS.getDataFieldsFromBestXYZ(bestxyz); - - position = new VectorD3D(Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PX]), Double.parseDouble( - fields[HelperGPS.BESTXYZ_FIELD.PY]), Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PZ])); - - positionDeviation = new VectorF3D(Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PX_DEVIATION]), Float - .parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PY_DEVIATION]), Float.parseFloat( - fields[HelperGPS.BESTXYZ_FIELD.PZ_DEVIATION])); - - velocity = new VectorD3D(Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VX]), Double.parseDouble( - fields[HelperGPS.BESTXYZ_FIELD.VY]), Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VZ])); - - velocityDeviation = new VectorF3D(Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VX_DEVIATION]), Float - .parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VY_DEVIATION]), Float.parseFloat( - fields[HelperGPS.BESTXYZ_FIELD.VZ_DEVIATION])); - } - synchronized (MUTEX) { // Store the latest Position - currentCartesianPosition = position; - currentCartesianPositionDeviation = positionDeviation; - currentCartesianVelocity = velocity; - currentCartesianVelocityDeviation = velocityDeviation; - timeOfCurrentPositionAndVelocity = System.currentTimeMillis(); - } - } catch (IOException | NumberFormatException e) { - e.printStackTrace(); - throw e; - } - } - @Override public void getTLE(GetTLEInteraction interaction) throws MALInteractionException, MALException { - if (!adapter.isUnitAvailable() && isTLEFallbackEnabled == false) { // Is the unit available? - throw new MALInteractionException(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, - null)); - } - interaction.sendAcknowledgement(); - TLE tle = adapter.getTLE(); - - interaction.sendResponse(new TwoLineElementSet(tle.getSatelliteNumber(), "" + tle.getClassification(), tle - .getLaunchYear(), tle.getLaunchNumber(), tle.getLaunchPiece(), tle.getDate().getComponents(0).getDate() - .getYear(), tle.getDate().getComponents(0).getDate().getDayOfYear(), tle.getDate().getComponents(0) - .getTime().getSecondsInUTCDay(), tle.getMeanMotionFirstDerivative(), tle - .getMeanMotionSecondDerivative(), tle.getBStar(), tle.getElementNumber(), tle.getI(), tle - .getRaan(), tle.getE(), tle.getPerigeeArgument(), tle.getMeanAnomaly(), tle.getMeanMotion(), - tle.getRevolutionNumberAtEpoch())); + throw new UnsupportedOperationException("Not supported yet."); } public static final class PublishInteractionListener implements MALPublishInteractionListener { @Override public void publishDeregisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { - LOGGER.fine("PublishInteractionListener::publishDeregisterAckReceived"); + throws MALException { + LOGGER + .fine("PublishInteractionListener::publishDeregisterAckReceived"); } @Override public void publishErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { - LOGGER.warning("PublishInteractionListener::publishErrorReceived"); + final Map qosProperties) throws MALException { + LOGGER + .warning("PublishInteractionListener::publishErrorReceived"); } @Override public void publishRegisterAckReceived(final MALMessageHeader header, final Map qosProperties) - throws MALException { - LOGGER.log(Level.INFO, "Registration Ack: {0}", header.toString()); + throws MALException { + LOGGER.log(Level.INFO, + "Registration Ack: {0}", header.toString()); } @Override public void publishRegisterErrorReceived(final MALMessageHeader header, final MALErrorBody body, - final Map qosProperties) throws MALException { - LOGGER.warning("PublishInteractionListener::publishRegisterErrorReceived"); + final Map qosProperties) throws MALException { + LOGGER + .warning("PublishInteractionListener::publishRegisterErrorReceived"); } } @@ -759,8 +575,9 @@ public Boolean reloadConfiguration(ConfigurationObjectDetails configurationObjec // ok, we're good to go... // Load the Parameter Definitions from this configuration... - PositionList pDefs = (PositionList) HelperArchive.getObjectBodyListFromArchive(manager.getArchiveService(), - GPSHelper.NEARBYPOSITION_OBJECT_TYPE, ConfigurationProviderSingleton.getDomain(), confSet.getObjInstIds()); + PositionList pDefs = (PositionList) HelperArchive.getObjectBodyListFromArchive( + manager.getArchiveService(), GPSHelper.NEARBYPOSITION_OBJECT_TYPE, + ConfigurationProviderSingleton.getDomain(), confSet.getObjInstIds()); manager.reconfigureDefinitions(confSet.getObjInstIds(), pDefs); // Reconfigures the Manager @@ -817,23 +634,37 @@ public void start() { active = true; } - @Override - public void getBestXYZSentence(GetBestXYZSentenceInteraction interaction) - throws MALInteractionException, MALException - { - if (!adapter.isUnitAvailable()) { // Is the unit available? - throw new MALInteractionException( - new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - } - interaction.sendAcknowledgement(); - try { - interaction.sendResponse(adapter.getBestXYZSentence()); - } catch (IOException e) { - interaction - .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - LOGGER.log(Level.SEVERE, e.getMessage()); - } - } + public void pause() { + active = false; + } + + public void init() { + timer.scheduleTask(new Thread(() -> { + if (active) { + boolean useTLEpropagation = false; + try { + useTLEpropagation = useTLEPropagation(); + } catch (MALException | MALInteractionException e) { + } + final Position pos = updateCurrentPosition(useTLEpropagation); + try { + updateCurrentPositionAndVelocity(useTLEpropagation); + } catch (IOException | NumberFormatException e) { + } + + // Compare with all the available definitions and raise + // NearbyPositionAlerts in case something has changed + LongList ids = manager.listAll(); + + for (int i = 0; i < ids.size(); i++) { + Long objId = ids.get(i); + NearbyPositionDefinition def = manager.get(objId); + Boolean previousState = manager.getPreviousStatus(objId); + + try { + double distance = PositionsCalculator.deltaDistanceFrom2Points(def.getPosition(), + pos); + boolean isInside = (distance < def.getDistanceBoundary()); if (previousState == null) { // Maybe it's the first run... manager.setPreviousStatus(objId, isInside); @@ -846,99 +677,126 @@ public void getBestXYZSentence(GetBestXYZSentenceInteraction interaction) manager.setPreviousStatus(objId, isInside); } } catch (IOException ex) { - LOGGER.log(Level.SEVERE, ex.getMessage()); + LOGGER.log(Level.SEVERE, + ex.getMessage()); } } } }), 0, PERIOD, TimeUnit.MILLISECONDS, true); } } - interaction.sendAcknowledgement(); - try { - interaction.sendResponse(adapter.getTIMEASentence()); - } catch (IOException e) { - interaction - .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); - LOGGER.log(Level.SEVERE, e.getMessage()); + + @Override + public void getBestXYZSentence(GetBestXYZSentenceInteraction interaction) + throws MALInteractionException, MALException { + if (!adapter.isUnitAvailable()) { // Is the unit available? + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendAcknowledgement(); + try { + interaction.sendResponse(adapter.getBestXYZSentence()); + } catch (IOException e) { + interaction + .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + LOGGER.log(Level.SEVERE, e.getMessage()); + } } - public boolean useTLEPropagation() throws MALInteractionException, MALException { - return false; - } - - /** - * Updates the current position/velocity - * @param useTLEpropagation - */ - public void updateCurrentPositionAndVelocity(boolean useTLEpropagation) - throws IOException, NumberFormatException - { - try { - final VectorD3D position; - final VectorF3D positionDeviation; - final VectorD3D velocity; - final VectorF3D velocityDeviation; - - String bestxyz = adapter.getBestXYZSentence(); - - String[] fields = HelperGPS.getDataFieldsFromBestXYZ(bestxyz); - - position = new VectorD3D( - Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PX]), - Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PY]), - Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PZ]) - ); - - positionDeviation = new VectorF3D( - Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PX_DEVIATION]), - Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PY_DEVIATION]), - Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PZ_DEVIATION]) - ); - - velocity = new VectorD3D( - Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VX]), - Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VY]), - Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VZ]) - ); - - velocityDeviation = new VectorF3D( - Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VX_DEVIATION]), - Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VY_DEVIATION]), - Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VZ_DEVIATION]) - ); - - synchronized (MUTEX) { // Store the latest Position - currentCartesianPosition = position; - currentCartesianPositionDeviation = positionDeviation; - currentCartesianVelocity = velocity; - currentCartesianVelocityDeviation = velocityDeviation; - timeOfCurrentPositionAndVelocity = System.currentTimeMillis(); - } - } catch (IOException | NumberFormatException e) { - LOGGER.log(Level.SEVERE, e.getMessage()); - throw e; + @Override + public void getTIMEASentence(GetTIMEASentenceInteraction interaction) + throws MALInteractionException, MALException { + if (!adapter.isUnitAvailable()) { // Is the unit available? + throw new MALInteractionException( + new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + } + interaction.sendAcknowledgement(); + try { + interaction.sendResponse(adapter.getTIMEASentence()); + } catch (IOException e) { + interaction + .sendError(new MALStandardError(PlatformHelper.DEVICE_NOT_AVAILABLE_ERROR_NUMBER, null)); + LOGGER.log(Level.SEVERE, e.getMessage()); + } } - } - - /** - * Updates the current position using TLE if useTLEpropagation is true, - * or the GPS adapter if useTLEpropagation is false - * @param useTLEpropagation - * @return the updated position, or null if the methods that get latest position fail - */ - public Position updateCurrentPosition(boolean useTLEpropagation) - { - Position position = adapter.getCurrentPosition(); - if (position == null) { - return null; + + public boolean useTLEPropagation() throws MALInteractionException, MALException { + return false; } - synchronized (MUTEX) { // Store the latest Position - currentPosition = position; - timeOfCurrentPosition = System.currentTimeMillis(); + /** + * Updates the current position/velocity + * + * @param useTLEpropagation + */ + public void updateCurrentPositionAndVelocity(boolean useTLEpropagation) + throws IOException, NumberFormatException { + try { + final VectorD3D position; + final VectorF3D positionDeviation; + final VectorD3D velocity; + final VectorF3D velocityDeviation; + + String bestxyz = adapter.getBestXYZSentence(); + + String[] fields = HelperGPS.getDataFieldsFromBestXYZ(bestxyz); + + position = new VectorD3D( + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PX]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PY]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.PZ]) + ); + + positionDeviation = new VectorF3D( + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PX_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PY_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.PZ_DEVIATION]) + ); + + velocity = new VectorD3D( + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VX]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VY]), + Double.parseDouble(fields[HelperGPS.BESTXYZ_FIELD.VZ]) + ); + + velocityDeviation = new VectorF3D( + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VX_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VY_DEVIATION]), + Float.parseFloat(fields[HelperGPS.BESTXYZ_FIELD.VZ_DEVIATION]) + ); + + synchronized (MUTEX) { // Store the latest Position + currentCartesianPosition = position; + currentCartesianPositionDeviation = positionDeviation; + currentCartesianVelocity = velocity; + currentCartesianVelocityDeviation = velocityDeviation; + timeOfCurrentPositionAndVelocity = System.currentTimeMillis(); + } + } catch (IOException | NumberFormatException e) { + LOGGER.log(Level.SEVERE, e.getMessage()); + throw e; + } + } + + /** + * Updates the current position using TLE if useTLEpropagation is true, or + * the GPS adapter if useTLEpropagation is false + * + * @param useTLEpropagation + * @return the updated position, or null if the methods that get latest + * position fail + */ + public Position updateCurrentPosition(boolean useTLEpropagation) { + Position position = adapter.getCurrentPosition(); + if (position == null) { + return null; + } + + synchronized (MUTEX) { // Store the latest Position + currentPosition = position; + timeOfCurrentPosition = System.currentTimeMillis(); + } + return position; } - return position; - } - } diff --git a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java index 2d7451086..c3e52ceeb 100644 --- a/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java +++ b/core/nmf-composites/nanosat-mo-supervisor/src/main/java/esa/mo/nmf/nanosatmosupervisor/parameter/OBSWParameterManager.java @@ -50,62 +50,66 @@ * @author Tanguy Soto */ public class OBSWParameterManager { - /** - * The logger - */ - private static final Logger LOGGER = Logger.getLogger(OBSWParameterManager.class.getName()); - - /** - * Default OBSW parameter report interval (seconds) - */ - private static final int DEFAULT_REPORT_INTERVAL = 5; - - /** - * Helper to read the OBSW parameter from datapool. - */ - private final ParameterLister parameterLister; - - /** - * Maps each parameter proxy (object instance id of the ParameterIdentity in the supervisor) to - * the OBSW parameter it represents. - */ - private Map proxyIdsToOBSWParams; - - /** - * Provides the OBSW parameter values - */ - private OBSWParameterValuesProvider valuesProvider; - - public OBSWParameterManager(InputStream datapool) - throws IOException, JAXBException, XMLStreamException { - // Read from provided inputstreams - parameterLister = new ParameterLister(datapool); - - // Initialize the parameters proxies to OBSW parameter maps - proxyIdsToOBSWParams = new HashMap<>(); - - // Instantiate the value provider - HashMap parameterMap = parameterLister.getParameters(); - String defaultClass = "esa.mo.nmf.nanosatmosupervisor.parameter.DummyValuesProvider"; - String valuesProviderClass = System.getProperty("nmf.supervisor.parameter.valuesprovider.impl", defaultClass); - - try { - Constructor c = Class.forName(valuesProviderClass).getConstructor(parameterMap.getClass()); - valuesProvider = (OBSWParameterValuesProvider) c.newInstance(new Object[] {parameterMap}); - } catch (Exception e) { - LOGGER.log(Level.SEVERE, - "Error initializing the values provider. Using dummy values provider.", e); - valuesProvider = new DummyValuesProvider(parameterMap); + + /** + * The logger + */ + private static final Logger LOGGER = Logger.getLogger(OBSWParameterManager.class.getName()); + + /** + * Default OBSW parameter report interval (seconds) + */ + private static final int DEFAULT_REPORT_INTERVAL = 5; + + /** + * Helper to read the OBSW parameter from datapool. + */ + private final ParameterLister parameterLister; + + /** + * Maps each parameter proxy (object instance id of the ParameterIdentity in + * the supervisor) to the OBSW parameter it represents. + */ + private Map proxyIdsToOBSWParams; + + /** + * Provides the OBSW parameter values + */ + private OBSWParameterValuesProvider valuesProvider; + + public OBSWParameterManager(InputStream datapool) + throws IOException, JAXBException, XMLStreamException { + // Read from provided inputstreams + parameterLister = new ParameterLister(datapool); + + // Initialize the parameters proxies to OBSW parameter maps + proxyIdsToOBSWParams = new HashMap<>(); + + // Instantiate the value provider + HashMap parameterMap = parameterLister.getParameters(); + String defaultClass = "esa.mo.nmf.nanosatmosupervisor.parameter.DummyValuesProvider"; + String valuesProviderClass = System.getProperty("nmf.supervisor.parameter.valuesprovider.impl", defaultClass); + + try { + Constructor c = Class.forName(valuesProviderClass).getConstructor(parameterMap.getClass()); + valuesProvider = (OBSWParameterValuesProvider) c.newInstance(new Object[]{parameterMap}); + } catch (Exception e) { + LOGGER.log(Level.SEVERE, + "Error initializing the values provider. Using dummy values provider.", e); + valuesProvider = new DummyValuesProvider(parameterMap); + } } /** - * Registers proxies for the OBSW parameters using the provided registration object. + * Registers proxies for the OBSW parameters using the provided registration + * object. * * @param registrationObject The registration object */ public void registerParametersProxies(MCRegistration registrationObject) { // Sort parameters by id - List parameters = new ArrayList<>(parameterLister.getParameters().values()); + List parameters + = new ArrayList<>(parameterLister.getParameters().values()); parameters.sort(Comparator.comparing(OBSWParameter::getId)); // Create the parameter proxies definitions @@ -113,9 +117,9 @@ public void registerParametersProxies(MCRegistration registrationObject) { IdentifierList paramIdentifiers = new IdentifierList(); for (OBSWParameter param : parameters) { - paramDefs.add(new ParameterDefinitionDetails(param.getDescription(), HelperAttributes - .attributeName2typeShortForm(param.getType()).byteValue(), "", false, new Duration( - DEFAULT_REPORT_INTERVAL), null, null)); + paramDefs.add(new ParameterDefinitionDetails(param.getDescription(), + HelperAttributes.attributeName2typeShortForm(param.getType()).byteValue(), "", false, + new Duration(DEFAULT_REPORT_INTERVAL), null, null)); paramIdentifiers.add(new Identifier(param.getName())); } @@ -123,7 +127,7 @@ public void registerParametersProxies(MCRegistration registrationObject) { LongList proxyIds = registrationObject.registerParameters(paramIdentifiers, paramDefs); if (proxyIds == null || proxyIds.size() != parameters.size()) { LOGGER.log(Level.SEVERE, - "Error while registering OBSW parameters proxies: returned IDs are null or some are missing"); + "Error while registering OBSW parameters proxies: returned IDs are null or some are missing"); return; } for (int i = 0; i < proxyIds.size(); i++) { @@ -133,30 +137,32 @@ public void registerParametersProxies(MCRegistration registrationObject) { /** * Returns a value for a given OBSW parameter proxy. - * + * * @param parameterID ID of the parameter proxy * @return The value */ public Attribute getValue(Long parameterID) { - Identifier obswParamIdentifier = new Identifier(proxyIdsToOBSWParams.get(parameterID).getName()); + Identifier obswParamIdentifier + = new Identifier(proxyIdsToOBSWParams.get(parameterID).getName()); return getValue(obswParamIdentifier); } /** * Sets a new value to a given OBSW parameter. - * + * * @param newRawValue the new value * @return true if parameter is set, false otherwise. */ public Boolean setValue(ParameterRawValue newRawValue) { - Identifier obswParamIdentifier = new Identifier(proxyIdsToOBSWParams.get(newRawValue.getParamInstId()) - .getName()); + Identifier obswParamIdentifier + = new Identifier(proxyIdsToOBSWParams.get(newRawValue.getParamInstId()).getName()); return setValue(newRawValue.getRawValue(), obswParamIdentifier); } /** * @param parameterID The parameter ID to test - * @return true if the ID corresponds to one of the parameter proxies registered by this class + * @return true if the ID corresponds to one of the parameter proxies + * registered by this class */ public boolean isOBSWParameterProxy(Long parameterID) { return proxyIdsToOBSWParams.containsKey(parameterID); @@ -174,7 +180,7 @@ private Attribute getValue(Identifier identifier) { /** * Sets a new value for the given OBSW parameter name. - * + * * @param rawValue The new value of the parameter * @param identifier Name of the parameter * @return True if parameter is set, false otherwise. diff --git a/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java b/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java index 063ef2d39..d5dda5588 100644 --- a/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java +++ b/core/nmf-composites/nmf-mo-adapters/common-mo-adapter/src/main/java/esa/mo/nmf/commonmoadapter/CommonMOAdapterImpl.java @@ -102,184 +102,13 @@ public class CommonMOAdapterImpl extends NMFConsumer implements SimpleCommanding private Subscription parameterSubscription = null; private Subscription aggregationSubscription = null; - /** - * The constructor of this class - * - * @param connection The connection details of the provider - */ - public CommonMOAdapterImpl(final ConnectionConsumer connection) - { - this(connection, null, null); - } - - /** - * The constructor of this class - * - * @param connection The connection details of the provider - * @param authenticationId authenticationId of the logged in user - * @param localNamePrefix the prefix for the local name of the consumer - */ - public CommonMOAdapterImpl(final ConnectionConsumer connection, final Blob authenticationId, final String localNamePrefix) - { - super(connection, authenticationId, localNamePrefix); - super.init(); - } - - /** - * The constructor of this class - * - * @param providerDetails The Provider details. This object can be obtained from the Directory - * service - */ - public CommonMOAdapterImpl(final ProviderSummary providerDetails) - { - this(providerDetails, null, null); - } - - /** - * The constructor of this class - * - * @param providerDetails The Provider details. This object can be obtained from the Directory - * service - * @param authenticationId authenticationId of the logged in user - * @param localNamePrefix the prefix for the local name of the consumer - */ - public CommonMOAdapterImpl(final ProviderSummary providerDetails, final Blob authenticationId, final String localNamePrefix) - { - super(providerDetails, authenticationId, localNamePrefix); - super.init(); - } - - @Override - public void setParameter(final String parameterName, final Serializable content) - { - // Check if the parameter exists - IdentifierList parameters = new IdentifierList(1); - parameters.add(new Identifier(parameterName)); - - // If it is java type, then convert it to Attribute - Object midValue = HelperAttributes.javaType2Attribute(content); - Attribute rawValue; - - if (midValue instanceof Attribute) { // Is the parameter MAL type or something else? - rawValue = (Attribute) midValue; - } else { - try { - // Well, if it is something else, then it will have to serialize it and put it inside a Blob - rawValue = HelperAttributes.serialObject2blobAttribute(content); - } catch (IOException ex) { - LOGGER.log(Level.SEVERE, null, ex); - return; - } - } - - ParameterStub parameterService = super.getMCServices().getParameterService().getParameterStub(); - - try { - ObjectInstancePairList objIds = parameterService.listDefinition(parameters); - - if (objIds == null) { - return; // something went wrong... Connection problem? - } - - ObjectInstancePair objId = objIds.get(0); - - // If the definition does not exist, then create it automatically for the user - if (objId == null) { - // Well, then let's create a new Parameter Definition and add it on the provider... - ParameterDefinitionDetails parameterDefinition = new ParameterDefinitionDetails(); - parameterDefinition.setDescription( - "This Definition was automatically generated by: " + CommonMOAdapterImpl.class.getName()); - - if (rawValue instanceof Attribute) { // Is the parameter MAL type or something else? - parameterDefinition.setRawType(((Attribute) midValue).getTypeShortForm().byteValue()); - } else { - parameterDefinition.setRawType(HelperAttributes.SERIAL_OBJECT_RAW_TYPE); - } - - parameterDefinition.setRawUnit(null); - parameterDefinition.setGenerationEnabled(false); - parameterDefinition.setReportInterval(new Duration(0)); - parameterDefinition.setValidityExpression(null); - parameterDefinition.setConversion(null); - - ParameterCreationRequestList request = new ParameterCreationRequestList(1); - request.add(new ParameterCreationRequest(new Identifier(parameterName), parameterDefinition)); - - // Now, add the definition to the service provider - objIds = parameterService.addParameter(request); - } - - // Continues here... - ParameterRawValueList raws = new ParameterRawValueList(); - Long objIdInsID = objIds.get(0).getObjIdentityInstanceId(); - rawValue = (content == null) ? null : rawValue; - raws.add(new ParameterRawValue(objIdInsID, rawValue)); - - // Ok, now, let's finally set the Value! - parameterService.setValue(raws); - } catch (MALInteractionException ex) { - LOGGER.log(Level.SEVERE, "The parameter could not be set!", ex); - } catch (MALException ex) { - LOGGER.log(Level.SEVERE, null, ex); - } - } - - @Override - public void addDataReceivedListener(final DataReceivedListener listener) - { - // Make the parameter adapter to call the receiveDataListener when there's a new object available - class DataReceivedParameterAdapter extends ParameterAdapter - { - - @Override - public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, - final Identifier lIdentifier, final UpdateHeaderList lUpdateHeaderList, - final ObjectIdList lObjectIdList, final ParameterValueList lParameterValueList, - final Map qosp) - { - - if (lParameterValueList.size() == lUpdateHeaderList.size()) { - for (int i = 0; i < lUpdateHeaderList.size(); i++) { - String parameterName = lUpdateHeaderList.get(i).getKey().getFirstSubKey().toString(); - Attribute parameterValue = lParameterValueList.get(i).getRawValue(); - Serializable object; - - // Is it a Blob? - if (parameterValue instanceof Blob) { - // If so, try to unserialize it - try { - object = HelperAttributes.blobAttribute2serialObject((Blob) parameterValue); - } catch (IOException ex) { - // Didn't work? Well, maybe it is just a normal Blob... - object = (Serializable) HelperAttributes.attribute2JavaType(parameterValue); - } - } else { - // Not a Blob? - // Then make it a Java type if possible - object = (Serializable) HelperAttributes.attribute2JavaType(parameterValue); - } - - // Push the data to the user interface - // Simple interface - if (listener instanceof SimpleDataReceivedListener) { - ((SimpleDataReceivedListener) listener).onDataReceived(parameterName, object); - } - - // Complete interface - if (listener instanceof CompleteDataReceivedListener) { - ObjectId source = lObjectIdList.get(i); - Time timestamp = lUpdateHeaderList.get(i).getTimestamp(); - - ParameterInstance parameterInstance = new ParameterInstance(new Identifier( - parameterName), - lParameterValueList.get(i), source, timestamp); - - ((CompleteDataReceivedListener) listener).onDataReceived(parameterInstance); - } - } - } - } + /** + * The constructor of this class + * + * @param connection The connection details of the provider + */ + public CommonMOAdapterImpl(final ConnectionConsumer connection) { + this(connection, null, null); } /** @@ -289,8 +118,7 @@ public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, * @param authenticationId authenticationId of the logged in user * @param localNamePrefix the prefix for the local name of the consumer */ - public CommonMOAdapterImpl(final ConnectionConsumer connection, final Blob authenticationId, - final String localNamePrefix) { + public CommonMOAdapterImpl(final ConnectionConsumer connection, final Blob authenticationId, final String localNamePrefix) { super(connection, authenticationId, localNamePrefix); super.init(); } @@ -298,8 +126,8 @@ public CommonMOAdapterImpl(final ConnectionConsumer connection, final Blob authe /** * The constructor of this class * - * @param providerDetails The Provider details. This object can be obtained from the Directory - * service + * @param providerDetails The Provider details. This object can be obtained + * from the Directory service. */ public CommonMOAdapterImpl(final ProviderSummary providerDetails) { this(providerDetails, null, null); @@ -308,13 +136,13 @@ public CommonMOAdapterImpl(final ProviderSummary providerDetails) { /** * The constructor of this class * - * @param providerDetails The Provider details. This object can be obtained from the Directory - * service + * @param providerDetails The Provider details. This object can be obtained + * from the Directory service. * @param authenticationId authenticationId of the logged in user * @param localNamePrefix the prefix for the local name of the consumer */ - public CommonMOAdapterImpl(final ProviderSummary providerDetails, final Blob authenticationId, - final String localNamePrefix) { + public CommonMOAdapterImpl(final ProviderSummary providerDetails, + final Blob authenticationId, final String localNamePrefix) { super(providerDetails, authenticationId, localNamePrefix); super.init(); } @@ -356,8 +184,8 @@ public void setParameter(final String parameterName, final Serializable content) if (objId == null) { // Well, then let's create a new Parameter Definition and add it on the provider... ParameterDefinitionDetails parameterDefinition = new ParameterDefinitionDetails(); - parameterDefinition.setDescription("This Definition was automatically generated by: " + - CommonMOAdapterImpl.class.getName()); + parameterDefinition.setDescription( + "This Definition was automatically generated by: " + CommonMOAdapterImpl.class.getName()); if (rawValue instanceof Attribute) { // Is the parameter MAL type or something else? parameterDefinition.setRawType(((Attribute) midValue).getTypeShortForm().byteValue()); @@ -380,8 +208,9 @@ public void setParameter(final String parameterName, final Serializable content) // Continues here... ParameterRawValueList raws = new ParameterRawValueList(); - ParameterRawValue raw = new ParameterRawValue(objIds.get(0).getObjIdentityInstanceId(), rawValue); - raws.add(raw); + Long objIdInsID = objIds.get(0).getObjIdentityInstanceId(); + rawValue = (content == null) ? null : rawValue; + raws.add(new ParameterRawValue(objIdInsID, rawValue)); // Ok, now, let's finally set the Value! parameterService.setValue(raws); @@ -398,9 +227,10 @@ public void addDataReceivedListener(final DataReceivedListener listener) { class DataReceivedParameterAdapter extends ParameterAdapter { @Override - public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final Identifier lIdentifier, - final UpdateHeaderList lUpdateHeaderList, final ObjectIdList lObjectIdList, - final ParameterValueList lParameterValueList, final Map qosp) { + public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, + final Identifier lIdentifier, final UpdateHeaderList lUpdateHeaderList, + final ObjectIdList lObjectIdList, final ParameterValueList lParameterValueList, + final Map qosp) { if (lParameterValueList.size() == lUpdateHeaderList.size()) { for (int i = 0; i < lUpdateHeaderList.size(); i++) { @@ -434,8 +264,9 @@ public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final I ObjectId source = lObjectIdList.get(i); Time timestamp = lUpdateHeaderList.get(i).getTimestamp(); - ParameterInstance parameterInstance = new ParameterInstance(new Identifier(parameterName), - lParameterValueList.get(i), source, timestamp); + ParameterInstance parameterInstance = new ParameterInstance(new Identifier( + parameterName), + lParameterValueList.get(i), source, timestamp); ((CompleteDataReceivedListener) listener).onDataReceived(parameterInstance); } @@ -448,9 +279,10 @@ public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final I class DataReceivedAggregationAdapter extends AggregationAdapter { @Override - public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final Identifier lIdentifier, - final UpdateHeaderList lUpdateHeaderList, final ObjectIdList lObjectIdList, - final AggregationValueList lAggregationValueList, final Map qosp) { + public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, + final Identifier lIdentifier, final UpdateHeaderList lUpdateHeaderList, + final ObjectIdList lObjectIdList, final AggregationValueList lAggregationValueList, + final Map qosp) { if (lAggregationValueList.size() == lUpdateHeaderList.size()) { for (int i = 0; i < lUpdateHeaderList.size(); i++) { @@ -461,8 +293,7 @@ public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final I AggregationValue aggregationValue = lAggregationValueList.get(i); for (AggregationSetValue aggregationSetValue : aggregationValue.getParameterSetValues()) { - for (AggregationParameterValue aggregationParamValue : aggregationSetValue - .getValues()) { + for (AggregationParameterValue aggregationParamValue : aggregationSetValue.getValues()) { Long paramDefInstId = aggregationParamValue.getParamDefInstId(); Attribute parameterValue = aggregationParamValue.getValue().getRawValue(); @@ -480,8 +311,8 @@ public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final I String aggregationName = lUpdateHeaderList.get(i).getKey().getFirstSubKey().toString(); AggregationValue aggregationValue = lAggregationValueList.get(i); - AggregationInstance aggregationInstance = new AggregationInstance(new Identifier( - aggregationName), aggregationValue, source, timestamp); + AggregationInstance aggregationInstance = new AggregationInstance( + new Identifier(aggregationName), aggregationValue, source, timestamp); ((CompleteAggregationReceivedListener) listener).onDataReceived(aggregationInstance); } @@ -497,28 +328,31 @@ public void monitorValueNotifyReceived(final MALMessageHeader msgHeader, final I try { // Register for pub-sub of all parameters super.getMCServices().getParameterService().getParameterStub().monitorValueRegister( - this.parameterSubscription, new DataReceivedParameterAdapter()); + this.parameterSubscription, new DataReceivedParameterAdapter()); } catch (MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, null, ex); } catch (NullPointerException ex) { - LOGGER.log(Level.SEVERE, "Null pointer exception when trying to access the Parameter service. " + - "Check if the service consumer was initialized with a proper URI.", ex); + LOGGER.log(Level.SEVERE, + "Null pointer exception when trying to access the Parameter service. " + + "Check if the service consumer was initialized with a proper URI.", + ex); } } - if (listener instanceof SimpleAggregationReceivedListener || - listener instanceof CompleteAggregationReceivedListener) { + if (listener instanceof SimpleAggregationReceivedListener || listener instanceof CompleteAggregationReceivedListener) { // Subscribes to ALL Aggregations this.aggregationSubscription = ConnectionConsumer.subscriptionWildcardRandom(); try { // Register for pub-sub of all aggregations super.getMCServices().getAggregationService().getAggregationStub().monitorValueRegister( - this.aggregationSubscription, new DataReceivedAggregationAdapter()); + this.aggregationSubscription, new DataReceivedAggregationAdapter()); } catch (MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, null, ex); } catch (NullPointerException ex) { - LOGGER.log(Level.SEVERE, "Null pointer exception when trying to access the Aggregation service. " + - "Check if the service consumer was initialized with a proper URI.", ex); + LOGGER.log(Level.SEVERE, + "Null pointer exception when trying to access the Aggregation service. " + + "Check if the service consumer was initialized with a proper URI.", + ex); } } } @@ -545,8 +379,8 @@ public Long launchAction(final String actionName, final Serializable[] objects) if (objId == null) { // Well, then let's create a new Action Definition and add it on the provider... ActionDefinitionDetails actionDefinition = new ActionDefinitionDetails(); - actionDefinition.setDescription("This Definition was automatically generated by: " + - CommonMOAdapterImpl.class.getName()); + actionDefinition.setDescription("This Definition was automatically generated by: " + + CommonMOAdapterImpl.class.getName()); actionDefinition.setProgressStepCount(new UShort((short) 0)); ArgumentDefinitionDetailsList argList = new ArgumentDefinitionDetailsList(objects.length); @@ -639,18 +473,15 @@ public void closeConnections() { IdentifierList idList = new IdentifierList(); idList.add(this.parameterSubscription.getSubscriptionId()); - super.getMCServices().getParameterService().getParameterStub().asyncMonitorValueDeregister(idList, - new ParameterAdapter() { - @Override - public void monitorValueDeregisterAckReceived(MALMessageHeader msgHeader, Map qosProperties) { - parameterSubscription = null; - } - - }); + super.getMCServices().getParameterService().getParameterStub().asyncMonitorValueDeregister(idList, new ParameterAdapter() { + @Override + public void monitorValueDeregisterAckReceived(MALMessageHeader msgHeader, Map qosProperties) { + parameterSubscription = null; + } + }); } catch (MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, null, ex); } - } // Unregister the consumer from the broker @@ -659,13 +490,15 @@ public void monitorValueDeregisterAckReceived(MALMessageHeader msgHeader, Map qo IdentifierList idList = new IdentifierList(); idList.add(this.aggregationSubscription.getSubscriptionId()); - super.getMCServices().getAggregationService().getAggregationStub().asyncMonitorValueDeregister(idList, - new AggregationAdapter() { - @Override - public void monitorValueDeregisterAckReceived(MALMessageHeader msgHeader, Map qosProperties) { - aggregationSubscription = null; - } - }); + super.getMCServices().getAggregationService().getAggregationStub().asyncMonitorValueDeregister( + idList, new AggregationAdapter() { + @Override + public void monitorValueDeregisterAckReceived(MALMessageHeader msgHeader, + Map qosProperties) { + aggregationSubscription = null; + } + } + ); } catch (MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, null, ex); } @@ -702,8 +535,7 @@ public void monitorValueDeregisterAckReceived(MALMessageHeader msgHeader, Map qo } @Override - public Long launchAction(Long defInstId, AttributeValueList argumentValues, ActionAdapter actionAdapter) - throws NMFException { + public Long launchAction(Long defInstId, AttributeValueList argumentValues, ActionAdapter actionAdapter) throws NMFException { Long instanceObjId = null; // Create an ActionInstanceDetails object for the invocation of this action @@ -713,25 +545,40 @@ public Long launchAction(Long defInstId, AttributeValueList argumentValues, Acti IdentifierList argumentIds = null; try { - ActionInstanceDetails instanceDetails = new ActionInstanceDetails(defInstId, stageStartedRequired, - stageProgressRequired, stageCompletedRequired, argumentValues, argumentIds, null); + ActionInstanceDetails instanceDetails + = new ActionInstanceDetails( + defInstId, + stageStartedRequired, + stageProgressRequired, + stageCompletedRequired, + argumentValues, + argumentIds, + null); // Store the Action Instance in the Archive and get an // object instance identifier to use during the submit Long related = defInstId; ObjectId source = null; // TBD - should be the OperationActivity object - SingleConnectionDetails actionConnection = super.getMCServices().getActionService().getConnectionDetails(); + SingleConnectionDetails actionConnection + = super.getMCServices().getActionService().getConnectionDetails(); - ArchiveDetailsList archiveDetailsListActionInstance = HelperArchive.generateArchiveDetailsList(related, - source, actionConnection.getProviderURI()); + ArchiveDetailsList archiveDetailsListActionInstance + = HelperArchive.generateArchiveDetailsList( + related, + source, + actionConnection.getProviderURI()); boolean returnObjInstIds = true; ActionInstanceDetailsList instanceDetailsList = new ActionInstanceDetailsList(); instanceDetailsList.add(instanceDetails); - LongList objIdActionInstances = super.getCOMServices().getArchiveService().getArchiveStub().store( - returnObjInstIds, ActionHelper.ACTIONINSTANCE_OBJECT_TYPE, actionConnection.getDomain(), - archiveDetailsListActionInstance, instanceDetailsList); + LongList objIdActionInstances + = super.getCOMServices().getArchiveService().getArchiveStub().store( + returnObjInstIds, + ActionHelper.ACTIONINSTANCE_OBJECT_TYPE, + actionConnection.getDomain(), + archiveDetailsListActionInstance, + instanceDetailsList); if (objIdActionInstances.size() == 1) { instanceObjId = objIdActionInstances.get(0); @@ -745,8 +592,11 @@ public Long launchAction(Long defInstId, AttributeValueList argumentValues, Acti // out the Transaction ID of the MAL message and include it in the // corresponding OperationActivity // actionService.submitAction(instanceObjId, instanceDetails); - MALMessage msg = super.getMCServices().getActionService().getActionStub().asyncSubmitAction(instanceObjId, - instanceDetails, actionAdapter); + MALMessage msg = super.getMCServices().getActionService().getActionStub().asyncSubmitAction( + instanceObjId, + instanceDetails, + actionAdapter + ); // Store the corresponding OperationActivity object instance in the // Archive and publish its release @@ -756,17 +606,22 @@ public Long launchAction(Long defInstId, AttributeValueList argumentValues, Acti related = null; source = null; // the object that caused this to be created - ArchiveDetailsList archiveDetailsListOp = HelperArchive.generateArchiveDetailsList(related, source, - actionConnection.getProviderURI()); + ArchiveDetailsList archiveDetailsListOp = HelperArchive.generateArchiveDetailsList( + related, + source, + actionConnection.getProviderURI()); Long transId = msg.getHeader().getTransactionId(); archiveDetailsListOp.get(0).setInstId(transId); // requirement: 3.5.2.4 try { returnObjInstIds = false; - super.getCOMServices().getArchiveService().getArchiveStub().store(returnObjInstIds, - ActivityTrackingHelper.OPERATIONACTIVITY_OBJECT_TYPE, actionConnection.getDomain(), - archiveDetailsListOp, opActivityList); + super.getCOMServices().getArchiveService().getArchiveStub().store( + returnObjInstIds, + ActivityTrackingHelper.OPERATIONACTIVITY_OBJECT_TYPE, + actionConnection.getDomain(), + archiveDetailsListOp, + opActivityList); } catch (MALInteractionException ex) { // A duplicate might happen if the consumer stored the Operation Activity object if (ex.getStandardError().getErrorNumber().getValue() != COMHelper.DUPLICATE_ERROR_NUMBER.getValue()) { @@ -779,13 +634,16 @@ public Long launchAction(Long defInstId, AttributeValueList argumentValues, Acti throw new NMFException("The storing of the Operation Activity failed. (2)", ex); } - ObjectId source2 = new ObjectId(ActivityTrackingHelper.OPERATIONACTIVITY_OBJECT_TYPE, new ObjectKey( - actionConnection.getDomain(), transId)); + ObjectId source2 = new ObjectId(ActivityTrackingHelper.OPERATIONACTIVITY_OBJECT_TYPE, + new ObjectKey(actionConnection.getDomain(), transId)); ObjectDetails details = new ObjectDetails(defInstId, source2); archiveDetailsListActionInstance.get(0).setDetails(details); - super.getCOMServices().getArchiveService().getArchiveStub().update(ActionHelper.ACTIONINSTANCE_OBJECT_TYPE, - actionConnection.getDomain(), archiveDetailsListActionInstance, instanceDetailsList); + super.getCOMServices().getArchiveService().getArchiveStub().update( + ActionHelper.ACTIONINSTANCE_OBJECT_TYPE, + actionConnection.getDomain(), + archiveDetailsListActionInstance, + instanceDetailsList); } catch (MALInteractionException | MALException | NMFException ex) { throw new NMFException("Failed to execute Action " + defInstId, ex); } @@ -793,9 +651,12 @@ public Long launchAction(Long defInstId, AttributeValueList argumentValues, Acti return instanceObjId; } - /** {@inheritDoc} */ + /** + * {@inheritDoc} + */ @Override - public void toggleParametersGeneration(List parameterNames, boolean enableGeneration) throws NMFException { + public void toggleParametersGeneration(List parameterNames, boolean enableGeneration) + throws NMFException { // Nothing to do in those cases if (parameterNames == null) { LOGGER.log(Level.WARNING, "Provided parameterNames list is null"); @@ -822,26 +683,28 @@ public void toggleParametersGeneration(List parameterNames, boolean enab if (objIds == null) { throw new NMFException(String.format( - "Error while toggling parameters generation, couldn't get parameters instance IDs (unknown error) for parameters names: %s", - paramNames)); + "Error while toggling parameters generation, couldn't get parameters instance IDs (unknown error) for parameters names: %s", + paramNames)); } // Check how many we got back if (objIds.size() < parameterNames.size()) { if (objIds.size() <= 0) { throw new NMFException(String.format( - "Error while toggling parameters generation, 0 parameters instance IDs found for parameters names: %s", - paramNames)); + "Error while toggling parameters generation, 0 parameters instance IDs found for parameters names: %s", + paramNames)); } else { LOGGER.log(Level.WARNING, String.format( - "Couldn't get some parameters instance IDs, for parameters names: %s", paramNames)); + "Couldn't get some parameters instance IDs, for parameters names: %s", + paramNames)); } } // toggle their generation InstanceBooleanPairList ibpl = new InstanceBooleanPairList(); for (ObjectInstancePair objectInstancePair : objIds) { - ibpl.add(new InstanceBooleanPair(objectInstancePair.getObjIdentityInstanceId(), enableGeneration)); + ibpl.add(new InstanceBooleanPair(objectInstancePair.getObjIdentityInstanceId(), + enableGeneration)); } parameterService.enableGeneration(false, ibpl); } catch (MALInteractionException | MALException e) { diff --git a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java index 5154654ea..858786c19 100644 --- a/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java +++ b/mission/simulator/platform-services-impl/src/main/java/esa/mo/platform/impl/util/PlatformServicesProviderSoftSim.java @@ -61,50 +61,25 @@ */ public class PlatformServicesProviderSoftSim implements PlatformServicesProviderInterface { - // Simulator - private final ESASimulator instrumentsSimulator = new ESASimulator("127.0.0.1"); + // Simulator + private final ESASimulator instrumentsSimulator = new ESASimulator("127.0.0.1"); - // Services - private final ArtificialIntelligenceProviderServiceImpl aiService = new ArtificialIntelligenceProviderServiceImpl(); - private final AutonomousADCSProviderServiceImpl autonomousADCSService = new AutonomousADCSProviderServiceImpl(); - private final CameraProviderServiceImpl cameraService = new CameraProviderServiceImpl(); - private final GPSProviderServiceWithTLEImpl gpsService = new GPSProviderServiceWithTLEImpl(); - private final OpticalDataReceiverProviderServiceImpl opticalDataReceiverService = new OpticalDataReceiverProviderServiceImpl(); - private final SoftwareDefinedRadioProviderServiceImpl sdrService = new SoftwareDefinedRadioProviderServiceImpl(); - private final PowerControlProviderServiceImpl powerService = new PowerControlProviderServiceImpl(); - private PowerControlAdapterInterface pcAdapter; - private final ClockProviderServiceImpl clockService = new ClockProviderServiceImpl(); - - @Override - public void init(COMServicesProvider comServices) throws MALException { - // Check if hybrid setup is used - CameraAdapterInterface camAdapter; - AIMovidiusAdapter aiAdapter; - AutonomousADCSAdapterInterface adcsAdapter; - GPSAdapterInterface gpsAdapter; - OpticalDataReceiverAdapterInterface optRxAdapter; - SoftwareDefinedRadioAdapterInterface sdrAdapter; - ClockAdapterInterface clockAdapter; - - Properties platformProperties = new Properties(); - try { - platformProperties.load(new FileInputStream("platformsim.properties")); - if (platformProperties.getProperty("platform.mode").equals("hybrid")) { - String pcAdapterName = platformProperties.getProperty("pc.adapter"); - String camAdapterName = platformProperties.getProperty("camera.adapter"); - String adcsAdapterName = platformProperties.getProperty("adcs.adapter"); - String gpsAdapterName = platformProperties.getProperty("gps.adapter"); - String optRxAdapterName = platformProperties.getProperty("optrx.adapter"); - String sdrAdapterName = platformProperties.getProperty("sdr.adapter"); - String clockAdapterName = platformProperties.getProperty("clock.adapter"); - - // PowerControl adapter - try { - pcAdapter = (PowerControlAdapterInterface) Class.forName(pcAdapterName).newInstance(); + // Services + private final ArtificialIntelligenceProviderServiceImpl aiService = new ArtificialIntelligenceProviderServiceImpl(); + private final AutonomousADCSProviderServiceImpl autonomousADCSService = new AutonomousADCSProviderServiceImpl(); + private final CameraProviderServiceImpl cameraService = new CameraProviderServiceImpl(); + private final GPSProviderServiceWithTLEImpl gpsService = new GPSProviderServiceWithTLEImpl(); + private final OpticalDataReceiverProviderServiceImpl opticalDataReceiverService = new OpticalDataReceiverProviderServiceImpl(); + private final SoftwareDefinedRadioProviderServiceImpl sdrService = new SoftwareDefinedRadioProviderServiceImpl(); + private final PowerControlProviderServiceImpl powerService = new PowerControlProviderServiceImpl(); + private PowerControlAdapterInterface pcAdapter; + private final ClockProviderServiceImpl clockService = new ClockProviderServiceImpl(); + @Override public void init(COMServicesProvider comServices) throws MALException { // Check if hybrid setup is used CameraAdapterInterface camAdapter; + AIMovidiusAdapter aiAdapter; AutonomousADCSAdapterInterface adcsAdapter; GPSAdapterInterface gpsAdapter; OpticalDataReceiverAdapterInterface optRxAdapter; @@ -129,8 +104,8 @@ public void init(COMServicesProvider comServices) throws MALException { } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the power control adapter. Falling back to default PowerControlSoftSimAdapter.", - e); + "Failed to instantiate the power control adapter. Falling back to default PowerControlSoftSimAdapter.", + e); pcAdapter = new PowerControlSoftSimAdapter(); } @@ -139,38 +114,28 @@ public void init(COMServicesProvider comServices) throws MALException { if (Arrays.asList(Class.forName(camAdapterName).getInterfaces()).contains(SimulatorAdapter.class)) { camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); } else { - Constructor constructor = Class.forName(camAdapterName).getConstructor( - PowerControlAdapterInterface.class); + Constructor constructor = Class.forName(camAdapterName).getConstructor(PowerControlAdapterInterface.class); camAdapter = (CameraAdapterInterface) constructor.newInstance(pcAdapter); } - } catch (InstantiationException | - IllegalAccessException | - ClassNotFoundException | - NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | + ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the camera adapter. Falling back to default CameraSoftSimAdapter.", e); + "Failed to instantiate the camera adapter. Falling back to default CameraSoftSimAdapter.", e); camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); } // ADCS adapter try { - if (Arrays.asList(Class.forName(adcsAdapterName).getInterfaces()).contains( - SimulatorAdapter.class)) { + if (Arrays.asList(Class.forName(adcsAdapterName).getInterfaces()).contains(SimulatorAdapter.class)) { adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); } else { - Constructor constructor = Class.forName(adcsAdapterName).getConstructor( - PowerControlAdapterInterface.class); + Constructor constructor = Class.forName(adcsAdapterName).getConstructor(PowerControlAdapterInterface.class); adcsAdapter = (AutonomousADCSAdapterInterface) constructor.newInstance(pcAdapter); } - } catch (InstantiationException | - IllegalAccessException | - ClassNotFoundException | - NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException + | InvocationTargetException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the iADCS adapter. Falling back to default AutonomousADCSSoftSimAdapter.", - e); + "Failed to instantiate the iADCS adapter. Falling back to default AutonomousADCSSoftSimAdapter.", e); adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); } @@ -179,38 +144,28 @@ public void init(COMServicesProvider comServices) throws MALException { if (Arrays.asList(Class.forName(gpsAdapterName).getInterfaces()).contains(SimulatorAdapter.class)) { gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); } else { - Constructor constructor = Class.forName(gpsAdapterName).getConstructor( - PowerControlAdapterInterface.class); + Constructor constructor = Class.forName(gpsAdapterName).getConstructor(PowerControlAdapterInterface.class); gpsAdapter = (GPSAdapterInterface) constructor.newInstance(pcAdapter); } - } catch (InstantiationException | - IllegalAccessException | - ClassNotFoundException | - NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException + | InvocationTargetException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the GPS adapter. Falling back to default GPSSoftSimAdapter.", e); + "Failed to instantiate the GPS adapter. Falling back to default GPSSoftSimAdapter.", e); gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); } // Optical Data Receiver adapter try { - if (Arrays.asList(Class.forName(optRxAdapterName).getInterfaces()).contains( - SimulatorAdapter.class)) { + if (Arrays.asList(Class.forName(optRxAdapterName).getInterfaces()).contains(SimulatorAdapter.class)) { optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); } else { - Constructor constructor = Class.forName(optRxAdapterName).getConstructor( - PowerControlAdapterInterface.class); + Constructor constructor = Class.forName(optRxAdapterName).getConstructor(PowerControlAdapterInterface.class); optRxAdapter = (OpticalDataReceiverAdapterInterface) constructor.newInstance(pcAdapter); } - } catch (InstantiationException | - IllegalAccessException | - ClassNotFoundException | - NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException + | InvocationTargetException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the optRX adapter. Falling back to default OpticalDataReceiverSoftSimAdapter.", - e); + "Failed to instantiate the optRX adapter. Falling back to default OpticalDataReceiverSoftSimAdapter.", e); optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); } @@ -219,37 +174,33 @@ public void init(COMServicesProvider comServices) throws MALException { if (Arrays.asList(Class.forName(sdrAdapterName).getInterfaces()).contains(SimulatorAdapter.class)) { sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); } else { - Constructor constructor = Class.forName(sdrAdapterName).getConstructor( - PowerControlAdapterInterface.class); + Constructor constructor = Class.forName(sdrAdapterName).getConstructor(PowerControlAdapterInterface.class); sdrAdapter = (SoftwareDefinedRadioAdapterInterface) constructor.newInstance(pcAdapter); } - } catch (InstantiationException | - IllegalAccessException | - ClassNotFoundException | - NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException + | InvocationTargetException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the SDR adapter. Falling back to default SoftwareDefinedRadioSoftSimAdapter.", - e); + "Failed to instantiate the SDR adapter. Falling back to default SoftwareDefinedRadioSoftSimAdapter.", e); sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); } // Clock adapter try { - if (Arrays.asList(Class.forName(clockAdapterName).getInterfaces()).contains( - SimulatorAdapter.class)) { + if (Arrays.asList(Class.forName(clockAdapterName).getInterfaces()).contains(SimulatorAdapter.class)) { clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); } else { clockAdapter = (ClockAdapterInterface) Class.forName(clockAdapterName).newInstance(); } } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Failed to instantiate the clock adapter. Falling back to default ClockSoftSimAdapter", e); + "Failed to instantiate the clock adapter. Falling back to default ClockSoftSimAdapter", e); clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); } + aiAdapter = null; } else { pcAdapter = new PowerControlSoftSimAdapter(); camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); + aiAdapter = new AIMovidiusAdapter(); adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); @@ -259,62 +210,39 @@ public void init(COMServicesProvider comServices) throws MALException { } catch (IOException e) { // Assume simulated environment by default Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Platform config file not found. Using simulated environment."); + "Platform config file not found. Using simulated environment."); pcAdapter = new PowerControlSoftSimAdapter(); camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); + try { + aiAdapter = new AIMovidiusAdapter(); + } catch (IOException ex) { + Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log( + Level.INFO, "The AI adapter could not be started!", ex); + + aiAdapter = null; + } adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); } - aiAdapter = null; - } else { - pcAdapter = new PowerControlSoftSimAdapter(); - camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); - aiAdapter = new AIMovidiusAdapter(); - adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); - gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); - optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); - sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); - clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); - } - } catch (IOException e) { - // Assume simulated environment by default - Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log(Level.WARNING, - "Platform config file not found. Using simulated environment."); - pcAdapter = new PowerControlSoftSimAdapter(); - camAdapter = new CameraSoftSimAdapter(instrumentsSimulator, pcAdapter); - try { - aiAdapter = new AIMovidiusAdapter(); - } catch (IOException ex) { - Logger.getLogger(PlatformServicesProviderSoftSim.class.getName()).log( - Level.INFO, "The AI adapter could not be started!", ex); - - aiAdapter = null; + + autonomousADCSService.init(comServices, adcsAdapter); + if (aiAdapter != null) { + aiService.init(aiAdapter); } - adcsAdapter = new AutonomousADCSSoftSimAdapter(instrumentsSimulator, pcAdapter); - gpsAdapter = new GPSSoftSimAdapter(instrumentsSimulator, pcAdapter); - optRxAdapter = new OpticalDataReceiverSoftSimAdapter(instrumentsSimulator, pcAdapter); - sdrAdapter = new SoftwareDefinedRadioSoftSimAdapter(instrumentsSimulator, pcAdapter); - clockAdapter = new ClockSoftSimAdapter(instrumentsSimulator); + cameraService.init(comServices, camAdapter); + gpsService.init(comServices, gpsAdapter); + opticalDataReceiverService.init(optRxAdapter); + sdrService.init(sdrAdapter); + powerService.init(pcAdapter); + clockService.init(clockAdapter); } - autonomousADCSService.init(comServices, adcsAdapter); - if(aiAdapter != null) { - aiService.init(aiAdapter); + public void startStatusTracking(ConnectionConsumer connection) { + pcAdapter.startStatusTracking(connection); } - cameraService.init(comServices, camAdapter); - gpsService.init(comServices, gpsAdapter); - opticalDataReceiverService.init(optRxAdapter); - sdrService.init(sdrAdapter); - powerService.init(pcAdapter); - clockService.init(clockAdapter); - } - - public void startStatusTracking(ConnectionConsumer connection) { - pcAdapter.startStatusTracking(connection); - } @Override public AutonomousADCSProviderServiceImpl getAutonomousADCSService() { @@ -342,8 +270,8 @@ public SoftwareDefinedRadioInheritanceSkeleton getSoftwareDefinedRadioService() return this.sdrService; } - @Override - public ArtificialIntelligenceInheritanceSkeleton getAIService() { - throw new UnsupportedOperationException("Not supported yet."); - } + @Override + public ArtificialIntelligenceInheritanceSkeleton getAIService() { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/parent/pom.xml b/parent/pom.xml index 1692b4434..04b5d99c4 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -16,7 +16,7 @@ int.esa.ccsds.mo POM - 8.1 + 8 int.esa.nmf diff --git a/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java b/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java index 823131f9c..05898cb60 100644 --- a/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java +++ b/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraHandler.java @@ -47,13 +47,15 @@ import org.orekit.bodies.GeodeticPoint; /** - * Class for handling taking and saving of Photographs and everything else camera related + * Class for handling taking and saving of Photographs and everything else + * camera related * * @author Kevin Otto */ public class CameraAcquisitorSystemCameraHandler { - private static final Logger LOGGER = Logger.getLogger(CameraAcquisitorSystemCameraHandler.class.getName()); + private static final Logger LOGGER = Logger.getLogger( + CameraAcquisitorSystemCameraHandler.class.getName()); // photographNow action name public static final String ACTION_PHOTOGRAPH_NOW = "photographNow"; @@ -73,8 +75,9 @@ public class CameraAcquisitorSystemCameraHandler { public CameraAcquisitorSystemCameraHandler(CameraAcquisitorSystemMCAdapter casMCAdapter) { this.casMCAdapter = casMCAdapter; - this.defaultCameraResolution = new PixelResolution(new UInteger(defaultPictureWidth), new UInteger( - defaultPictureHeight)); + this.defaultCameraResolution + = new PixelResolution(new UInteger(defaultPictureWidth), new UInteger( + defaultPictureHeight)); } /** @@ -87,24 +90,28 @@ public CameraAcquisitorSystemCameraHandler(CameraAcquisitorSystemMCAdapter casMC * @param interaction * @return */ - UInteger photographNow(Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { + UInteger photographNow(Long actionInstanceObjId, + boolean reportProgress, MALInteraction interaction) { class AdapterImpl extends GPSAdapter { @Override - public void getTLEResponseReceived(MALMessageHeader msgHeader, TwoLineElementSet tle, Map qosProperties) { + public void getTLEResponseReceived(MALMessageHeader msgHeader, TwoLineElementSet tle, + Map qosProperties) { LOGGER.log(Level.INFO, "TLE: {0}", tle); } @Override - public void getTLEAckErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + public void getTLEAckErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { LOGGER.log(Level.INFO, "TLE ERROR: {0}", error.toString()); } } try { - this.casMCAdapter.getConnector().getPlatformServices().getGPSService().getTLE(new AdapterImpl()); + this.casMCAdapter.getConnector().getPlatformServices().getGPSService().getTLE( + new AdapterImpl()); } catch (Exception e) { LOGGER.log(Level.SEVERE, "[TLE TEST]", e); @@ -131,7 +138,7 @@ private class CameraDataHandler extends CameraAdapter { private final String fileName; CameraDataHandler(Long actionInstanceObjId, int stageOffset, int totalStages, String fileName, - CameraAcquisitorSystemMCAdapter casMCAdapter) { + CameraAcquisitorSystemMCAdapter casMCAdapter) { this.actionInstanceObjId = actionInstanceObjId; this.stageOffset = stageOffset; this.totalStage = totalStages + PHOTOGRAPH_NOW_STAGES; @@ -140,14 +147,18 @@ private class CameraDataHandler extends CameraAdapter { } @Override - public void takePictureResponseReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - org.ccsds.moims.mo.platform.camera.structures.Picture picture, java.util.Map qosProperties) { + public void takePictureResponseReceived( + org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, + org.ccsds.moims.mo.platform.camera.structures.Picture picture, + java.util.Map qosProperties) { // report action progress try { - this.casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, STAGE_RECIVED + - this.stageOffset, this.totalStage, this.actionInstanceObjId); + this.casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, + STAGE_RECIVED + this.stageOffset, + this.totalStage, this.actionInstanceObjId); } catch (NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); + LOGGER.log(Level.SEVERE, null, + ex); } // @@ -165,15 +176,15 @@ public void takePictureResponseReceived(org.ccsds.moims.mo.mal.transport.MALMess try { GeodeticPoint position = this.casMCAdapter.getGpsHandler().getCurrentPosition(); - posString = String.valueOf(FastMath.toDegrees(position.getLatitude())) + "_" + String.valueOf(FastMath - .toDegrees(position.getLongitude())); + posString = String.valueOf(FastMath.toDegrees(position.getLatitude())) + "_" + String.valueOf( + FastMath.toDegrees(position.getLongitude())); } catch (Exception ex) { LOGGER.log(Level.SEVERE, "getCurrentPosition Failed!/n {0}", ex); } // create filename - final String filenamePrefix = folder + File.separator + timeNow + "_" + posString + "_" + this.fileName + - "_" + this.actionInstanceObjId; + final String filenamePrefix + = folder + File.separator + timeNow + "_" + posString + "_" + this.fileName + "_" + this.actionInstanceObjId; try { // Store it in a file! if (picture.getSettings().getFormat().equals(PictureFormat.RAW)) { @@ -204,87 +215,100 @@ public void takePictureResponseReceived(org.ccsds.moims.mo.mal.transport.MALMess // report action progress try { - this.casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, STAGE_FIN + this.stageOffset, - this.totalStage, this.actionInstanceObjId); + this.casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, + STAGE_FIN + this.stageOffset, + this.totalStage, this.actionInstanceObjId); } catch (NMFException ex) { - LOGGER.log(Level.SEVERE, "The action progress could not be reported!", ex); + LOGGER.log(Level.SEVERE, + "The action progress could not be reported!", ex); } // } @Override - public void takePictureAckErrorReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - org.ccsds.moims.mo.mal.MALStandardError error, java.util.Map qosProperties) { + public void takePictureAckErrorReceived( + org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, + org.ccsds.moims.mo.mal.MALStandardError error, + java.util.Map qosProperties) { try { - this.casMCAdapter.getConnector().reportActionExecutionProgress(false, 1, STAGE_RECIVED + - this.stageOffset, this.totalStage, this.actionInstanceObjId); - LOGGER.log(Level.WARNING, "takePicture ack error received {0}", error.toString()); + this.casMCAdapter.getConnector().reportActionExecutionProgress(false, 1, + STAGE_RECIVED + this.stageOffset, + this.totalStage, this.actionInstanceObjId); + LOGGER.log(Level.WARNING, + "takePicture ack error received {0}", error.toString()); } catch (NMFException ex) { - LOGGER.log(Level.SEVERE, "takePicture ack error " + error.toString() + " could not be reported!", ex); + LOGGER.log(Level.SEVERE, + "takePicture ack error " + error.toString() + " could not be reported!", + ex); } } @Override - public void takePictureResponseErrorReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - org.ccsds.moims.mo.mal.MALStandardError error, java.util.Map qosProperties) { + public void takePictureResponseErrorReceived( + org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, + org.ccsds.moims.mo.mal.MALStandardError error, + java.util.Map qosProperties) { try { - this.casMCAdapter.getConnector().reportActionExecutionProgress(false, 1, STAGE_RECIVED + - this.stageOffset, this.totalStage, this.actionInstanceObjId); - LOGGER.log(Level.WARNING, "takePicture response error received {0}", error.toString()); + this.casMCAdapter.getConnector().reportActionExecutionProgress(false, 1, + STAGE_RECIVED + this.stageOffset, + this.totalStage, this.actionInstanceObjId); + LOGGER.log(Level.WARNING, + "takePicture response error received {0}", error.toString()); } catch (NMFException ex) { - LOGGER.log(Level.SEVERE, "takePicture response error " + error.toString() + " could not be reported!", - ex); + LOGGER.log(Level.SEVERE, + "takePicture response error " + error.toString() + " could not be reported!", + ex); } } } - } - - /** - * Takes a photograph (instantly) - * - * @param actionInstanceObjId the Instance ID of the action that triggers the Photograph - * @param stageOffset number of states that where already executed before taking a - * photograph - * @param totalStages total number of Stages (including all stages needed for a - * photograph) - * @param fileName a text that is added at the end of the filename (before the file - * ending) - * @throws NMFException - * @throws IOException - * @throws MALInteractionException - * @throws MALException - */ - public void takePhotograph(long actionInstanceObjId, int stageOffset, int totalStages, - String fileName) throws - NMFException, - IOException, - MALInteractionException, - MALException - { - PixelResolution resolution = new PixelResolution( - new UInteger(casMCAdapter.getPictureWidth()), - new UInteger(casMCAdapter.getPictureHeight())); - - CameraAdapter adapter = new CameraDataHandler(actionInstanceObjId, stageOffset, totalStages, - fileName, - this.casMCAdapter); - - CameraSettings settings = new CameraSettings( - resolution, - casMCAdapter.getPictureType(), - new Duration(casMCAdapter.getExposureTime()), - casMCAdapter.getGainRed(), - casMCAdapter.getGainGreen(), - casMCAdapter.getGainBlue(), - null); - - if (casMCAdapter.getExposureType() == CameraAcquisitorSystemMCAdapter.ExposureTypeModeEnum.AUTOMATIC) { - LOGGER.log(Level.INFO, "Taking Photograph with automatic exposure"); - this.casMCAdapter.getConnector().getPlatformServices().getCameraService() - .takeAutoExposedPicture(settings, adapter); - } else { - LOGGER.log(Level.INFO, "Taking Photograph with manual exposure"); - this.casMCAdapter.getConnector().getPlatformServices().getCameraService() - .takePicture(settings, adapter); + + /** + * Takes a photograph (instantly) + * + * @param actionInstanceObjId the Instance ID of the action that triggers + * the Photograph + * @param stageOffset number of states that where already executed before + * taking a photograph + * @param totalStages total number of Stages (including all stages needed + * for a photograph) + * @param fileName a text that is added at the end of the filename (before + * the file ending) + * @throws NMFException + * @throws IOException + * @throws MALInteractionException + * @throws MALException + */ + public void takePhotograph(long actionInstanceObjId, int stageOffset, int totalStages, + String fileName) throws + NMFException, + IOException, + MALInteractionException, + MALException { + PixelResolution resolution = new PixelResolution( + new UInteger(casMCAdapter.getPictureWidth()), + new UInteger(casMCAdapter.getPictureHeight())); + + CameraAdapter adapter = new CameraDataHandler(actionInstanceObjId, stageOffset, totalStages, + fileName, + this.casMCAdapter); + + CameraSettings settings = new CameraSettings( + resolution, + casMCAdapter.getPictureType(), + new Duration(casMCAdapter.getExposureTime()), + casMCAdapter.getGainRed(), + casMCAdapter.getGainGreen(), + casMCAdapter.getGainBlue(), + null); + + if (casMCAdapter.getExposureType() == CameraAcquisitorSystemMCAdapter.ExposureTypeModeEnum.AUTOMATIC) { + LOGGER.log(Level.INFO, "Taking Photograph with automatic exposure"); + this.casMCAdapter.getConnector().getPlatformServices().getCameraService() + .takeAutoExposedPicture(settings, adapter); + } else { + LOGGER.log(Level.INFO, "Taking Photograph with manual exposure"); + this.casMCAdapter.getConnector().getPlatformServices().getCameraService() + .takePicture(settings, adapter); + } } } diff --git a/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraTargetHandler.java b/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraTargetHandler.java index 34d992702..81a5dad06 100644 --- a/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraTargetHandler.java +++ b/sdk/examples/space/camera-acquisitor-system/src/main/java/esa/mo/nmf/apps/CameraAcquisitorSystemCameraTargetHandler.java @@ -73,8 +73,8 @@ public CameraAcquisitorSystemCameraTargetHandler(CameraAcquisitorSystemMCAdapter this.casMCAdapter = casMCAdapter; } - UInteger photographLocation(AttributeValueList attributeValues, Long actionInstanceObjId, boolean reportProgress, - MALInteraction interaction) { + UInteger photographLocation(AttributeValueList attributeValues, + Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { // get parameters Double latitude = HelperAttributes.attribute2double(attributeValues.get(0).getValue()); Double longitude = HelperAttributes.attribute2double(attributeValues.get(1).getValue()); @@ -83,8 +83,8 @@ UInteger photographLocation(AttributeValueList attributeValues, Long actionInsta return photographLocation(latitude, longitude, timeStamp, actionInstanceObjId, reportProgress, interaction); } - UInteger photographLocation(double latitude, double longitude, String timeStamp, Long actionInstanceObjId, - boolean reportProgress, MALInteraction interaction) { + UInteger photographLocation(double latitude, double longitude, String timeStamp, + Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { AbsoluteDate targetDate = new AbsoluteDate(timeStamp, TimeScalesFactory.getUTC()); double seconds = targetDate.durationFrom(CameraAcquisitorSystemMCAdapter.getNow()); @@ -94,25 +94,28 @@ UInteger photographLocation(double latitude, double longitude, String timeStamp, @Override public void run() { try { - casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, STAGE_WAIT_FOR_PASS, - PHOTOGRAPH_LOCATION_STAGES, actionInstanceObjId); + casMCAdapter.getConnector().reportActionExecutionProgress( + true, + 0, + STAGE_WAIT_FOR_PASS, + PHOTOGRAPH_LOCATION_STAGES, + actionInstanceObjId); } catch (NMFException ex) { LOGGER.log(Level.SEVERE, null, ex); } - Duration timeTillPhotograph = new Duration(targetDate.durationFrom(CameraAcquisitorSystemMCAdapter - .getNow())); + Duration timeTillPhotograph = new Duration(targetDate.durationFrom(CameraAcquisitorSystemMCAdapter.getNow())); // set desired attitude using target latitude and longitude AttitudeMode desiredAttitude = new AttitudeModeTargetTracking((float) latitude, (float) longitude); try { casMCAdapter.getConnector().getPlatformServices().getAutonomousADCSService().setDesiredAttitude( - new Duration(timeTillPhotograph.getValue() + casMCAdapter.getAttitudeSaftyMarginSeconds()), - desiredAttitude); + new Duration(timeTillPhotograph.getValue() + casMCAdapter.getAttitudeSaftyMarginSeconds()), + desiredAttitude); - casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, STAGE_ATTITUDE_CORECTION, - PHOTOGRAPH_LOCATION_STAGES, actionInstanceObjId); + casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, + STAGE_ATTITUDE_CORECTION, PHOTOGRAPH_LOCATION_STAGES, actionInstanceObjId); LOGGER.log(Level.INFO, "Attitude Correction Running"); } catch (NMFException | IOException | MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, null, ex); @@ -131,22 +134,22 @@ public void run() { } try { - casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, STAGE_WAIT_FOR_OPTIMAL_PASS, - PHOTOGRAPH_LOCATION_STAGES, actionInstanceObjId); + casMCAdapter.getConnector().reportActionExecutionProgress(true, 0, + STAGE_WAIT_FOR_OPTIMAL_PASS, PHOTOGRAPH_LOCATION_STAGES, actionInstanceObjId); LOGGER.log(Level.INFO, "Finished waiting for Pass"); // trigger photograph LOGGER.log(Level.INFO, "Taking Photograph now"); - casMCAdapter.getCameraHandler().takePhotograph(actionInstanceObjId, STAGE_WAIT_FOR_OPTIMAL_PASS, - PHOTOGRAPH_LOCATION_STAGES, ""); - + casMCAdapter.getCameraHandler().takePhotograph(actionInstanceObjId, + STAGE_WAIT_FOR_OPTIMAL_PASS, PHOTOGRAPH_LOCATION_STAGES, ""); } catch (NMFException | IOException | MALInteractionException | MALException ex) { LOGGER.log(Level.SEVERE, ex.getMessage()); } } }; - this.timer.schedule(task, ((long) seconds) * 1000 - this.casMCAdapter.getWorstCaseRotationTimeMS() //conversion to milliseconds + this.timer.schedule(task, + ((long) seconds) * 1000 - this.casMCAdapter.getWorstCaseRotationTimeMS() //conversion to milliseconds ); LOGGER.log(Level.INFO, "Starting Timer for Photograph, Number of Seconds: {0}", seconds); @@ -154,7 +157,8 @@ public void run() { } /** - * recovers all scheduled photographs in case of a crash or a reboot of the system. + * recovers all scheduled photographs in case of a crash or a reboot of the + * system. */ void recoverLastState() { // get previous requests @@ -179,13 +183,13 @@ void recoverLastState() { if (casMCAdapter.getConnector().getCOMServices().getArchiveService() != null) { LOGGER.log(Level.INFO, "Archive Service found."); - casMCAdapter.getConnector().getCOMServices().getArchiveService().query(true, new ObjectType( - // new UShort(4), new UShort(1), new UOctet((short) 1), new UShort(3)), - new UShort(0), new UShort(0), new UOctet((short) 0), new UShort(0)), archiveQueryList, null, - archiveAdapter); + casMCAdapter.getConnector().getCOMServices().getArchiveService().query( + true, new ObjectType( + // new UShort(4), new UShort(1), new UOctet((short) 1), new UShort(3)), + new UShort(0), new UShort(0), new UOctet((short) 0), new UShort(0)), + archiveQueryList, null, archiveAdapter); } else { LOGGER.log(Level.INFO, "NO Archive Service found!"); - } } catch (NMFException | MALException | MALInteractionException ex) { LOGGER.log(Level.SEVERE, null, ex); @@ -202,8 +206,9 @@ public SchedulerArchiveAdapter() { } @Override - public MALMessage sendResponse(ObjectType objType, IdentifierList domain, ArchiveDetailsList objDetails, - ElementList objBodies) throws MALInteractionException, MALException { + public MALMessage sendResponse(ObjectType objType, IdentifierList domain, + ArchiveDetailsList objDetails, ElementList objBodies) + throws MALInteractionException, MALException { if (objBodies != null) { int i = 0; for (Object objBody : objBodies) { @@ -215,11 +220,14 @@ public MALMessage sendResponse(ObjectType objType, IdentifierList domain, Archiv AbsoluteDate targetDate = new AbsoluteDate(timeStamp, TimeScalesFactory.getUTC()); if (targetDate.compareTo(CameraAcquisitorSystemMCAdapter.getNow()) > 0) { - photographLocation(instance.getArgumentValues(), objDetails.get(i).getInstId(), - true, null); + photographLocation(instance.getArgumentValues(), objDetails.get( + i).getInstId(), true, + null); LOGGER.log(Level.INFO, "recovered action: {0} latitude:{1} longitude:{2}", - new Object[]{timeStamp, instance.getArgumentValues().get(0).getValue() - .toString(), instance.getArgumentValues().get(1).getValue().toString()}); + new Object[]{ + timeStamp, + instance.getArgumentValues().get(0).getValue().toString(), + instance.getArgumentValues().get(1).getValue().toString()}); } } catch (Exception e) { LOGGER.log(Level.WARNING, "recover action failed: {0}", e.getMessage()); @@ -237,8 +245,9 @@ public MALMessage sendAcknowledgement() throws MALInteractionException, MALExcep } @Override - public MALMessage sendUpdate(ObjectType objType, IdentifierList domain, ArchiveDetailsList objDetails, - ElementList objBodies) throws MALInteractionException, MALException { + public MALMessage sendUpdate(ObjectType objType, IdentifierList domain, + ArchiveDetailsList objDetails, ElementList objBodies) + throws MALInteractionException, MALException { sendResponse(objType, domain, objDetails, objBodies); return null; } diff --git a/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java b/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java index 3c84e13d6..d638cbb33 100644 --- a/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java +++ b/sdk/examples/space/camera/src/main/java/esa/mo/nmf/apps/MCSnapNMFAdapter.java @@ -70,34 +70,16 @@ public class MCSnapNMFAdapter extends MonitorAndControlNMFAdapter { private static final String ACTION_TAKE_PICTURE_RAW = "TakeSnap.RAW"; private static final String ACTION_TAKE_PICTURE_JPG = "TakeSnap.JPG"; - PixelResolution resolution = new PixelResolution(new UInteger(width), new UInteger(height)); - - if (ACTION_TAKE_PICTURE_RAW.equals(name.getValue())) { - try { - DataReceivedAdapter adapter = new DataReceivedAdapter(actionInstanceObjId); - connector.getPlatformServices().getCameraService().takePicture( - new CameraSettings(resolution, PictureFormat.RAW, new Duration(0.200), - DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B, null), - adapter - ); - return null; // Success! - } catch (MALInteractionException | MALException | IOException | NMFException ex) { - Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, null, ex); - } - } - - if (ACTION_TAKE_PICTURE_JPG.equals(name.getValue())) { - try { - DataReceivedAdapter adapter = new DataReceivedAdapter(actionInstanceObjId); - connector.getPlatformServices().getCameraService().takePicture( - new CameraSettings(resolution, PictureFormat.JPG, new Duration(0.200), - DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B, null), - adapter - ); - return null; // Success! - } catch (MALInteractionException | MALException | IOException | NMFException ex) { - Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, null, ex); - } + private final AtomicInteger snapsTaken = new AtomicInteger(0); + private final int width = 2048; + private final int height = 1944; + private final int TOTAL_STAGES = 3; + private final float DEFAULT_GAIN_R = 10; + private final float DEFAULT_GAIN_G = 8; + private final float DEFAULT_GAIN_B = 10; + + public void setNMF(NMFInterface connector) { + this.connector = connector; } @Override @@ -108,8 +90,15 @@ public void initialRegistrations(MCRegistration registration) { ParameterDefinitionDetailsList defs = new ParameterDefinitionDetailsList(); IdentifierList paramNames = new IdentifierList(); - defs.add(new ParameterDefinitionDetails("The number of snaps taken.", Union.STRING_SHORT_FORM.byteValue(), "", - false, new Duration(10), null, null)); + defs.add(new ParameterDefinitionDetails( + "The number of snaps taken.", + Union.STRING_SHORT_FORM.byteValue(), + "", + false, + new Duration(10), + null, + null + )); paramNames.add(new Identifier(PARAMETER_SNAPS_TAKEN)); registration.registerParameters(paramNames, defs); @@ -125,16 +114,24 @@ public void initialRegistrations(MCRegistration registration) { Byte convertedType = null; String convertedUnit = null; - arguments1.add(new ArgumentDefinitionDetails(new Identifier("1"), null, rawType, rawUnit, - conditionalConversions, convertedType, convertedUnit)); + arguments1.add(new ArgumentDefinitionDetails(new Identifier("1"), null, + rawType, rawUnit, conditionalConversions, convertedType, convertedUnit)); } - actionDefs.add(new ActionDefinitionDetails("Uses the NMF Camera service to take a picture.", new UOctet( - (short) 0), new UShort(TOTAL_STAGES), arguments1)); + actionDefs.add(new ActionDefinitionDetails( + "Uses the NMF Camera service to take a picture.", + new UOctet((short) 0), + new UShort(TOTAL_STAGES), + arguments1 + )); actionNames.add(new Identifier(ACTION_TAKE_PICTURE_RAW)); - actionDefs.add(new ActionDefinitionDetails("Uses the NMF Camera service to take a picture.", new UOctet( - (short) 0), new UShort(TOTAL_STAGES), arguments1)); + actionDefs.add(new ActionDefinitionDetails( + "Uses the NMF Camera service to take a picture.", + new UOctet((short) 0), + new UShort(TOTAL_STAGES), + arguments1 + )); actionNames.add(new Identifier(ACTION_TAKE_PICTURE_JPG)); registration.registerActions(actionNames, actionDefs); @@ -159,8 +156,8 @@ public Boolean onSetValue(IdentifierList identifiers, ParameterRawValueList valu } @Override - public UInteger actionArrived(Identifier name, AttributeValueList attributeValues, Long actionInstanceObjId, - boolean reportProgress, MALInteraction interaction) { + public UInteger actionArrived(Identifier name, AttributeValueList attributeValues, + Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction) { if (connector == null) { return new UInteger(0); } @@ -169,9 +166,12 @@ public UInteger actionArrived(Identifier name, AttributeValueList attributeValue if (ACTION_TAKE_PICTURE_RAW.equals(name.getValue())) { try { - connector.getPlatformServices().getCameraService().takePicture(new CameraSettings(resolution, - PictureFormat.RAW, new Duration(0.200), DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B), - new DataReceivedAdapter(actionInstanceObjId)); + DataReceivedAdapter adapter = new DataReceivedAdapter(actionInstanceObjId); + connector.getPlatformServices().getCameraService().takePicture( + new CameraSettings(resolution, PictureFormat.RAW, new Duration(0.200), + DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B, null), + adapter + ); return null; // Success! } catch (MALInteractionException | MALException | IOException | NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, null, ex); @@ -180,9 +180,12 @@ PictureFormat.RAW, new Duration(0.200), DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_ if (ACTION_TAKE_PICTURE_JPG.equals(name.getValue())) { try { - connector.getPlatformServices().getCameraService().takePicture(new CameraSettings(resolution, - PictureFormat.JPG, new Duration(0.200), DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B), - new DataReceivedAdapter(actionInstanceObjId)); + DataReceivedAdapter adapter = new DataReceivedAdapter(actionInstanceObjId); + connector.getPlatformServices().getCameraService().takePicture( + new CameraSettings(resolution, PictureFormat.JPG, new Duration(0.200), + DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_GAIN_B, null), + adapter + ); return null; // Success! } catch (MALInteractionException | MALException | IOException | NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, null, ex); @@ -194,8 +197,8 @@ PictureFormat.JPG, new Duration(0.200), DEFAULT_GAIN_R, DEFAULT_GAIN_G, DEFAULT_ public class DataReceivedAdapter extends CameraAdapter { - private static final int STAGE_ACK = 1; - private static final int STAGE_RSP = 2; + private final int STAGE_ACK = 1; + private final int STAGE_RSP = 2; private final Long actionInstanceObjId; DataReceivedAdapter(Long actionInstanceObjId) { @@ -204,18 +207,18 @@ public class DataReceivedAdapter extends CameraAdapter { @Override public void takePictureAckReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - java.util.Map qosProperties) { + java.util.Map qosProperties) { try { connector.reportActionExecutionProgress(true, 0, STAGE_ACK, TOTAL_STAGES, actionInstanceObjId); } catch (NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, - "The action progress could not be reported!", ex); + "The action progress could not be reported!", ex); } } @Override public void takePictureResponseReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - org.ccsds.moims.mo.platform.camera.structures.Picture picture, java.util.Map qosProperties) { + org.ccsds.moims.mo.platform.camera.structures.Picture picture, java.util.Map qosProperties) { // The picture was received! snapsTaken.incrementAndGet(); @@ -223,7 +226,7 @@ public void takePictureResponseReceived(org.ccsds.moims.mo.mal.transport.MALMess connector.reportActionExecutionProgress(true, 0, STAGE_RSP, TOTAL_STAGES, actionInstanceObjId); } catch (NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, - "The action progress could not be reported!", ex); + "The action progress could not be reported!", ex); } final String folder = "toGround"; @@ -266,32 +269,30 @@ public void takePictureResponseReceived(org.ccsds.moims.mo.mal.transport.MALMess connector.reportActionExecutionProgress(true, 0, 3, TOTAL_STAGES, actionInstanceObjId); } catch (NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, - "The action progress could not be reported!", ex); + "The action progress could not be reported!", ex); } } @Override public void takePictureAckErrorReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - org.ccsds.moims.mo.mal.MALStandardError error, java.util.Map qosProperties) { + org.ccsds.moims.mo.mal.MALStandardError error, java.util.Map qosProperties) { try { connector.reportActionExecutionProgress(false, 1, STAGE_ACK, TOTAL_STAGES, actionInstanceObjId); } catch (NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, - "The action progress could not be reported!", ex); + "The action progress could not be reported!", ex); } } @Override public void takePictureResponseErrorReceived(org.ccsds.moims.mo.mal.transport.MALMessageHeader msgHeader, - org.ccsds.moims.mo.mal.MALStandardError error, java.util.Map qosProperties) { + org.ccsds.moims.mo.mal.MALStandardError error, java.util.Map qosProperties) { try { connector.reportActionExecutionProgress(false, 1, STAGE_RSP, TOTAL_STAGES, actionInstanceObjId); } catch (NMFException ex) { Logger.getLogger(MCSnapNMFAdapter.class.getName()).log(Level.SEVERE, - "The action progress could not be reported!", ex); + "The action progress could not be reported!", ex); } } - } - } diff --git a/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java b/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java index 6607ba337..6f24213df 100644 --- a/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java +++ b/sdk/examples/space/payloads-test/src/main/java/esa/mo/nmf/apps/PayloadsTestActionsHandler.java @@ -65,8 +65,8 @@ public PayloadsTestActionsHandler(PayloadsTestMCAdapter payloadsTestMCAdapter) { this.payloadsTestMCAdapter = payloadsTestMCAdapter; } - public UInteger executeAdcsModeAction(Duration duration, AttitudeMode attitudeMode, - PayloadsTestMCAdapter payloadsTestMCAdapter) { + public UInteger executeAdcsModeAction(Duration duration, + AttitudeMode attitudeMode, PayloadsTestMCAdapter payloadsTestMCAdapter) { if (duration != null) { // Negative Durations are not allowed! if (duration.getValue() < 0) { @@ -78,8 +78,7 @@ public UInteger executeAdcsModeAction(Duration duration, AttitudeMode attitudeMo } } try { - payloadsTestMCAdapter.nmf.getPlatformServices().getAutonomousADCSService().setDesiredAttitude(duration, - attitudeMode); + payloadsTestMCAdapter.nmf.getPlatformServices().getAutonomousADCSService().setDesiredAttitude(duration, attitudeMode); } catch (MALInteractionException | MALException | NMFException ex) { LOGGER.log(Level.SEVERE, null, ex); return new UInteger(3); @@ -90,8 +89,8 @@ public UInteger executeAdcsModeAction(Duration duration, AttitudeMode attitudeMo return null; // Success } - public UInteger scheduleTakePicture(Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction, - Duration scheduleDelay, PictureFormat format, boolean autoExposed) { + public UInteger scheduleTakePicture(Long actionInstanceObjId, boolean reportProgress, + MALInteraction interaction, Duration scheduleDelay, PictureFormat format, boolean autoExposed) { Timer timer = new Timer(); long delay = (long) (scheduleDelay.getValue() * 1000L); if (delay < 0) { @@ -104,24 +103,27 @@ public void run() { String actionName; switch (format.getOrdinal()) { case PictureFormat._BMP_INDEX: - if (autoExposed) + if (autoExposed) { actionName = "takeAutoExposedPicture_BMP"; - else + } else { actionName = "takePicture_BMP"; + } break; case PictureFormat._RAW_INDEX: - if (autoExposed) + if (autoExposed) { actionName = "takeAutoExposedPicture_RAW"; - else + } else { actionName = "takePicture_RAW"; + } break; case PictureFormat._PNG_INDEX: case PictureFormat._JPG_INDEX: default: - if (autoExposed) + if (autoExposed) { actionName = "takeAutoExposedPicture_JPG"; - else + } else { actionName = "takePicture_JPG"; + } break; } payloadsTestMCAdapter.simpleCommandingInterface.launchAction(actionName, new Serializable[]{}); @@ -130,54 +132,48 @@ public void run() { return null; // Success! } - public UInteger takePicture( - Long actionInstanceObjId, - boolean reportProgress, - MALInteraction interaction, - PictureFormat format) - { - try { - payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takePicture( - new CameraSettings( - payloadsTestMCAdapter.defaultCameraResolution, - format, - new Duration(payloadsTestMCAdapter.cameraExposureTime), - payloadsTestMCAdapter.cameraGainR, - payloadsTestMCAdapter.cameraGainG, - payloadsTestMCAdapter.cameraGainB, - null), - new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); - return null; // Success! - } catch (MALInteractionException | MALException | IOException | NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); - return new UInteger(1); + public UInteger takePicture(Long actionInstanceObjId, boolean reportProgress, + MALInteraction interaction, PictureFormat format) { + try { + payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takePicture( + new CameraSettings( + payloadsTestMCAdapter.defaultCameraResolution, + format, + new Duration(payloadsTestMCAdapter.cameraExposureTime), + payloadsTestMCAdapter.cameraGainR, + payloadsTestMCAdapter.cameraGainG, + payloadsTestMCAdapter.cameraGainB, + null), + new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); + return null; // Success! + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return new UInteger(1); + } } - public UInteger takeAutoExposedPicture( - Long actionInstanceObjId, - boolean reportProgress, - MALInteraction interaction, - PictureFormat format) - { - try { - payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takeAutoExposedPicture( - new CameraSettings( - payloadsTestMCAdapter.defaultCameraResolution, - format, - new Duration(payloadsTestMCAdapter.cameraExposureTime), - payloadsTestMCAdapter.cameraGainR, - payloadsTestMCAdapter.cameraGainG, - payloadsTestMCAdapter.cameraGainB, - null), - new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); - return null; // Success! - } catch (MALInteractionException | MALException | IOException | NMFException ex) { - LOGGER.log(Level.SEVERE, null, ex); - return new UInteger(1); + public UInteger takeAutoExposedPicture(Long actionInstanceObjId, + boolean reportProgress, MALInteraction interaction, PictureFormat format) { + try { + payloadsTestMCAdapter.nmf.getPlatformServices().getCameraService().takeAutoExposedPicture( + new CameraSettings( + payloadsTestMCAdapter.defaultCameraResolution, + format, + new Duration(payloadsTestMCAdapter.cameraExposureTime), + payloadsTestMCAdapter.cameraGainR, + payloadsTestMCAdapter.cameraGainG, + payloadsTestMCAdapter.cameraGainB, + null), + new PayloadsTestCameraDataHandler(actionInstanceObjId, payloadsTestMCAdapter)); + return null; // Success! + } catch (MALInteractionException | MALException | IOException | NMFException ex) { + LOGGER.log(Level.SEVERE, null, ex); + return new UInteger(1); + } } - public UInteger setDeviceState(Long actionInstanceObjId, boolean reportProgress, MALInteraction interaction, - UInteger deviceType, boolean setOn) { + public UInteger setDeviceState(Long actionInstanceObjId, boolean reportProgress, + MALInteraction interaction, UInteger deviceType, boolean setOn) { try { DeviceList deviceList = new DeviceList(); deviceList.add(new Device(setOn, null, null, DeviceType.fromNumericValue(deviceType))); @@ -193,20 +189,20 @@ public UInteger recordSDRData(Long actionInstanceObjId, boolean reportProgress, try { if (!sdrRegistered) { payloadsTestMCAdapter.nmf.getPlatformServices().getSoftwareDefinedRadioService().streamRadioRegister( - ConnectionConsumer.subscriptionWildcardRandom(), new PayloadsTestSDRDataHandler()); + ConnectionConsumer.subscriptionWildcardRandom(), new PayloadsTestSDRDataHandler()); sdrRegistered = true; } - SDRConfiguration config = new SDRConfiguration(SDR_CENTER_FREQUENCY, SDR_RX_GAIN, SDR_LPF_BW, - SDR_SAMPLING_FREQUENCY); - payloadsTestMCAdapter.nmf.getPlatformServices().getSoftwareDefinedRadioService().enableSDR(true, config, - SDR_REPORTING_INTERVAL); + SDRConfiguration config = new SDRConfiguration(SDR_CENTER_FREQUENCY, + SDR_RX_GAIN, SDR_LPF_BW, SDR_SAMPLING_FREQUENCY); + payloadsTestMCAdapter.nmf.getPlatformServices().getSoftwareDefinedRadioService().enableSDR( + true, config, SDR_REPORTING_INTERVAL); Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { try { payloadsTestMCAdapter.nmf.getPlatformServices().getSoftwareDefinedRadioService().enableSDR( - false, config, SDR_REPORTING_INTERVAL); + false, config, SDR_REPORTING_INTERVAL); } catch (MALInteractionException | MALException | IOException | NMFException ex) { LOGGER.log(Level.SEVERE, "Failed to stop the SDR", ex); } diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java index b6c05dc41..2f0c42e53 100644 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java +++ b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/DirectoryConnectionConsumerPanel.java @@ -60,115 +60,111 @@ */ public class DirectoryConnectionConsumerPanel extends javax.swing.JPanel { - private final javax.swing.JTabbedPane tabs; - private ConnectionConsumer connectionConsumer; - private ProviderSummaryList summaryList; - private DefaultTableModel tableData; - private final boolean isS2G; - private static final String LAST_USED_CONSUMER_PREF = "last_used_consumer"; - private static Preferences prefs = Preferences.userNodeForPackage(DirectoryConnectionConsumerPanel.class); - - /** - * Creates new form ConsumerPanelArchive - * - * @param isS2G Flag that defines if it is a Space to Ground link - * @param connectionConsumer - * @param tabs - */ - public DirectoryConnectionConsumerPanel(final boolean isS2G, - final ConnectionConsumer connectionConsumer, final JTabbedPane tabs) - { - initComponents(); - this.connectionConsumer = connectionConsumer; - this.tabs = tabs; - this.initTextBoxAddress(); - this.isS2G = isS2G; - - String[] tableCol = new String[]{"Service name", "Supported Capabilities", - "Service Properties", "URI address", "Broker URI Address"}; - - tableData = new javax.swing.table.DefaultTableModel( - new Object[][]{}, tableCol) - { - Class[] types = new Class[]{ - java.lang.String.class, java.lang.String.class, java.lang.String.class, - java.lang.String.class, java.lang.String.class - }; - - @Override //all cells false - public boolean isCellEditable(int row, int column) - { - return false; - } - - @Override - public Class getColumnClass(int columnIndex) - { - return types[columnIndex]; - } - }; - - jTable1.setModel(tableData); - - ListSelectionListener listSelectionListener = listSelectionEvent -> { - // Update the jTable according to the selection of the index - cleanTableData(); - - int index = providersList.getSelectedIndex(); - - if (index == -1) { - index = 0; - } - - ServiceCapabilityList services - = summaryList.get(index).getProviderDetails().getServiceCapabilities(); - - // And then add the new stuff - for (int i = 0; i < services.size(); i++) { - ServiceCapability service = services.get(i); - - String serviceName; - try { - serviceName = HelperMisc.serviceKey2name(service.getServiceKey().getKeyArea(), - service.getServiceKey().getKeyAreaVersion(), service.getServiceKey().getKeyService()); - } catch (MALException ex) { - serviceName = ""; - } + private final javax.swing.JTabbedPane tabs; + private ConnectionConsumer connectionConsumer; + private ProviderSummaryList summaryList; + private DefaultTableModel tableData; + private final boolean isS2G; + private static final String LAST_USED_CONSUMER_PREF = "last_used_consumer"; + private static Preferences prefs = Preferences.userNodeForPackage(DirectoryConnectionConsumerPanel.class); + + /** + * Creates new form ConsumerPanelArchive + * + * @param isS2G Flag that defines if it is a Space to Ground link + * @param connectionConsumer + * @param tabs + */ + public DirectoryConnectionConsumerPanel(final boolean isS2G, + final ConnectionConsumer connectionConsumer, final JTabbedPane tabs) { + initComponents(); + this.connectionConsumer = connectionConsumer; + this.tabs = tabs; + this.initTextBoxAddress(); + this.isS2G = isS2G; + + String[] tableCol = new String[]{"Service name", "Supported Capabilities", + "Service Properties", "URI address", "Broker URI Address"}; + + tableData = new javax.swing.table.DefaultTableModel(new Object[][]{}, tableCol) { + Class[] types = new Class[]{ + java.lang.String.class, java.lang.String.class, java.lang.String.class, + java.lang.String.class, java.lang.String.class + }; + + @Override //all cells false + public boolean isCellEditable(int row, int column) { + return false; + } + + @Override + public Class getColumnClass(int columnIndex) { + return types[columnIndex]; + } + }; + + jTable1.setModel(tableData); + + ListSelectionListener listSelectionListener = listSelectionEvent -> { + // Update the jTable according to the selection of the index + cleanTableData(); + + int index = providersList.getSelectedIndex(); + + if (index == -1) { + index = 0; + } + + ServiceCapabilityList services + = summaryList.get(index).getProviderDetails().getServiceCapabilities(); + + // And then add the new stuff + for (int i = 0; i < services.size(); i++) { + ServiceCapability service = services.get(i); + + String serviceName; + try { + serviceName = HelperMisc.serviceKey2name(service.getServiceKey().getKeyArea(), + service.getServiceKey().getKeyAreaVersion(), service.getServiceKey().getKeyService()); + } catch (MALException ex) { + serviceName = ""; + } + + String serviceURI = ""; + String brokerURI = ""; + + if (service.getServiceAddresses().size() > 0) { + serviceURI = service.getServiceAddresses().get(0).getServiceURI().toString(); + // To avoid null pointers here... + brokerURI = (service.getServiceAddresses().get(0).getBrokerURI() == null) + ? "null" : service.getServiceAddresses().get(0).getBrokerURI().toString(); + } + + String supportedCapabilities = (service.getSupportedCapabilitySets() == null) + ? "All Supported" : service.getSupportedCapabilitySets().toString(); - String serviceURI = ""; - String brokerURI = ""; + tableData.addRow(new Object[]{ + serviceName, + supportedCapabilities, + service.getServiceProperties().toString(), + serviceURI, + brokerURI + }); + } + }; + + providersList.addListSelectionListener(listSelectionListener); + connectButton.setEnabled(false); + } /** - * Cleans the table data that contains the list of services provided by the currently selected prodiver. + * Cleans the table data that contains the list of services provided by the + * currently selected provider. */ private void cleanTableData() { while (tableData.getRowCount() != 0) { tableData.removeRow(tableData.getRowCount() - 1); } - - String supportedCapabilities = (service.getSupportedCapabilitySets() == null) - ? "All Supported" : service.getSupportedCapabilitySets().toString(); - - tableData.addRow(new Object[]{ - serviceName, - supportedCapabilities, - service.getServiceProperties().toString(), - serviceURI, - brokerURI - }); - } - }; - - providersList.addListSelectionListener(listSelectionListener); - connectButton.setEnabled(false); - } - - /** - * Cleans the table data that contains the list of services provided by the currently selected provider. - */ - private void cleanTableData() { - while (tableData.getRowCount() != 0) { - tableData.removeRow(tableData.getRowCount() - 1); } public void setURITextbox(final String uri) { @@ -180,8 +176,9 @@ public void setURITextbox(final String uri) { } /** - * This method is called from within the constructor to initialize the form. WARNING: Do NOT - * modify this code. The content of this method is always regenerated by the Form Editor. + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents @@ -227,34 +224,48 @@ private void initComponents() { javax.swing.GroupLayout jPanel10Layout = new javax.swing.GroupLayout(jPanel10); jPanel10.setLayout(jPanel10Layout); - jPanel10Layout.setHorizontalGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel10Layout.createSequentialGroup().addContainerGap().addComponent(jLabel29, - javax.swing.GroupLayout.PREFERRED_SIZE, 208, javax.swing.GroupLayout.PREFERRED_SIZE).addGap(1, 1, 1) - .addComponent(uriServiceDirectory, javax.swing.GroupLayout.DEFAULT_SIZE, 388, Short.MAX_VALUE).addGap( - 18, 18, 18).addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, - false).addComponent(load_URI_links1, javax.swing.GroupLayout.DEFAULT_SIZE, - javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(connectButton, - javax.swing.GroupLayout.DEFAULT_SIZE, 193, Short.MAX_VALUE)).addContainerGap())); - jPanel10Layout.setVerticalGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel10Layout.createSequentialGroup().addGroup(jPanel10Layout.createParallelGroup( - javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel10Layout.createSequentialGroup().addGap(9, 9, - 9).addComponent(jLabel29, javax.swing.GroupLayout.PREFERRED_SIZE, - javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addGroup( - jPanel10Layout.createSequentialGroup().addGap(5, 5, 5).addGroup(jPanel10Layout - .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent( - uriServiceDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, - javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(load_URI_links1)))).addPreferredGap( - javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(connectButton, - javax.swing.GroupLayout.DEFAULT_SIZE, 38, Short.MAX_VALUE))); + jPanel10Layout.setHorizontalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel29, javax.swing.GroupLayout.PREFERRED_SIZE, 208, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(1, 1, 1) + .addComponent(uriServiceDirectory, javax.swing.GroupLayout.DEFAULT_SIZE, 388, Short.MAX_VALUE) + .addGap(18, 18, 18) + .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(load_URI_links1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(connectButton, javax.swing.GroupLayout.DEFAULT_SIZE, 193, Short.MAX_VALUE)) + .addContainerGap()) + ); + jPanel10Layout.setVerticalGroup( + jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel10Layout.createSequentialGroup() + .addGap(9, 9, 9) + .addComponent(jLabel29, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel10Layout.createSequentialGroup() + .addGap(5, 5, 5) + .addGroup(jPanel10Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(uriServiceDirectory, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(load_URI_links1)))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(connectButton, javax.swing.GroupLayout.DEFAULT_SIZE, 38, Short.MAX_VALUE)) + ); jSplitPane1.setDividerLocation(280); - jTable1.setModel(new javax.swing.table.DefaultTableModel(new Object[][]{{null, null, null, null}, {null, null, - null, null}, - {null, null, null, null}, {null, null, - null, null}}, - new String[]{"Title 1", "Title 2", "Title 3", "Title 4"})); + jTable1.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null}, + {null, null, null, null} + }, + new String [] { + "Title 1", "Title 2", "Title 3", "Title 4" + } + )); jScrollPane1.setViewportView(jTable1); jSplitPane1.setRightComponent(jScrollPane1); @@ -272,32 +283,43 @@ private void initComponents() { javax.swing.GroupLayout homeTabLayout = new javax.swing.GroupLayout(homeTab); homeTab.setLayout(homeTabLayout); - homeTabLayout.setHorizontalGroup(homeTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel10, javax.swing.GroupLayout.DEFAULT_SIZE, 828, Short.MAX_VALUE).addGroup(homeTabLayout - .createSequentialGroup().addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 110, - javax.swing.GroupLayout.PREFERRED_SIZE).addGap(0, 0, Short.MAX_VALUE)).addGroup(homeTabLayout - .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent(jSplitPane1, - javax.swing.GroupLayout.DEFAULT_SIZE, 988, Short.MAX_VALUE))); - homeTabLayout.setVerticalGroup(homeTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(homeTabLayout.createSequentialGroup().addComponent(jPanel10, - javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap( - javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jLabel1, - javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE).addGap(0, - 260, Short.MAX_VALUE)).addGroup(homeTabLayout.createParallelGroup( - javax.swing.GroupLayout.Alignment.LEADING).addGroup( - javax.swing.GroupLayout.Alignment.TRAILING, homeTabLayout.createSequentialGroup() - .addGap(99, 99, 99).addComponent(jSplitPane1, - javax.swing.GroupLayout.DEFAULT_SIZE, 259, Short.MAX_VALUE)))); + homeTabLayout.setHorizontalGroup( + homeTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel10, javax.swing.GroupLayout.DEFAULT_SIZE, 828, Short.MAX_VALUE) + .addGroup(homeTabLayout.createSequentialGroup() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 110, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE)) + .addGroup(homeTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 988, Short.MAX_VALUE)) + ); + homeTabLayout.setVerticalGroup( + homeTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(homeTabLayout.createSequentialGroup() + .addComponent(jPanel10, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 260, Short.MAX_VALUE)) + .addGroup(homeTabLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, homeTabLayout.createSequentialGroup() + .addGap(99, 99, 99) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 259, Short.MAX_VALUE))) + ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); - layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addComponent( - jLabel7, javax.swing.GroupLayout.DEFAULT_SIZE, 828, Short.MAX_VALUE).addComponent(homeTab, - javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 828, - Short.MAX_VALUE)); - layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(layout - .createSequentialGroup().addGap(17, 17, 17).addComponent(jLabel7).addGap(18, 18, 18).addComponent(homeTab, - javax.swing.GroupLayout.DEFAULT_SIZE, 358, Short.MAX_VALUE))); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel7, javax.swing.GroupLayout.DEFAULT_SIZE, 828, Short.MAX_VALUE) + .addComponent(homeTab, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 828, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(17, 17, 17) + .addComponent(jLabel7) + .addGap(18, 18, 18) + .addComponent(homeTab, javax.swing.GroupLayout.DEFAULT_SIZE, 358, Short.MAX_VALUE)) + ); }// //GEN-END:initComponents private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed @@ -314,32 +336,40 @@ public void run() { this.setName("ConnectButtonActionThread"); ServiceKey loginServiceKey = new ServiceKey(LoginHelper.LOGIN_SERVICE.getArea().getNumber(), - LoginHelper.LOGIN_SERVICE.getNumber(), LoginHelper.LOGIN_SERVICE.getArea().getVersion()); - ServiceCapability loginService = summary.getProviderDetails().getServiceCapabilities().stream().filter( - serviceCapability -> serviceCapability.getServiceKey().equals(loginServiceKey)).findFirst().orElse( - null); + LoginHelper.LOGIN_SERVICE.getNumber(), LoginHelper.LOGIN_SERVICE.getArea().getVersion()); + ServiceCapability loginService = summary.getProviderDetails().getServiceCapabilities() + .stream() + .filter(serviceCapability -> serviceCapability.getServiceKey().equals(loginServiceKey)) + .findFirst() + .orElse(null); ServiceKey archiveServiceKey = new ServiceKey(ArchiveHelper.ARCHIVE_SERVICE.getArea().getNumber(), - ArchiveHelper.ARCHIVE_SERVICE.getNumber(), ArchiveHelper.ARCHIVE_SERVICE.getArea().getVersion()); - ServiceCapability archiveService = summary.getProviderDetails().getServiceCapabilities().stream() - .filter(serviceCapability -> serviceCapability.getServiceKey().equals(archiveServiceKey)) - .findFirst().orElse(null); + ArchiveHelper.ARCHIVE_SERVICE.getNumber(), ArchiveHelper.ARCHIVE_SERVICE.getArea().getVersion()); + ServiceCapability archiveService = summary.getProviderDetails().getServiceCapabilities() + .stream() + .filter(serviceCapability -> serviceCapability.getServiceKey().equals(archiveServiceKey)) + .findFirst() + .orElse(null); Blob authenticationId = null; String localNamePrefix = null; IdentifierList providerDomain = summary.getProviderKey().getDomain(); IdentifierList domainForArchiveRetrieval = providerDomain; if (loginService != null && archiveService != null) { - if (loginService.getServiceAddresses().get(0).getServiceURI().getValue().toLowerCase().contains( - "lwmcs")) { - localNamePrefix = "LWMCS_Consumer_" + RANDOM.nextInt(); - ProviderSummary lwmcs = summaryList.stream().filter(providerSummary -> providerSummary - .getProviderId().getValue().toLowerCase().contains("lwmcs")).findFirst().orElse(null); + if (loginService.getServiceAddresses().get(0).getServiceURI().getValue().toLowerCase().contains("lwmcs")) { + localNamePrefix = "LWMCS_Consumer_" + new Random().nextInt(); + ProviderSummary lwmcs = summaryList.stream() + .filter(providerSummary -> providerSummary.getProviderId() + .getValue() + .toLowerCase() + .contains("lwmcs")) + .findFirst() + .orElse(null); if (lwmcs != null) { domainForArchiveRetrieval = lwmcs.getProviderKey().getDomain(); } } - LoginDialog loginDialog = new LoginDialog(loginService, archiveService, providerDomain, - domainForArchiveRetrieval, localNamePrefix); + LoginDialog loginDialog = new LoginDialog(loginService, archiveService, + providerDomain, domainForArchiveRetrieval, localNamePrefix); if (loginDialog.isLoginSuccessful()) { authenticationId = loginDialog.getAuthenticationId(); } else { @@ -379,14 +409,13 @@ public void run() { t1.start(); }//GEN-LAST:event_connectButtonActionPerformed - public ProviderTabPanel createNewProviderTabPanel(final ProviderSummary providerSummary, Blob authenticationId, - String localNamePrefix) { + public ProviderTabPanel createNewProviderTabPanel(final ProviderSummary providerSummary, Blob authenticationId, String localNamePrefix) { return new ProviderTabPanel(providerSummary, authenticationId, localNamePrefix); } private void errorConnectionProvider(String service, Throwable ex) { - JOptionPane.showMessageDialog(null, "Could not connect to " + service + " service provider!" + - "\nException:\n" + ex + "\n" + ex.getMessage(), "Error!", JOptionPane.PLAIN_MESSAGE); + JOptionPane.showMessageDialog(null, "Could not connect to " + service + " service provider!" + + "\nException:\n" + ex + "\n" + ex.getMessage(), "Error!", JOptionPane.PLAIN_MESSAGE); } private void uriServiceDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_uriServiceDirectoryActionPerformed @@ -401,8 +430,8 @@ private void load_URI_links1ActionPerformed(java.awt.event.ActionEvent evt) {//G DefaultListModel listOfProviders = new DefaultListModel(); for (ProviderSummary summary : summaryList) { - listOfProviders.addElement(summary.getProviderKey().getInstId().toString() + ". " + summary - .getProviderId().toString()); + listOfProviders.addElement(summary.getProviderKey().getInstId().toString() + + ". " + summary.getProviderId().toString()); } providersList.setModel(listOfProviders); @@ -443,9 +472,9 @@ private URI getAddressToBeUsed() { // updates the } private void initTextBoxAddress() { // runs during the init of the app - // Common services + // Common services SingleConnectionDetails details = connectionConsumer.getServicesDetails().get( - DirectoryHelper.DIRECTORY_SERVICE_NAME); + DirectoryHelper.DIRECTORY_SERVICE_NAME); if (details != null) { this.uriServiceDirectory.setText(details.getProviderURI().toString()); @@ -462,46 +491,46 @@ public class CloseMouseHandler implements MouseListener { this.providerPanel = providerPanel; } - @Override - public void mouseClicked(MouseEvent evt) { - for (int i = 0; i < tabs.getTabCount(); i++) { - final Component component = tabs.getTabComponentAt(i); - - if (component == panel) { - tabs.remove(i); - tabs.revalidate(); - tabs.repaint(); - - Thread t1 = new Thread() { - @Override - public void run() { - this.setName("CloseButtonTabThread"); - - try { - if(providerPanel.getServices().getAuthenticationId() != null) { - try { - providerPanel.getServices().getCommonServices().getLoginService().getLoginStub().logout(); - providerPanel.getServices().setAuthenticationId(null); - Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()) - .log(Level.INFO, "Logged out successfully"); - } catch (MALInteractionException | MALException e) { - Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()) - .log(Level.SEVERE, "Unexpected exception during logout!", e); - } - } - providerPanel.getServices().closeConnections(); - } catch (Exception ex) { - Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()).log(Level.WARNING, - "The connection was not closed correctly. Maybe the provider was unreachable!"); - } - } - }; - - t1.start(); - return; - } + @Override + public void mouseClicked(MouseEvent evt) { + for (int i = 0; i < tabs.getTabCount(); i++) { + final Component component = tabs.getTabComponentAt(i); + + if (component == panel) { + tabs.remove(i); + tabs.revalidate(); + tabs.repaint(); + + Thread t1 = new Thread() { + @Override + public void run() { + this.setName("CloseButtonTabThread"); + + try { + if (providerPanel.getServices().getAuthenticationId() != null) { + try { + providerPanel.getServices().getCommonServices().getLoginService().getLoginStub().logout(); + providerPanel.getServices().setAuthenticationId(null); + Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()) + .log(Level.INFO, "Logged out successfully"); + } catch (MALInteractionException | MALException e) { + Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()) + .log(Level.SEVERE, "Unexpected exception during logout!", e); + } + } + providerPanel.getServices().closeConnections(); + } catch (Exception ex) { + Logger.getLogger(DirectoryConnectionConsumerPanel.class.getName()).log(Level.WARNING, + "The connection was not closed correctly. Maybe the provider was unreachable!"); + } + } + }; + + t1.start(); + return; + } + } } - } @Override public void mousePressed(MouseEvent me) { @@ -519,5 +548,4 @@ public void mouseEntered(MouseEvent me) { public void mouseExited(MouseEvent me) { } } - } From 0268bb29b6a865ad3a4d46e9c2be5da4aed9aa61 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Thu, 23 Feb 2023 17:20:42 +0100 Subject: [PATCH 164/173] Fixes the CameraSettings arguments --- .../esa/mo/nmf/clitool/PlatformCommands.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java index a0b42cb47..13c2ea8ab 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java @@ -50,6 +50,7 @@ * @author marcel.mikolajko */ public class PlatformCommands { + static Logger LOGGER = Logger.getLogger(PlatformCommands.class.getName()); @Command(name = "gps", subcommands = {GetNMEASentence.class}) @@ -66,6 +67,7 @@ public static class Camera { @Command(name = "take-picture", description = "Take a picture from the camera") public static class TakePicture extends BaseCommand implements Runnable { + @Option(names = {"-res", "--resolution"}, paramLabel = "", required = true, description = "Resolution of the image in format widthxheigh. For example 1920x1080") String resolution; @@ -109,17 +111,20 @@ public void run() { } String[] res = resolution.split("x"); - CameraSettings settings = new CameraSettings(new PixelResolution(new UInteger(Integer.parseInt(res[0])), - new UInteger(Integer.parseInt(res[1]))), PictureFormat.fromString(format.toUpperCase()), new Duration( - Double.parseDouble(exposure)), Float.parseFloat(gainRed), Float.parseFloat(gainGreen), Float - .parseFloat(gainBlue)); + CameraSettings settings = new CameraSettings( + new PixelResolution(new UInteger(Integer.parseInt(res[0])), new UInteger(Integer.parseInt(res[1]))), + PictureFormat.fromString(format.toUpperCase()), + new Duration(Double.parseDouble(exposure)), + Float.parseFloat(gainRed), Float.parseFloat(gainGreen), Float.parseFloat(gainBlue), + null + ); final Object lock = new Object(); try { camera.takePicture(settings, new CameraAdapter() { @Override public void takePictureResponseReceived(MALMessageHeader msgHeader, Picture picture, - Map qosProperties) { + Map qosProperties) { System.out.println("Picture received: " + picture); try { filename = filename + "." + format.toLowerCase(); @@ -136,7 +141,7 @@ public void takePictureResponseReceived(MALMessageHeader msgHeader, Picture pict @Override public void takePictureResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { + Map qosProperties) { LOGGER.log(Level.SEVERE, "Error during takePicture!", error); synchronized (lock) { lock.notifyAll(); @@ -172,6 +177,7 @@ public void takePictureResponseErrorReceived(MALMessageHeader msgHeader, MALStan @Command(name = "get-status", description = "Gets the provider status") public static class GetStatus extends BaseCommand implements Runnable { + @Override public void run() { if (!super.initRemoteConsumer()) { @@ -215,8 +221,9 @@ public void run() { @Command(name = "get-nmea-sentence", description = "Gets the NMEA sentence") public static class GetNMEASentence extends BaseCommand implements Runnable { + @Parameters(arity = "1", paramLabel = "", index = "0", - description = "Identifier of the sentence") + description = "Identifier of the sentence") String sentenceId; @Override @@ -239,7 +246,7 @@ public void run() { gps.getNMEASentence(sentenceId, new GPSAdapter() { @Override public void getNMEASentenceResponseReceived(MALMessageHeader msgHeader, String sentence, - Map qosProperties) { + Map qosProperties) { System.out.println("Sentence received: " + sentence); synchronized (lock) { @@ -249,7 +256,7 @@ public void getNMEASentenceResponseReceived(MALMessageHeader msgHeader, String s @Override public void getNMEASentenceResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { + Map qosProperties) { LOGGER.log(Level.SEVERE, "Error during getNMEASentence!", error); synchronized (lock) { lock.notifyAll(); @@ -266,4 +273,3 @@ public void getNMEASentenceResponseErrorReceived(MALMessageHeader msgHeader, MAL } } } -//------------------------------------------------------------------------------ \ No newline at end of file From c5751e481d50dba2a11e4a8fd8d96599da504550 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Feb 2023 11:39:28 +0100 Subject: [PATCH 165/173] Removes the mo_pic from CTT and the Beans dependency --- sdk/tools/consumer-test-tool/pom.xml | 14 -- .../nmf/ctt/utils/ConfigurationManager.form | 225 ------------------ .../src/main/resources/mo_pic.png | Bin 12893 -> 0 bytes 3 files changed, 239 deletions(-) delete mode 100644 sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ConfigurationManager.form delete mode 100644 sdk/tools/consumer-test-tool/src/main/resources/mo_pic.png diff --git a/sdk/tools/consumer-test-tool/pom.xml b/sdk/tools/consumer-test-tool/pom.xml index adf02cdb4..cf4fc632f 100644 --- a/sdk/tools/consumer-test-tool/pom.xml +++ b/sdk/tools/consumer-test-tool/pom.xml @@ -80,23 +80,9 @@ mal-elements-window ${esa.nmf.version-qualifier} - - org.jdesktop - beansbinding - 1.2.1 - - - - ${basedir}/src/main/resources - - mo_pic.png - - - - org.apache.maven.plugins diff --git a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ConfigurationManager.form b/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ConfigurationManager.form deleted file mode 100644 index f1cefd80f..000000000 --- a/sdk/tools/consumer-test-tool/src/main/java/esa/mo/nmf/ctt/utils/ConfigurationManager.form +++ /dev/null @@ -1,225 +0,0 @@ - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sdk/tools/consumer-test-tool/src/main/resources/mo_pic.png b/sdk/tools/consumer-test-tool/src/main/resources/mo_pic.png deleted file mode 100644 index 7040af9da5c115fd59c6d32fec2a302645009bac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12893 zcmbVy2UJsCmo|h%2vI;Gf z8!Rla3>FsFmmDxKf~s4-4=$|sH!i8Lq}ClA1vhYWWi@3Mmh>>xh7khXBW*A1*t4*3 zl|g^3l{W89Sy;s9u3S*Q<{KVNSe7kO6X(Ie0K3l9m%c5F@e^&l~U z6O_h}6sZ0P#!s{yhNyGh3~z`pYz^&m#qKSiyev9 zs{7vx4mEdXIiEIPJw07Nzj=OiELo{ozIb|CQ*$^*LS(lJ$6;T%i5T3MM}>oo_?Q3d z)kpJhdtUhZ*VR^f-!(zGdrEjLn3N$^l6KMcR?3Ns+eWjU&PJ?kd^#|*Q>vc8$8Fc_eM$HLLRYJev&3y6v+ zhQ$0$o{Fsl!u!wn|F>T!|Ctw_<8kNan-m~0GJ+1ow8tE#sT}^~pLDPXjhomnccVpK+%Y)|yavZqeT8NHEe4=e;vYf& zt6vlk9omaOBJttThO7?==U@H`mqHDtw6y(E3V{P}k&GB$9)lQTsuAOB`7M6y+&T+W zKs+$i-~0db>vC1eufDO&bi?@d>AW+;M&x9?SiIi+$yQf+1$qE#UyaOdb&Swm3T)kH z3g3Qvy`{RxFf~~z;Y#JF&dsFU!Y@}jFgagg^Y^5fvu^LGn;5vCExJpGMn!T?v)#$W zN`6pDD%km2z&`1_CmNGeO3@JIco8RIYsIaV?>SllJFccd5^Q*dNPm9S^}sO)qV75l zZySe5FC?fRkj)MF*i-b`m|ThzO60bvru@FL@6_>gFNhuD-{+>%{gmkpBh0a7ibkRH z$fr7-n5EkHD=D3?j_>>tfT)hfPAk!lqO4+XWjGMm4b)0uCv?J7d8rDyLpY7a@5K(2 zHOc0BXpDt1Wn+nR63BbPE8qY|wgLtmAMah^NMZ%5q%s=SV~xmX@C-PW5o)gY5c4V3 zU}Y^HNRh+5tmr0{K|b0@BC|1{zcu%$4H-;+`HkY2mRbU*V-IHPkYMJa*8&hunJj1$ z%sGBGd8y)~b@YeR0#6(TB-)m@JhtoiOm$2z_jwuiMQY|7*Sro`H~hvOfLt(R#o5k< zNNJOVfzEKYn+LLuW48>dRXa^f3OD_aFNt&=;zC9k1I z&ijB2kOh2%N@v(HN#0toc8-1E_4G>wlO#-B9*3vD1i#UNtwnQp-eulNOfezf$F+Os zl%y-suqZKdz5p7dT?GjeZe^I8*3=>L1CvgWLd$LhJ-ZLqO@-Fo2W^Wd({nKA+A#gH zZVA}PDb$Uvl!ze&%I@^ifvc(2X0cnnod${-#lt`}oF>W-xZfF-z&L@+2irYH$cg^& zOJ@Q8$sE}80^y4P;Ya^xz%Jo#mUz@@``Ef)aW^v++Nc{AH0c7S_M- zfur!mAYgHiM}9lQ9*P_}A#_JWv}ncf-L)W(B;7jI=2g850hPzxF&0@`vfb>a0(wNO zRi!UNE|NA-#x2f@W55%{8zT`v7g$fS^P&U0#f?~T^m4c^S4;&w$`qJMu2&%B&$#d* z&Anj%e$j*$An{1uyf{2h3itlGDFV<|70{&*QcOAdW$IxRe1grtK!FFC;EfCxw4^y@ zepr+Q+oeW3jQTOTZ=G8vXGQA(n8z7So2p$sbuWxTL2yy~Yo5Og&?;E?c>U1v@t{U; z*>%T9SI_XFO*?*M8I$Sme(*<@A{)Jme368uHyMCSp$7OqRI3pn%p+UpFzltKjh!<% zyw?BLT~q)__8TyT4C#^@8&4mkq$F7mcd}SpM-jtOq{X3_LnTyXX8)m4O((FS_1=G6 za=ZHYiLKj9t+kC^PgWxt8~5&DJ{h(jwcSoS+UhN$fGY13E{DW7x=$a71FU|ZP6A%L zsMa5?VSFsf^o}Fn0aIx*7d~7in8GE33tv8E15~=#0*26Tm{@zK!e=S$j)@d@xIX&2 z(}(T#RiQB*oi1t{_5J2y3V!-fkSt(pOt`odM%17oP0h&|oS1!jXOle5r!{WuF;YWl zxg}sLsbu;ip1b%>!{E0Pd#BULu#4XV^Y0wEnB8|vL_q(>-th9oZ)I%7ZYI(3n-UVn zS-%cVT5L7#3v=T=QK;Lne`DdbkVCy{Qr!2gxAt1bf}fAAq+f(fl*BL8ZXM;`rG`BM zd|*QBQ2?TYid~<7CM8L3#y5P0i*sF-VEMbWlaB~PoAccMKUd83pHg!m>u7Vmd!s2b*bS}Zp6reY?a zzhs+hY%zBp&;@;NC>tzMz1Et?=o0jvtmU|A>D+ zrJVnA{hIWlc`kgg$B4$@qFb9*TZfmT+JX9uyZsPULZr>JmRJNPlGJy}%UTV46ty6! zyb(OH>^l4^pf`!T;K=qwN4{>-odn&*)CI#lhhtR~#(e?H5N-_jn%4-4(r|*~^o|g1 zXUSQjuYPn>Ce|VQ8?t9bMSt-{X0`Z9L*&n~7j)#rts1!K>d|F%{WoP1|Q z_ErxQX{+$+4j;=yAS*E!xF3p<=dAY&tFj4Oj{o9TSec?aYhQ1&QRTk&*$;8U@LRPR z$Onr>GU_+Mb)1OZjat~6=vQ$`P$T|!c$Ct$qpw9|@e1obo&MtC-Yy%?_y*aBcKzC4 zn_r!|`tVxG$ak`dz#GYLV?_A;vcGGXj)yOBl5B_PKu6!Ef3!RW$@T`isuUJ_g2U@h zvGmYYmWqAOVS>F54`DZV00T;8}il)AxS5O5)R|)#FMPH#smP9wI;81M2QOioAZ%cg%8fsT4M=uJK#%f>uTO z^fJHyY;~unYnr|D!jyt@iOO1>ZQJRF@9@z&!%Dc7C_Wsru269~=c$-;kMZyIR@ApW zhQUhnVkPw1Ou;c3?1Jq(_4uXXLu+xTfwZYUlYWRfps03n+@-KXg&!6jxt&H=R@ApX zbmUD6+PJz@QO{n}wdhNK{DC}DW;Ui-e#m+?~(f0+0l`ct6v#Yhttm6wC(y?=bmgi=OUXa?I0GcYmn75Y?4N& zBJ{?2(ey$(!2oD@H<9N~Vwb_9b6fVfEK@%tH`fx)JBjlHwMmL?0cUKicA&NEVZ?A( z_hQ-kujYncI2+9eDUr)d?BB9B-`v?A-a6;KVh&o7#Jj9LhCFDh3|FCTU*2Zym#?vz za#f`A-+tVS{I*lwa`V}>2qkXxM0@(9!csR-MDFa;oxi8nm+PsSa%osm{(g@TAal%& z-0`!}ePpXOEzo^=>hz3XzIkV@Qj)r~`(@>PE`6dmwb;zf_@YFPGF%ty{=U!0=$E;< zY+}DZzk*HA78j1^DFXQ`5V;^;l34aU0@US|>I|4N*&$cK5^KZO?}rInQ3c8eXui&n|^?WiV>D%63r+p6FU@2{IqvHiMS|YXcry zF0MSJDj$J(k=E0gZ!<9vkoKv^e1ApG+*404hnBiJxwCq!VIkM7Z5T}7w^&qyX6Jy} z&VOc;o)#6U-9`IKEPNPX^FDLZ?Q+TKbDOLEhFhn&(P!PJ6%+nC#0>TLGbPW*<3gm! z6L{MqFrOF92V2)^dOK(YvwvDw0e?ja5XAH~A74E$>uO^n{eM&|j}M8^uBnZz}{;N-S!0?t$iz9wFm; zR;{k0FIU5O-C3cg4idHLc4<$+V1wY$J=nZftzm5od?;Sa&07#ylo;6_2mEwu38vjI z2JU2WVm9&d$k0QIogXH54W6s+fDZ`#YGkOJwECjm&S5;7DC<aZwCQ0=E~8y@IVA* z0j#_e^&`c*SMh|H@?o6ILa+N(UB1#N(s_1bgU1QUY+m4t`9v%VRX&QKGgzU#P}@W3 z!kE86+O7HYIp5sERsC9jNks3>E{E$lmg0vgMIfBGMiV$O94#mkxd+@)s95^t?3}YU zXe!F%5bph*qJwBtIao(6hZ@i)r#N{9bOnH4U2r$Ca`w17`g6fp76LUVt$eNR5~pI! z>SHSQ-ENRDpqz$@2KkAj9nkg!cTOSS8sA)+9&1$OMw@CUij(oN8X&<@O4YCusPYNG zG!ASbnkl5vND}Z3d#RFWnY(VXbr(<4(PLkM=7NyEW@LVxh1JZq`-^vO6}d1+n$F*g@O)aZ~FYx<$s9kjN6CkV+o z?#l<7G;K4OxK6)6Qlxnm7qS1_s9dM>r|W{4PibTJS-CCx>$0F*Bvn#llsr2nm8UTk z5v?7q^C=Rie?(@IDjepWzq?nB4%8OgR)z{t8AaFLqkw(*;dsIksUA)ZBWV){+yY3Q zp?MVz3hdEmlfII@g+W1T93*~vyT1?Tz+mp##Y`C+1z8?OxZUsDr}59D@iVKa|hViTfZ|T2CXjctKaFJ zyuM2dw;B7fCZPMkO17@|8Pf^s%y~nn_4-Sqk^2j}bWQq%a@R($+jz~)1#7CmS}a!D zP(Pho?A_gzW|bX`p!$fHz`r=DECNfy%aAqjwv+qI9=F7`4n=AG{P3X4A=97jMZz+- zv3=RE^AzC+R7B9Z!hCm^7Vadq<$)UG)PDjW>r!ZJbPp+TCH^D=H=AM(hMlH)-h{%(4}d(t@3#$kos-lm zda#MvG|$Y=U0#lU!#<*l>1T``lKX-s`0mHRU#@<}2lmQtEd@F6n;#!oW_xyP_tp!B zdXp!SXS=CkQ?kdN4^yyM5~KRp)#>8nTjzbr>c8z=SSO=jlgKriU($&KQ8SHj6u?C( znhH~mq5h2-o*i$Gr*Ch4$*wQ_6;R)ib!^=kWoN8BvCg_$pd0=S@z7iINA3=}Oze%W z6Ss)&#?2^CFTRZ?`LJj@Cq`p0K0FcUan|T}=+mpM&FGsc0GH)xojv{-_k|npJn42e z)2TO~?5&sXWxbu>c|c82#MIeJ`2jxg(82J&bi_#=o_!ZbgaStT4tQHBJK?FB4Na$Q zi?bJ!+xKov^cVJpt$j5Ea1nrqd=SZPjjr|=zo^gFx#u4;$@c40Y0vv$`0C~Nn4oZe z)E+zQw!<&b=gp5?2-U82!Kv_JY7J){wiTk}(1!(3(x0Z=a#hcmAK7o6_vB9H;efqK zvZzGa^GC~a1JlU}N<2+y%&`tF;-z=%nQbHGQ>tz_8a3r%F%hxu?#QKome!VLl1dEk zaYX%~V+ZmOZBB0etBK>7M5B_oo6pbI_j;I31O);Sg^cSQOjmih?X~aYTXSoQR%^3| z{S<7t=b?zP9hbnlcdNO9Tn;LZ+8TjK61g8AzL~H7DYx2aE|TMvm*%s36wrN|Zk7S4 zGv(TQ4iqN<#CakSoF0OFz)+|R9Qu~oa)m6e;W5GwoaAuSz@&8}rS`!1iRT4w{2@dM~PZ+#dizP+fpe3r#d73-l$SP;evivmPEW z;V!_|1_f@eYLf!M;#j;!7C)#_7=Y~?po77*n*tgz)ZVE-G&m(oiVM9}<~ zZml&U)+zz4bJTYas0qO4vbAa7^4|h>NtCl|EI3;;L7rGd9dI;IIC&~v0jLCo2J6Tt zG~jJ(0VP+Ag`>lZA$*k;MM~-fQ<6U?*nVa(t^i^II<&6cZStAeOyrjqFF(-V9mO_t za8$zrfG5S6lKl$_x{$~Sg5eL~7fi|XAmD_i6Y33UCm@8C#$6=~D@|wY1EkEgY1X0* z;n4C8?8gLH)3y6w0&%h78*+I^n85c4+gzv*0dLy~xO#xG=tX@7RU!jETKeK((unVC zIzu0j(bZv$vw4DI3S!0m#9j&_6_`VNB}n0+J~$w$Pk|vmu-FD$&%_H*;TZ&ytRzex z$b)`F0(Rd)gr;w zCMtp&_uw&i$@DZ3gN}n)Ku!#51AF2jGDSPwF7x!q>^TJUa=BzOCoa)AF-ntlNWyu@V3S1mC0Ss zi+!AvvLsxm3VPFvgw;&(Nn^4D0K}PAt-bpIYia`tg#w8jvX4JIw|D^4)yCcfkTN2Q z5HDP4^0z?F!Z4YHUa%#Jw%=vX&rk{R29VG*eRgZO!#|mloBuo6iwp@&Rj;^_vRAyo zKWn|X$l${WHGolhw3U2T(0|TvFookuWWN6~pQeEkY65R&AeF3E!vA^mKAh8-eD#04 ziS@<^wL%~_)F|(Jx|;-_GbbBEuTZSqpixL)le_895H|qQ4`JFWk-vP9R78l+gQKL5 z0FI15!>l-xswsRwt0kA*Et<)F&?ZCM8)rSr;LywX4gU&S=#yeR^31anBEyZrAqH!u z6Cy2Ypcg03l*pJDug+zPntga;Be?dfv-7vaw&H3$|&00ysk(?|BiQc|yZ(9{_Bs*MLy(fWXLv zZi3h576+x0DcBRhL77J`rEn0^G?*Ua2Vyw_!icUjhkVZ5xYgCW%oSUhc*#M5_o3z@ zlD$rKBDN73To;p2Eti)pO*mhs_$ad_at{bd0OB{&AqX4x}p7 z4L8p40l}5i#>fA*`wkrGDx}UJB;1tM6SNgSSax|X?IbcHfRsUA39NvDcuP-a<%^m) zK=nCEW=e!780?lvGGdc-Xg?#ydJ_ix&QcA_g&JX_GCFry2o;-?U~l0-Aupo|JU}60 zTfGjU|(t?v*J0L}wFOgb+5SuT(CV4@g~%!z7X zq9d4?w+KriYM9lZ*_!nYa}McFFpZ_UmEJ*vYyxqZ#>#hf>HygGduvKs{bsfRH#;hk z1Z}CklV#V^&M&-xM{Uq&LM%@0u%MgM3&GnA*hy`IAk_Hb==rQyzx{C-e8Us4!OGCW zmJT>{S_CA-f^sl{sL8gn95-S5DGLTfcqkcVuvVA<_j$yATeb*)5Te^A7YmDAzKuMc zYyDiJzUjrF1Ap>V?&v?Mm~R5prk#b%+;&U#=|K>Yb019Sy)q9gs?f-)&|A*lUTQBk z2Jc9tKI`v3Kz6{1v6quCz4AfiMUraBO;oJ?X)DW#LoyIF;0Kx!F|sf&9C}KdiKIP3 zwmNDAAbtYV2`qyVX_FjObe}#tkQondL;B`f>?u6zDw0i2OzP$Wg2xvfGsWU^-!+5?YLW0Ur)!b5`a$IY>RGIru@K_T~F9 zZITRgkv{kovs{5eFu`w7N7G+GJG*Q|QPByvbA0zH<-;4?Nh^wY$`(M1s9AR##Flo| zpfJC0O{Z?ec=|v42-w$Xg8#{zpsR*#70Q^L(6TJhCnW#?2IoI#E9fnT`z-!Ol)<4d z%^z80m;=HGD6;n+KZ26weQLkkK6!R~hV3sRwh9@1uU^%|u+=^lB=8eL_q{}3HxG~4 z9eP{H-1-;Xm)wmMV@o2a?h+Mv0jviM$OmcK=T!Esu>^iV;^UJ9TOCUP)6o)S|V3s@bXLm$%t1((JOAY`ONW1?E1ZgOh{TF}k_pf3>vFn(r<^)U_s zxV~*IiU)AV9Z((vbF)vInJNK0>9CgBFQ9xE235{^e;&nZmH&0hU_M&2UIK{T5+GI_ zU%~M%fY(^(DVk~6zXyS%S-T4Y!nG&^wlA z*AI|@WA8voPJ068#6%@!N|H+JFNm4Z#-8H1mVukd|MN_&BtXR0W(cm+7D~K7r*my}FFZ(1G^@=Ak~3Q2-_oWC1NL?Qq*? zDMNn*NA0-1{-O^2ehtEfEGQkJodM^f6Ewi90U);AsDpVzAqM(>qoWpn0sTKw1DySmL0H*as<5%RC|yBk#b8$s|tIx@u!Ph&~7|z^!QWHVIM`*?g|wM zR{@L_swxw?=|UN+Q&9v2sA-`g27H11mt*gZGGfrXyu*)mWu#YRT(3T6D>l;eY-*1c z{uINz=+(y`r!1;z`1#(=lmc(HPKxF$ncI+SYl*6NlTU*x`K0xQ&}jm=g7*CWB!2z;0Y{Bmp5cArbFf*8G& zy|u2Nqd6q!;|rtDW8%5EoYnYC+P2y6I%5QQ`T2_So3(X2GKJ2bKxX|VIl=Zphi3~< zyEi$ZKg#{U?g*+kMhd&N^i;A{Gi}MOaK7d*6`OeJqO&MReU)_kSQ*EYjL`n+tz+?LF4vvWZF0lxX{*{$;r%^wr&ORIn zTYprx94-TH3Pu~3{hfX4(MsY$tFp)C^{9k<7$NVJJ=&o9iO`y4fV?tmiIJ+LXx2N1 zxw_MW5GAg=Mz$_`n~iW3&Q&KfqFD!8WCw@=ZpAiPZTWZ)E7Ht9S9wf%tUTy8 zp2qJ8^Q8wO+RkPlwc9f^`_(><>!9{b+3a)YlkFJk356FwGgPO&M;Yh&A%EG+^p{+2 z)4L@lzfRy@IsSE5IZa3KtxhigxaXV4QK8}m8pF{Vdvdp{9_~=Qv>u8$hY36wLsdkL zc@B~dg$|8u{?*@4&inr6yx@(*vp_~gs$=WihK~{~Xv^BQWDX=gFkkxoNIUF}ep=t; zeG9jRRL+CC{fwlYgLlceHc2KR)4(o4$I8OCBcCCjYPEmpJ-NY|b2urR}ewynTZ%6&!aK9=#p0O7sm>c{X)!G$iQ3ab*)<9s0+)S65zH$xE6{ z9QA%>OHu|OD*0a|(j-tn7NIlYldX%)aFiE~RYW=YUBW&^>|4$XcKxN;QZ0~U$9OjL z)c^S4vd~{R@X(5Po6Om$>E5x)dmRT=8EKmV59~anJlR?<+Uy)#EbCc{YAd zweZ)OgpWt-B+a4Vn7c#<$dl9oGU(X`6~Z0bJt{?P@WLnu1x|f)jMYRV7tiMOaqwjk_zrX4JESBPU}>f$U18miK%xcDO^eyu-N@$> zaQV9GpP{7kAe|vu^3{HrY1JeO-kD|bt&atcClu5kupW?;EdoKu#@Kt=_2hYH?srln z;M~d;q*T5mfZELMNZnU5FCQTmV1Ga;Fh+ujt6@1&BZwgm3ufC6`X&~1j@QZa2>?ps zc;dqafoq!q{9r|3;DF`tFgIlfc!as~U9_zCH!cv3!6RFx(Nvw2fk?f(tc6%7IQW1N zYOcZS%*@C$e8c}phK~WQ%gqPb&OXA{QIFCRu?YaJfaM=-$p<;Y7FCY|ouBhi0lq#< zS(KzmTTbV0V5jm@8LLnB+1rSM^tpTw07=2G;dmyr1X3iFFhQvdAx|KKLN_2?LN}^G z3`#*gV?eJQn9jqxeda&KVKI-Zas#8z_Gli_?`@X?Qt8P%j3WusxS`riIq#$)w01P9 z0j147;yJ;#z&eD$(QT@079D`MwX(ShuCsXhxI(S5{(o^z#U>$>GZedM}Nz)uL25 z%~&tBl3;FvC7_;#p-LM)aOGZJwXWYHQb>Rs8HqgRxMZf8e^ckgbV^8c0=JmPuG z6*FO49Pv t-#WC_>&p;9@Wnp(jQaom|Fzc^`&#ephjTBFe`W#yuBcwSkg7tW{0G?J=r#ZV From 5e69f795542ae1d2c7fe9b380c9a202c6db076b5 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Feb 2023 18:38:34 +0100 Subject: [PATCH 166/173] Adds Exit Codes to the cli-tool & Fixes the start/stop/kill by getting the App Ids directly from the Apps Launcher service instead of getting it from the COM Archive --- parent/pom.xml | 6 - sdk/tools/cli-tool/pom.xml | 1 - .../java/esa/mo/nmf/clitool/BaseCommand.java | 1 - .../java/esa/mo/nmf/clitool/ExitCodes.java | 48 +++++ .../clitool/SoftwareManagementCommands.java | 202 ++++++++++-------- 5 files changed, 155 insertions(+), 103 deletions(-) create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ExitCodes.java diff --git a/parent/pom.xml b/parent/pom.xml index 04b5d99c4..cf3ee7fa7 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -87,12 +87,6 @@ int.esa.ccsds.mo API_COMMON ${esa.api.common.version} - - - int.esa.ccsds.mo - API_COM - - int.esa.ccsds.mo diff --git a/sdk/tools/cli-tool/pom.xml b/sdk/tools/cli-tool/pom.xml index 567d07427..353a23871 100644 --- a/sdk/tools/cli-tool/pom.xml +++ b/sdk/tools/cli-tool/pom.xml @@ -89,7 +89,6 @@ int.esa.nmf.core.moservices.api com-nmf - 2.1.0-SNAPSHOT diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java index 7a4a0c026..9f1d0b010 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java @@ -343,4 +343,3 @@ AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), return adapter.getAppObjectId(); } } -//------------------------------------------------------------------------------ \ No newline at end of file diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ExitCodes.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ExitCodes.java new file mode 100644 index 000000000..582a9c265 --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ExitCodes.java @@ -0,0 +1,48 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool; + +/** + * Exit codes from: /usr/include/sysexits.h + * + * @author Cesar Coelho + */ +public class ExitCodes { + + public static final int OK = 0; + public static final int GENERIC_ERROR = 1; + public static final int BASE = 64; + public static final int USAGE = 64; + public static final int NO_DATA = 65; + public static final int NO_INPUT = 66; + public static final int NO_USER = 67; + public static final int NO_HOST = 68; + public static final int UNAVAILABLE = 69; + public static final int SOFTWARE = 70; + public static final int OS_ERROR = 71; + public static final int OS_FILE = 72; + public static final int CAN_NOT_CREATE = 73; + public static final int IO_ERROR = 74; + public static final int TEMP_FAIL = 75; + public static final int PROTOCOL = 76; + public static final int NO_PERMISSION = 77; + public static final int CONFIG = 78; +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java index 2bd1605f2..886df9e10 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java @@ -21,6 +21,12 @@ package esa.mo.nmf.clitool; import esa.mo.helpertools.connections.ConnectionConsumer; +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; import org.ccsds.moims.mo.com.archive.consumer.ArchiveStub; import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; @@ -34,6 +40,7 @@ import org.ccsds.moims.mo.mal.transport.MALMessageHeader; import org.ccsds.moims.mo.softwaremanagement.SoftwareManagementHelper; import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; import org.ccsds.moims.mo.softwaremanagement.appslauncher.consumer.AppsLauncherAdapter; import org.ccsds.moims.mo.softwaremanagement.appslauncher.consumer.AppsLauncherStub; import org.ccsds.moims.mo.softwaremanagement.appslauncher.structures.AppDetails; @@ -41,17 +48,12 @@ import org.ccsds.moims.mo.softwaremanagement.heartbeat.consumer.HeartbeatStub; import picocli.CommandLine.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * @author marcel.mikolajko */ public class SoftwareManagementCommands { - static Logger LOGGER = Logger.getLogger(SoftwareManagementCommands.class.getName()); + + private static final Logger LOGGER = Logger.getLogger(SoftwareManagementCommands.class.getName()); public static Identifier heartbeatSubscription; public static Identifier outputSubscription; @@ -66,15 +68,16 @@ public static class Heartbeat { @Command(name = "subscribe", description = "Subscribes to provider's heartbeat") public static class Beat extends BaseCommand implements Runnable { + @Override public void run() { if (!super.initRemoteConsumer()) { - return; + System.exit(ExitCodes.NO_HOST); } if (consumer.getSMServices().getHeartbeatService() == null) { System.out.println("Heartbeat service is not available for this provider!"); - return; + System.exit(ExitCodes.UNAVAILABLE); } try { @@ -87,7 +90,7 @@ public void run() { heartbeat.beatRegister(subscription, new HeartbeatAdapter() { @Override public void beatNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, - UpdateHeaderList updateHeaderList, Map qosProperties) { + UpdateHeaderList updateHeaderList, Map qosProperties) { long timestamp = updateHeaderList.get(0).getTimestamp().getValue(); System.out.println("[" + timestamp + "] - Heartbeat received"); } @@ -100,43 +103,43 @@ public void beatNotifyReceived(MALMessageHeader msgHeader, Identifier identifier } } catch (MALInteractionException | MALException | InterruptedException e) { LOGGER.log(Level.SEVERE, "Error during heartbeat register!", e); + System.exit(ExitCodes.GENERIC_ERROR); } } } @Command(name = "subscribe", description = "Subscribes to app's stdout") public static class MonitorExecution extends BaseCommand implements Runnable { + @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the apps to subscribe to. If non are specified subscribe to all.") + description = "Names of the apps to subscribe to. If non are specified subscribe to all.") List appNames; @Override public void run() { if (!super.initRemoteConsumer()) { - return; + System.exit(ExitCodes.NO_HOST); } if (consumer.getSMServices().getAppsLauncherService() == null) { System.out.println("Apps launcher service is not available for this provider!"); - return; + System.exit(ExitCodes.UNAVAILABLE); } - final Object lock = new Object(); - try { - AppsLauncherStub appsLauncher = consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); - - Identifier subscriptionId = new Identifier("CLI-Consumer-AppsLauncherSubscription"); - Subscription subscription; - if (appNames == null || appNames.isEmpty()) { - subscription = ConnectionConsumer.subscriptionWildcard(subscriptionId); - } else { - ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - Map providerNameToDetails = getProvidersDetails(archive); + AppsLauncherStub appsLauncher = getAppsLauncher(); + Long timestamp = System.currentTimeMillis(); + Identifier subscriptionId = new Identifier("CLI-Consumer-AppsLauncherSubscription_" + timestamp); + Subscription subscription = ConnectionConsumer.subscriptionWildcard(subscriptionId); + EntityKeyList entityKeys = new EntityKeyList(); - EntityKeyList entityKeys = new EntityKeyList(); + if (appNames != null && !appNames.isEmpty()) { for (String app : appNames) { - Long id = providerNameToDetails.get(app).id; + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(app)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + Long id = response.getBodyElement0().get(0); + if (id != null) { EntityKey entitykey = new EntityKey(new Identifier(app), id, 0L, 0L); entityKeys.add(entitykey); @@ -147,12 +150,7 @@ public void run() { if (entityKeys.isEmpty()) { System.out.println("Could not find any providers matching provided names!"); - System.out.println("Available providers:"); - for (Map.Entry entry : providerNameToDetails.entrySet()) { - System.out.println(entry.getKey() + " - Running: " + entry.getValue().appDetails - .getRunning()); - } - return; + System.exit(ExitCodes.GENERIC_ERROR); } EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); @@ -166,7 +164,7 @@ public void run() { appsLauncher.monitorExecutionRegister(subscription, new AppsLauncherAdapter() { @Override public void monitorExecutionNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, - UpdateHeaderList updateHeaderList, StringList strings, Map qosProperties) { + UpdateHeaderList updateHeaderList, StringList strings, Map qosProperties) { for (int i = 0; i < updateHeaderList.size(); i++) { String providerName = updateHeaderList.get(i).getKey().getFirstSubKey().getValue(); String[] lines = strings.get(i).split("\n"); @@ -177,89 +175,90 @@ public void monitorExecutionNotifyReceived(MALMessageHeader msgHeader, Identifie } }); + final Object lock = new Object(); + synchronized (lock) { lock.wait(); } } catch (MALInteractionException | MALException | InterruptedException e) { LOGGER.log(Level.SEVERE, "Error during heartbeat register!", e); + System.exit(ExitCodes.GENERIC_ERROR); } } } @Command(name = "run", description = "Runs the specified provider app") public static class RunApp extends BaseCommand implements Runnable { + @Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to run.") String appName; @Override public void run() { if (!super.initRemoteConsumer()) { - return; + System.exit(ExitCodes.NO_HOST); } if (consumer.getSMServices().getAppsLauncherService() == null) { System.out.println("Apps launcher service is not available for this provider!"); - return; + System.exit(ExitCodes.UNAVAILABLE); } try { - AppsLauncherStub appsLauncher = consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); - - ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - Map providerNameToDetails = getProvidersDetails(archive); - if (!checkProvider(providerNameToDetails, appName)) { - return; + AppsLauncherStub appsLauncher = getAppsLauncher(); + // ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); + // Map providerNameToDetails = getProvidersDetails(archive); + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(appName)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + LongList appIds = response.getBodyElement0(); + + if (!checkProvider(appIds)) { + System.exit(ExitCodes.GENERIC_ERROR); } - LongList ids = new LongList(); - ids.add(providerNameToDetails.get(appName).id); - appsLauncher.runApp(ids); - - } catch (MALInteractionException | MALException | InterruptedException e) { + appsLauncher.runApp(appIds); + } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Error during runApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); } } } @Command(name = "stop", description = "Stops the specified provider app") public static class StopApp extends BaseCommand implements Runnable { + @Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to stop.") String appName; @Override public void run() { if (!super.initRemoteConsumer()) { - return; + System.exit(ExitCodes.NO_HOST); } if (consumer.getSMServices().getAppsLauncherService() == null) { System.out.println("Apps launcher service is not available for this provider!"); - return; + System.exit(ExitCodes.UNAVAILABLE); } try { - AppsLauncherStub appsLauncher = consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); - - ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - Map providerNameToDetails = getProvidersDetails(archive); - - if (!checkProvider(providerNameToDetails, appName)) { - return; + AppsLauncherStub appsLauncher = getAppsLauncher(); + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(appName)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + LongList appIds = response.getBodyElement0(); + + if (!checkProvider(appIds)) { + System.exit(ExitCodes.GENERIC_ERROR); } final Object lock = new Object(); - LongList ids = new LongList(); - ids.add(providerNameToDetails.get(appName).id); - appsLauncher.stopApp(ids, new AppsLauncherAdapter() { + appsLauncher.stopApp(appIds, new AppsLauncherAdapter() { @Override public void stopAppUpdateReceived(MALMessageHeader msgHeader, Long appClosing, Map qosProperties) { - for (ProviderAppDetails details : providerNameToDetails.values()) { - if (appClosing.equals(details.id)) { - System.out.println(details.appDetails.getName() + " closing in progress..."); - break; - } - } + System.out.println("Closing App with id: " + appClosing); } @Override @@ -273,7 +272,7 @@ public void stopAppResponseReceived(MALMessageHeader msgHeader, Map qosPropertie @Override public void stopAppUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { + Map qosProperties) { LOGGER.log(Level.SEVERE, "Error during stopApp!", error); synchronized (lock) { lock.notifyAll(); @@ -282,7 +281,7 @@ public void stopAppUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardEr @Override public void stopAppResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { + Map qosProperties) { LOGGER.log(Level.SEVERE, "Error during stopApp!", error); synchronized (lock) { lock.notifyAll(); @@ -296,60 +295,74 @@ public void stopAppResponseErrorReceived(MALMessageHeader msgHeader, MALStandard } catch (MALInteractionException | MALException | InterruptedException e) { LOGGER.log(Level.SEVERE, "Error during stopApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); } } } @Command(name = "kill", description = "Kills the specified provider app") public static class KillApp extends BaseCommand implements Runnable { + @Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to kill.") String appName; @Override public void run() { if (!super.initRemoteConsumer()) { - return; + System.exit(ExitCodes.NO_HOST); } if (consumer.getSMServices().getAppsLauncherService() == null) { System.out.println("Apps launcher service is not available for this provider!"); - return; + System.exit(ExitCodes.UNAVAILABLE); } try { - AppsLauncherStub appsLauncher = consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); - - ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - Map providerNameToDetails = getProvidersDetails(archive); - - if (!checkProvider(providerNameToDetails, appName)) { - return; + AppsLauncherStub appsLauncher = getAppsLauncher(); + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(appName)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + LongList appIds = response.getBodyElement0(); + + if (!checkProvider(appIds)) { + System.exit(ExitCodes.GENERIC_ERROR); } - LongList ids = new LongList(); - ids.add(providerNameToDetails.get(appName).id); - appsLauncher.killApp(ids); - } catch (MALInteractionException | MALException | InterruptedException e) { + appsLauncher.killApp(appIds); + } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Error during killApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); } } } - private static boolean checkProvider(Map providers, String provider) { - if (!providers.containsKey(provider)) { + private static boolean checkProvider(LongList matchingApps) { + if (matchingApps.size() != 1) { System.out.println("Could not find any apps matching provided name!"); - System.out.println("Available apps:"); - for (Map.Entry entry : providers.entrySet()) { - System.out.println(entry.getKey() + " - Running: " + entry.getValue().appDetails.getRunning()); + + ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); + try { + Map providers = getProvidersDetails(archive); + System.out.println("Available apps:"); + for (Map.Entry entry : providers.entrySet()) { + System.out.println(entry.getKey() + " - Running: " + entry.getValue().appDetails.getRunning()); + } + } catch (MALInteractionException | MALException | InterruptedException ex) { + LOGGER.log(Level.SEVERE, "Error while retrieving the available Apps!", ex); } + return false; } return true; } + public static AppsLauncherStub getAppsLauncher() { + return consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); + } + private static Map getProvidersDetails(ArchiveStub archive) - throws MALInteractionException, MALException, InterruptedException { + throws MALInteractionException, MALException, InterruptedException { final Object lock = new Object(); ArchiveQueryList queries = new ArchiveQueryList(); @@ -357,27 +370,27 @@ private static Map getProvidersDetails(ArchiveStub a Map result = new HashMap<>(); ObjectType appType = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), - AppsLauncherHelper.APP_OBJECT_NUMBER); + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), + AppsLauncherHelper.APP_OBJECT_NUMBER); archive.query(true, appType, queries, null, new ArchiveAdapter() { @Override public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { for (int i = 0; i < objDetails.size(); ++i) { AppDetails details = (AppDetails) objBodies.get(i); result.put(details.getName().getValue(), new ProviderAppDetails(objDetails.get(i).getInstId(), - details)); + details)); } } @Override public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { if (objDetails != null) { for (int i = 0; i < objDetails.size(); ++i) { AppDetails details = (AppDetails) objBodies.get(i); result.put(details.getName().getValue(), new ProviderAppDetails(objDetails.get(i).getInstId(), - details)); + details)); } } @@ -388,7 +401,7 @@ public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType @Override public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { + Map qosProperties) { LOGGER.log(Level.SEVERE, "Error during archive query!", error); synchronized (lock) { lock.notifyAll(); @@ -397,7 +410,7 @@ public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardErro @Override public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { + Map qosProperties) { LOGGER.log(Level.SEVERE, "Error during archive query!", error); synchronized (lock) { lock.notifyAll(); @@ -413,6 +426,7 @@ public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardEr } private static class ProviderAppDetails { + Long id; AppDetails appDetails; @@ -421,6 +435,4 @@ public ProviderAppDetails(Long id, AppDetails appDetails) { this.id = id; } } - } -//------------------------------------------------------------------------------ \ No newline at end of file From 8f8ec63384d8052b57d79d77c9d8a9642ff8a659 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 24 Feb 2023 20:55:41 +0100 Subject: [PATCH 167/173] Code cleanup --- .../java/esa/mo/nmf/clitool/BaseCommand.java | 64 ++++++++++--------- .../main/java/esa/mo/nmf/clitool/CLITool.java | 1 - .../clitool/SoftwareManagementCommands.java | 9 ++- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java index 9f1d0b010..b7fe702b4 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java @@ -27,6 +27,12 @@ import esa.mo.nmf.NMFConsumer; import esa.mo.nmf.clitool.adapters.ArchiveToAppAdapter; import esa.mo.nmf.clitool.adapters.QueryStatusProvider; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; import org.ccsds.moims.mo.com.archive.consumer.ArchiveStub; import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; @@ -41,34 +47,33 @@ import org.ccsds.moims.mo.common.login.structures.Profile; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; -import org.ccsds.moims.mo.mal.structures.*; +import org.ccsds.moims.mo.mal.structures.ElementList; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.LongList; +import org.ccsds.moims.mo.mal.structures.UOctet; +import org.ccsds.moims.mo.mal.structures.URI; import org.ccsds.moims.mo.mal.transport.MALMessageHeader; import org.ccsds.moims.mo.softwaremanagement.SoftwareManagementHelper; import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; -import picocli.CommandLine.*; - -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; +import picocli.CommandLine.Option; /** * @author marcel.mikolajko */ public abstract class BaseCommand { + private static final Logger LOGGER = Logger.getLogger(BaseCommand.class.getName()); @Option(names = {"-h", "--help"}, usageHelp = true, description = "display a help message") private boolean helpRequested; - @Option(names = {"-r", "--remote"}, paramLabel = "", description = "Provider URI\n" + - " - example: maltcp://10.0.2.15:1024/nanosat-mo-supervisor-Directory") + @Option(names = {"-r", "--remote"}, paramLabel = "", description = "Provider URI\n" + + " - example: maltcp://10.0.2.15:1024/nanosat-mo-supervisor-Directory") public String providerURI; - @Option(names = {"-l", "--local"}, paramLabel = "", description = "Local SQLite database file\n" + - " - example: ../nanosat-mo-supervisor-sim/comArchive.db") + @Option(names = {"-l", "--local"}, paramLabel = "", description = "Local SQLite database file\n" + + " - example: ../nanosat-mo-supervisor-sim/comArchive.db") public String databaseFile; @Option(names = {"-p", "--provider"}, paramLabel = "", @@ -90,7 +95,7 @@ public boolean initLocalArchiveProvider(String databaseFile) { try { localArchiveProvider.init(null); LOGGER.log(Level.INFO, String.format("ArchiveProvider initialized at %s with file %s", localArchiveProvider - .getConnection().getConnectionDetails().getProviderURI(), databaseFile)); + .getConnection().getConnectionDetails().getProviderURI(), databaseFile)); } catch (MALException e) { LOGGER.log(Level.SEVERE, "Error initializing archiveProvider", e); return false; @@ -175,8 +180,8 @@ public boolean initRemoteConsumer() { consumer.init(); domain = provider.getProviderKey().getDomain(); - if (consumer.getCommonServices().getLoginService() != null && consumer.getCommonServices().getLoginService() - .getLoginStub() != null) { + if (consumer.getCommonServices().getLoginService() != null + && consumer.getCommonServices().getLoginService().getLoginStub() != null) { System.out.println("\nLogin required for " + provider.getProviderId()); String login = System.console().readLine("Login: "); @@ -184,7 +189,7 @@ public boolean initRemoteConsumer() { System.out.println(); LongList ids = consumer.getCommonServices().getLoginService().getLoginStub().listRoles(new Identifier( - login), String.valueOf(password)); + login), String.valueOf(password)); List roleIds = new ArrayList<>(); List roleNames = new ArrayList<>(); @@ -192,7 +197,7 @@ public boolean initRemoteConsumer() { ArchiveAdapter adapter = new ArchiveAdapter() { @Override public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, - ElementList objBodies, Map qosProperties) { + ElementList objBodies, Map qosProperties) { for (int i = 0; i < objDetails.size(); ++i) { roleIds.add(objDetails.get(i).getInstId()); roleNames.add(objBodies.get(i).toString()); @@ -204,8 +209,8 @@ public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsL }; consumer.getCOMServices().getArchiveService().getArchiveStub().retrieve( - LoginHelper.LOGINROLE_OBJECT_TYPE, consumer.getCommonServices().getLoginService() - .getConnectionDetails().getDomain(), ids, adapter); + LoginHelper.LOGINROLE_OBJECT_TYPE, consumer.getCommonServices().getLoginService() + .getConnectionDetails().getDomain(), ids, adapter); synchronized (lock) { lock.wait(10000); @@ -224,7 +229,7 @@ public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsL } LoginResponse response = consumer.getCommonServices().getLoginService().getLoginStub().login( - new Profile(new Identifier(login), roleId), String.valueOf(password)); + new Profile(new Identifier(login), roleId), String.valueOf(password)); consumer.setAuthenticationId(response.getBodyElement0()); System.out.println("Login successful!"); } @@ -263,7 +268,7 @@ public static void closeConsumer() { ids.clear(); ids.add(SoftwareManagementCommands.outputSubscription); consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub().monitorExecutionDeregister( - ids); + ids); } } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Failed to deregister subscription: " + ids.get(0), e); @@ -286,7 +291,8 @@ public static void closeConsumer() { localArchiveProvider.close(); localArchiveProvider = null; } - System.out.println("Consumer successfully closed."); + + LOGGER.log(Level.INFO, "CLI-Tool successfully disconnected!"); } /** @@ -298,11 +304,11 @@ public static void closeConsumer() { * @param queryStatusProvider Interface providing the status of the query */ public static void queryArchive(ObjectType objectsTypes, ArchiveQueryList archiveQueryList, ArchiveAdapter adapter, - QueryStatusProvider queryStatusProvider) { + QueryStatusProvider queryStatusProvider) { // run the query try { ArchiveStub archive = localArchive == null ? consumer.getCOMServices().getArchiveService() - .getArchiveStub() : localArchive.getArchiveStub(); + .getArchiveStub() : localArchive.getArchiveStub(); archive.query(true, objectsTypes, archiveQueryList, null, adapter); } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Error when querying archive", e); @@ -319,8 +325,8 @@ public static void queryArchive(ObjectType objectsTypes, ArchiveQueryList archiv } /** - * Search a COM archive provider content to find the ObjectId of an App of the CommandExecutor - * service of the SoftwareManagement. + * Search a COM archive provider content to find the ObjectId of an App of + * the CommandExecutor service of the SoftwareManagement. * * @param appName Name of the NMF app we want the logs for * @param domain Restricts the search to objects in a specific domain ID @@ -329,8 +335,8 @@ public static void queryArchive(ObjectType objectsTypes, ArchiveQueryList archiv public static ObjectId getAppObjectId(String appName, IdentifierList domain) { // SoftwareManagement.AppsLaunch.App object type ObjectType appType = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), - AppsLauncherHelper.APP_OBJECT_NUMBER); + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), + AppsLauncherHelper.APP_OBJECT_NUMBER); // prepare domain filter ArchiveQueryList archiveQueryList = new ArchiveQueryList(); diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java index 3cffae83d..a5acc1829 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java @@ -50,4 +50,3 @@ public static void main(String[] args) { System.exit(cmd.execute(args)); } } -//------------------------------------------------------------------------------ \ No newline at end of file diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java index 886df9e10..2da0e6dd7 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java @@ -46,7 +46,8 @@ import org.ccsds.moims.mo.softwaremanagement.appslauncher.structures.AppDetails; import org.ccsds.moims.mo.softwaremanagement.heartbeat.consumer.HeartbeatAdapter; import org.ccsds.moims.mo.softwaremanagement.heartbeat.consumer.HeartbeatStub; -import picocli.CommandLine.*; +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; /** * @author marcel.mikolajko @@ -206,8 +207,6 @@ public void run() { try { AppsLauncherStub appsLauncher = getAppsLauncher(); - // ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - // Map providerNameToDetails = getProvidersDetails(archive); IdentifierList appsToSearch = new IdentifierList(); appsToSearch.add(new Identifier(appName)); ListAppResponse response = appsLauncher.listApp(appsToSearch, null); @@ -258,12 +257,12 @@ public void run() { appsLauncher.stopApp(appIds, new AppsLauncherAdapter() { @Override public void stopAppUpdateReceived(MALMessageHeader msgHeader, Long appClosing, Map qosProperties) { - System.out.println("Closing App with id: " + appClosing); + System.out.println("Stopping App with id: " + appClosing); } @Override public void stopAppResponseReceived(MALMessageHeader msgHeader, Map qosProperties) { - System.out.println("App closed!"); + System.out.println("App stopped!"); synchronized (lock) { lock.notifyAll(); From 67cb5153e36381b03fbe9f9fd55f35523bb6a754 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 19 Apr 2023 12:42:31 +0200 Subject: [PATCH 168/173] Adds progress messages and ups the version of the picocli library --- sdk/tools/cli-tool/pom.xml | 2 +- .../cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/sdk/tools/cli-tool/pom.xml b/sdk/tools/cli-tool/pom.xml index 353a23871..c34f27e43 100644 --- a/sdk/tools/cli-tool/pom.xml +++ b/sdk/tools/cli-tool/pom.xml @@ -69,7 +69,7 @@ info.picocli picocli - 4.6.1 + 4.7.1 com.googlecode.json-simple diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java index a5acc1829..3b59a93ae 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java @@ -41,11 +41,16 @@ public class CLITool { private boolean helpRequested; public static void main(String[] args) { + System.out.println("(1) The application is running..."); Runtime.getRuntime().addShutdownHook(new Thread(BaseCommand::closeConsumer)); + System.out.println("(2) The application is running..."); CLITool cliConsumer = new CLITool(); + System.out.println("(3) The application is running..."); CommandLine cmd = new CommandLine(cliConsumer); + System.out.println("(4) The application is running..."); cmd.setUsageHelpAutoWidth(true); cmd.setUsageHelpLongOptionsMaxWidth(30); + System.out.println("(5) The application is running..."); System.exit(cmd.execute(args)); } From 8f5b99c22b1056cb5a55d92542e018887c204344 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 19 Apr 2023 14:08:36 +0200 Subject: [PATCH 169/173] Refactors the code and adds a first class with the Package Management commands --- .../main/java/esa/mo/nmf/clitool/Helper.java | 152 ++++++++ .../java/esa/mo/nmf/clitool/LogsCommands.java | 6 +- .../clitool/SoftwareManagementCommands.java | 358 +----------------- .../nmf/clitool/sm/AppsLauncherCommands.java | 290 ++++++++++++++ .../clitool/sm/PackageManagementCommands.java | 84 ++++ 5 files changed, 545 insertions(+), 345 deletions(-) create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java new file mode 100644 index 000000000..199de2f74 --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java @@ -0,0 +1,152 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool; + +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; +import org.ccsds.moims.mo.com.archive.consumer.ArchiveStub; +import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; +import org.ccsds.moims.mo.com.structures.ObjectType; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.mal.structures.ElementList; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.LongList; +import org.ccsds.moims.mo.mal.structures.UOctet; +import org.ccsds.moims.mo.mal.transport.MALMessageHeader; +import org.ccsds.moims.mo.softwaremanagement.SoftwareManagementHelper; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.structures.AppDetails; + +/** + * The Helper class includes static methods that can be used by all other + * clases. + * + * @author Cesar Coelho + */ +public class Helper { + + private static final Logger LOGGER = Logger.getLogger(Helper.class.getName()); + + public static boolean checkProvider(LongList matchingApps) { + if (matchingApps.size() != 1) { + System.out.println("Could not find any apps matching provided name!"); + + ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); + try { + Map providers = getProvidersDetails(archive); + System.out.println("Available apps:"); + for (Map.Entry entry : providers.entrySet()) { + System.out.println(entry.getKey() + " - Running: " + entry.getValue().appDetails.getRunning()); + } + } catch (MALInteractionException | MALException | InterruptedException ex) { + LOGGER.log(Level.SEVERE, "Error while retrieving the available Apps!", ex); + } + + return false; + } + + return true; + } + + public static Map getProvidersDetails(ArchiveStub archive) + throws MALInteractionException, MALException, InterruptedException { + final Object lock = new Object(); + + ArchiveQueryList queries = new ArchiveQueryList(); + queries.add(new ArchiveQuery(BaseCommand.domain, null, null, 0L, null, null, null, null, null)); + + Map result = new HashMap<>(); + ObjectType appType = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), + AppsLauncherHelper.APP_OBJECT_NUMBER); + archive.query(true, appType, queries, null, new ArchiveAdapter() { + @Override + public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + for (int i = 0; i < objDetails.size(); ++i) { + AppDetails details = (AppDetails) objBodies.get(i); + result.put(details.getName().getValue(), + new ProviderAppDetails(objDetails.get(i).getInstId(), details)); + } + } + + @Override + public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + if (objDetails != null) { + for (int i = 0; i < objDetails.size(); ++i) { + AppDetails details = (AppDetails) objBodies.get(i); + result.put(details.getName().getValue(), + new ProviderAppDetails(objDetails.get(i).getInstId(), details)); + } + } + + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive query!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive query!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + return result; + } + + private static class ProviderAppDetails { + + Long id; + AppDetails appDetails; + + public ProviderAppDetails(Long id, AppDetails appDetails) { + this.appDetails = appDetails; + this.id = id; + } + } + +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java index 3d4ce500a..6d689b779 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java @@ -68,7 +68,8 @@ public static class ListLogs extends BaseCommand implements Runnable { @Option(names = {"-e", "--end"}, paramLabel = "", description = "Restricts the list to NMF apps having logs logged before the given time. " + - "If this option is provided without the -s option, returns the single object that has the closest timestamp to, but not greater than \n" + + "If this option is provided without the -s option, returns the single " + + "object that has the closest timestamp to, but not greater than \n" + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") String endTime; @@ -138,7 +139,8 @@ public static class GetLogs extends BaseCommand implements Runnable { @Option(names = {"-e", "--end"}, paramLabel = "", description = "Restricts the dump to logs logged before the given time. " + - "If this option is provided without the -s option, returns the single object that has the closest timestamp to, but not greater than \n" + + "If this option is provided without the -s option, returns the single " + + "object that has the closest timestamp to, but not greater than \n" + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") String endTime; diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java index 2da0e6dd7..1dd50bdcf 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java @@ -22,32 +22,22 @@ import esa.mo.helpertools.connections.ConnectionConsumer; import static esa.mo.nmf.clitool.BaseCommand.consumer; -import java.util.HashMap; -import java.util.List; +import esa.mo.nmf.clitool.sm.AppsLauncherCommands.KillApp; +import esa.mo.nmf.clitool.sm.AppsLauncherCommands.MonitorExecution; +import esa.mo.nmf.clitool.sm.AppsLauncherCommands.RunApp; +import esa.mo.nmf.clitool.sm.AppsLauncherCommands.StopApp; +import esa.mo.nmf.clitool.sm.PackageManagementCommands.FindPackage; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; -import org.ccsds.moims.mo.com.archive.consumer.ArchiveStub; -import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; -import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; -import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; -import org.ccsds.moims.mo.com.structures.ObjectType; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; -import org.ccsds.moims.mo.mal.MALStandardError; import org.ccsds.moims.mo.mal.structures.*; import org.ccsds.moims.mo.mal.transport.MALMessageHeader; -import org.ccsds.moims.mo.softwaremanagement.SoftwareManagementHelper; -import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; -import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; -import org.ccsds.moims.mo.softwaremanagement.appslauncher.consumer.AppsLauncherAdapter; -import org.ccsds.moims.mo.softwaremanagement.appslauncher.consumer.AppsLauncherStub; -import org.ccsds.moims.mo.softwaremanagement.appslauncher.structures.AppDetails; import org.ccsds.moims.mo.softwaremanagement.heartbeat.consumer.HeartbeatAdapter; import org.ccsds.moims.mo.softwaremanagement.heartbeat.consumer.HeartbeatStub; +import org.ccsds.moims.mo.softwaremanagement.packagemanagement.consumer.PackageManagementStub; import picocli.CommandLine.Command; -import picocli.CommandLine.Parameters; /** * @author marcel.mikolajko @@ -59,14 +49,18 @@ public class SoftwareManagementCommands { public static Identifier heartbeatSubscription; public static Identifier outputSubscription; - @Command(name = "apps-launcher", subcommands = {MonitorExecution.class, RunApp.class, StopApp.class, KillApp.class}) - public static class AppsLauncher { + @Command(name = "software-management", subcommands = {FindPackage.class}) + public static class SoftwareManagement { } @Command(name = "heartbeat", subcommands = {Beat.class}) public static class Heartbeat { } + @Command(name = "apps-launcher", subcommands = {MonitorExecution.class, RunApp.class, StopApp.class, KillApp.class}) + public static class AppsLauncher { + } + @Command(name = "subscribe", description = "Subscribes to provider's heartbeat") public static class Beat extends BaseCommand implements Runnable { @@ -108,330 +102,8 @@ public void beatNotifyReceived(MALMessageHeader msgHeader, Identifier identifier } } } - - @Command(name = "subscribe", description = "Subscribes to app's stdout") - public static class MonitorExecution extends BaseCommand implements Runnable { - - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the apps to subscribe to. If non are specified subscribe to all.") - List appNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - System.exit(ExitCodes.NO_HOST); - } - - if (consumer.getSMServices().getAppsLauncherService() == null) { - System.out.println("Apps launcher service is not available for this provider!"); - System.exit(ExitCodes.UNAVAILABLE); - } - - try { - AppsLauncherStub appsLauncher = getAppsLauncher(); - Long timestamp = System.currentTimeMillis(); - Identifier subscriptionId = new Identifier("CLI-Consumer-AppsLauncherSubscription_" + timestamp); - Subscription subscription = ConnectionConsumer.subscriptionWildcard(subscriptionId); - EntityKeyList entityKeys = new EntityKeyList(); - - if (appNames != null && !appNames.isEmpty()) { - for (String app : appNames) { - IdentifierList appsToSearch = new IdentifierList(); - appsToSearch.add(new Identifier(app)); - ListAppResponse response = appsLauncher.listApp(appsToSearch, null); - Long id = response.getBodyElement0().get(0); - - if (id != null) { - EntityKey entitykey = new EntityKey(new Identifier(app), id, 0L, 0L); - entityKeys.add(entitykey); - } else { - System.out.println("Provider " + app + " not found!"); - } - } - - if (entityKeys.isEmpty()) { - System.out.println("Could not find any providers matching provided names!"); - System.exit(ExitCodes.GENERIC_ERROR); - } - - EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); - EntityRequestList entities = new EntityRequestList(); - entities.add(entity); - - subscription = new Subscription(subscriptionId, entities); - } - outputSubscription = subscriptionId; - - appsLauncher.monitorExecutionRegister(subscription, new AppsLauncherAdapter() { - @Override - public void monitorExecutionNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, - UpdateHeaderList updateHeaderList, StringList strings, Map qosProperties) { - for (int i = 0; i < updateHeaderList.size(); i++) { - String providerName = updateHeaderList.get(i).getKey().getFirstSubKey().getValue(); - String[] lines = strings.get(i).split("\n"); - for (String line : lines) { - System.out.println("[" + providerName + "]: " + line); - } - } - } - }); - - final Object lock = new Object(); - - synchronized (lock) { - lock.wait(); - } - } catch (MALInteractionException | MALException | InterruptedException e) { - LOGGER.log(Level.SEVERE, "Error during heartbeat register!", e); - System.exit(ExitCodes.GENERIC_ERROR); - } - } - } - - @Command(name = "run", description = "Runs the specified provider app") - public static class RunApp extends BaseCommand implements Runnable { - - @Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to run.") - String appName; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - System.exit(ExitCodes.NO_HOST); - } - - if (consumer.getSMServices().getAppsLauncherService() == null) { - System.out.println("Apps launcher service is not available for this provider!"); - System.exit(ExitCodes.UNAVAILABLE); - } - - try { - AppsLauncherStub appsLauncher = getAppsLauncher(); - IdentifierList appsToSearch = new IdentifierList(); - appsToSearch.add(new Identifier(appName)); - ListAppResponse response = appsLauncher.listApp(appsToSearch, null); - LongList appIds = response.getBodyElement0(); - - if (!checkProvider(appIds)) { - System.exit(ExitCodes.GENERIC_ERROR); - } - - appsLauncher.runApp(appIds); - } catch (MALInteractionException | MALException e) { - LOGGER.log(Level.SEVERE, "Error during runApp!", e); - System.exit(ExitCodes.GENERIC_ERROR); - } - } - } - - @Command(name = "stop", description = "Stops the specified provider app") - public static class StopApp extends BaseCommand implements Runnable { - - @Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to stop.") - String appName; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - System.exit(ExitCodes.NO_HOST); - } - - if (consumer.getSMServices().getAppsLauncherService() == null) { - System.out.println("Apps launcher service is not available for this provider!"); - System.exit(ExitCodes.UNAVAILABLE); - } - - try { - AppsLauncherStub appsLauncher = getAppsLauncher(); - IdentifierList appsToSearch = new IdentifierList(); - appsToSearch.add(new Identifier(appName)); - ListAppResponse response = appsLauncher.listApp(appsToSearch, null); - LongList appIds = response.getBodyElement0(); - - if (!checkProvider(appIds)) { - System.exit(ExitCodes.GENERIC_ERROR); - } - - final Object lock = new Object(); - - appsLauncher.stopApp(appIds, new AppsLauncherAdapter() { - @Override - public void stopAppUpdateReceived(MALMessageHeader msgHeader, Long appClosing, Map qosProperties) { - System.out.println("Stopping App with id: " + appClosing); - } - - @Override - public void stopAppResponseReceived(MALMessageHeader msgHeader, Map qosProperties) { - System.out.println("App stopped!"); - - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void stopAppUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during stopApp!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void stopAppResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during stopApp!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - } catch (MALInteractionException | MALException | InterruptedException e) { - LOGGER.log(Level.SEVERE, "Error during stopApp!", e); - System.exit(ExitCodes.GENERIC_ERROR); - } - } - } - - @Command(name = "kill", description = "Kills the specified provider app") - public static class KillApp extends BaseCommand implements Runnable { - - @Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to kill.") - String appName; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - System.exit(ExitCodes.NO_HOST); - } - - if (consumer.getSMServices().getAppsLauncherService() == null) { - System.out.println("Apps launcher service is not available for this provider!"); - System.exit(ExitCodes.UNAVAILABLE); - } - - try { - AppsLauncherStub appsLauncher = getAppsLauncher(); - IdentifierList appsToSearch = new IdentifierList(); - appsToSearch.add(new Identifier(appName)); - ListAppResponse response = appsLauncher.listApp(appsToSearch, null); - LongList appIds = response.getBodyElement0(); - - if (!checkProvider(appIds)) { - System.exit(ExitCodes.GENERIC_ERROR); - } - - appsLauncher.killApp(appIds); - } catch (MALInteractionException | MALException e) { - LOGGER.log(Level.SEVERE, "Error during killApp!", e); - System.exit(ExitCodes.GENERIC_ERROR); - } - } - } - - private static boolean checkProvider(LongList matchingApps) { - if (matchingApps.size() != 1) { - System.out.println("Could not find any apps matching provided name!"); - - ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - try { - Map providers = getProvidersDetails(archive); - System.out.println("Available apps:"); - for (Map.Entry entry : providers.entrySet()) { - System.out.println(entry.getKey() + " - Running: " + entry.getValue().appDetails.getRunning()); - } - } catch (MALInteractionException | MALException | InterruptedException ex) { - LOGGER.log(Level.SEVERE, "Error while retrieving the available Apps!", ex); - } - - return false; - } - - return true; - } - - public static AppsLauncherStub getAppsLauncher() { - return consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); - } - - private static Map getProvidersDetails(ArchiveStub archive) - throws MALInteractionException, MALException, InterruptedException { - final Object lock = new Object(); - - ArchiveQueryList queries = new ArchiveQueryList(); - queries.add(new ArchiveQuery(BaseCommand.domain, null, null, 0L, null, null, null, null, null)); - - Map result = new HashMap<>(); - ObjectType appType = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, new UOctet((short) 0), - AppsLauncherHelper.APP_OBJECT_NUMBER); - archive.query(true, appType, queries, null, new ArchiveAdapter() { - @Override - public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { - for (int i = 0; i < objDetails.size(); ++i) { - AppDetails details = (AppDetails) objBodies.get(i); - result.put(details.getName().getValue(), new ProviderAppDetails(objDetails.get(i).getInstId(), - details)); - } - } - - @Override - public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { - if (objDetails != null) { - for (int i = 0; i < objDetails.size(); ++i) { - AppDetails details = (AppDetails) objBodies.get(i); - result.put(details.getName().getValue(), new ProviderAppDetails(objDetails.get(i).getInstId(), - details)); - } - } - - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive query!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive query!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - return result; - } - - private static class ProviderAppDetails { - - Long id; - AppDetails appDetails; - - public ProviderAppDetails(Long id, AppDetails appDetails) { - this.appDetails = appDetails; - this.id = id; - } + + public static PackageManagementStub getPackageManagement() { + return consumer.getSMServices().getPackageManagementService().getPackageManagementStub(); } } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java new file mode 100644 index 000000000..82ec193ec --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java @@ -0,0 +1,290 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.sm; + +import esa.mo.helpertools.connections.ConnectionConsumer; +import esa.mo.nmf.clitool.BaseCommand; +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import esa.mo.nmf.clitool.ExitCodes; +import esa.mo.nmf.clitool.Helper; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.mal.structures.EntityKey; +import org.ccsds.moims.mo.mal.structures.EntityKeyList; +import org.ccsds.moims.mo.mal.structures.EntityRequest; +import org.ccsds.moims.mo.mal.structures.EntityRequestList; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.LongList; +import org.ccsds.moims.mo.mal.structures.StringList; +import org.ccsds.moims.mo.mal.structures.Subscription; +import org.ccsds.moims.mo.mal.structures.UpdateHeaderList; +import org.ccsds.moims.mo.mal.transport.MALMessageHeader; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.body.ListAppResponse; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.consumer.AppsLauncherAdapter; +import org.ccsds.moims.mo.softwaremanagement.appslauncher.consumer.AppsLauncherStub; +import picocli.CommandLine; + +/** + * The AppsLauncherCommands class contains the static classes for the Apps + * Launcher service. + * + * @author Cesar Coelho + */ +public class AppsLauncherCommands { + + private static final Logger LOGGER = Logger.getLogger(AppsLauncherCommands.class.getName()); + + @CommandLine.Command(name = "subscribe", description = "Subscribes to app's stdout") + public static class MonitorExecution extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the apps to subscribe to. If non are specified subscribe to all.") + List appNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getAppsLauncherService() == null) { + System.out.println("Apps launcher service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + AppsLauncherStub appsLauncher = getAppsLauncher(); + Long timestamp = System.currentTimeMillis(); + Identifier subscriptionId = new Identifier("CLI-Consumer-AppsLauncherSubscription_" + timestamp); + Subscription subscription = ConnectionConsumer.subscriptionWildcard(subscriptionId); + EntityKeyList entityKeys = new EntityKeyList(); + + if (appNames != null && !appNames.isEmpty()) { + for (String app : appNames) { + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(app)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + Long id = response.getBodyElement0().get(0); + + if (id != null) { + EntityKey entitykey = new EntityKey(new Identifier(app), id, 0L, 0L); + entityKeys.add(entitykey); + } else { + System.out.println("Provider " + app + " not found!"); + } + } + + if (entityKeys.isEmpty()) { + System.out.println("Could not find any providers matching provided names!"); + System.exit(ExitCodes.GENERIC_ERROR); + } + + EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); + EntityRequestList entities = new EntityRequestList(); + entities.add(entity); + + subscription = new Subscription(subscriptionId, entities); + } + outputSubscription = subscriptionId; + + appsLauncher.monitorExecutionRegister(subscription, new AppsLauncherAdapter() { + @Override + public void monitorExecutionNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, + UpdateHeaderList updateHeaderList, StringList strings, Map qosProperties) { + for (int i = 0; i < updateHeaderList.size(); i++) { + String providerName = updateHeaderList.get(i).getKey().getFirstSubKey().getValue(); + String[] lines = strings.get(i).split("\n"); + for (String line : lines) { + System.out.println("[" + providerName + "]: " + line); + } + } + } + }); + + final Object lock = new Object(); + + synchronized (lock) { + lock.wait(); + } + } catch (MALInteractionException | MALException | InterruptedException e) { + LOGGER.log(Level.SEVERE, "Error during heartbeat register!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + @CommandLine.Command(name = "run", description = "Runs the specified provider app") + public static class RunApp extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to run.") + String appName; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getAppsLauncherService() == null) { + System.out.println("Apps launcher service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + AppsLauncherStub appsLauncher = getAppsLauncher(); + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(appName)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + LongList appIds = response.getBodyElement0(); + + if (!Helper.checkProvider(appIds)) { + System.exit(ExitCodes.GENERIC_ERROR); + } + + appsLauncher.runApp(appIds); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during runApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + @CommandLine.Command(name = "stop", description = "Stops the specified provider app") + public static class StopApp extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to stop.") + String appName; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getAppsLauncherService() == null) { + System.out.println("Apps launcher service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + AppsLauncherStub appsLauncher = getAppsLauncher(); + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(appName)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + LongList appIds = response.getBodyElement0(); + + if (!Helper.checkProvider(appIds)) { + System.exit(ExitCodes.GENERIC_ERROR); + } + + final Object lock = new Object(); + + appsLauncher.stopApp(appIds, new AppsLauncherAdapter() { + @Override + public void stopAppUpdateReceived(MALMessageHeader msgHeader, Long appClosing, Map qosProperties) { + System.out.println("Stopping App with id: " + appClosing); + } + + @Override + public void stopAppResponseReceived(MALMessageHeader msgHeader, Map qosProperties) { + System.out.println("App stopped!"); + + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void stopAppUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during stopApp!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void stopAppResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during stopApp!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + } catch (MALInteractionException | MALException | InterruptedException e) { + LOGGER.log(Level.SEVERE, "Error during stopApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + @CommandLine.Command(name = "kill", description = "Kills the specified provider app") + public static class KillApp extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the app to kill.") + String appName; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getAppsLauncherService() == null) { + System.out.println("Apps launcher service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + AppsLauncherStub appsLauncher = getAppsLauncher(); + IdentifierList appsToSearch = new IdentifierList(); + appsToSearch.add(new Identifier(appName)); + ListAppResponse response = appsLauncher.listApp(appsToSearch, null); + LongList appIds = response.getBodyElement0(); + + if (!Helper.checkProvider(appIds)) { + System.exit(ExitCodes.GENERIC_ERROR); + } + + appsLauncher.killApp(appIds); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during killApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + public static AppsLauncherStub getAppsLauncher() { + return consumer.getSMServices().getAppsLauncherService().getAppsLauncherStub(); + } +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java new file mode 100644 index 000000000..d053fa46c --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java @@ -0,0 +1,84 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.sm; + +import esa.mo.nmf.clitool.BaseCommand; +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import esa.mo.nmf.clitool.ExitCodes; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.softwaremanagement.packagemanagement.body.FindPackageResponse; +import org.ccsds.moims.mo.softwaremanagement.packagemanagement.consumer.PackageManagementStub; +import picocli.CommandLine; + +/** + * The AppsLauncherCommands class contains the static classes for the Apps + * Launcher service. + * + * @author Cesar Coelho + */ +public class PackageManagementCommands { + + private static final Logger LOGGER = Logger.getLogger(PackageManagementCommands.class.getName()); + + @CommandLine.Command(name = "findPackage", description = "The findPackage operation allows a consumer to find the available packages on the provider.") + public static class FindPackage extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the package to find.") + String name; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getAppsLauncherService() == null) { + System.out.println("Package Management service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + PackageManagementStub packageManagement = getPackageManagement(); + IdentifierList names = new IdentifierList(); + names.add(new Identifier(name)); + FindPackageResponse response = packageManagement.findPackage(names); + for (int i = 0; i < response.getBodyElement0().size(); i++) { + String packageName = response.getBodyElement0().get(i).getValue(); + Boolean isInstalled = response.getBodyElement1().get(i); + String installedStr = isInstalled ? " (installed)" : ""; + System.out.println("Package name: " + packageName + installedStr); + } + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during runApp!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + public static PackageManagementStub getPackageManagement() { + return consumer.getSMServices().getPackageManagementService().getPackageManagementStub(); + } +} From b1a883c2d4b188328cb79f0fbb74b901b5a6a763 Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Wed, 19 Apr 2023 14:45:55 +0200 Subject: [PATCH 170/173] Adds install, uninstall, and upgrade functionalities to the cli-tool --- .../clitool/SoftwareManagementCommands.java | 7 +- .../nmf/clitool/sm/AppsLauncherCommands.java | 1 + .../clitool/sm/PackageManagementCommands.java | 129 +++++++++++++++++- 3 files changed, 129 insertions(+), 8 deletions(-) diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java index 1dd50bdcf..3fdc5962d 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java @@ -27,6 +27,9 @@ import esa.mo.nmf.clitool.sm.AppsLauncherCommands.RunApp; import esa.mo.nmf.clitool.sm.AppsLauncherCommands.StopApp; import esa.mo.nmf.clitool.sm.PackageManagementCommands.FindPackage; +import esa.mo.nmf.clitool.sm.PackageManagementCommands.Install; +import esa.mo.nmf.clitool.sm.PackageManagementCommands.Uninstall; +import esa.mo.nmf.clitool.sm.PackageManagementCommands.Upgrade; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; @@ -49,7 +52,7 @@ public class SoftwareManagementCommands { public static Identifier heartbeatSubscription; public static Identifier outputSubscription; - @Command(name = "software-management", subcommands = {FindPackage.class}) + @Command(name = "software-management", subcommands = {FindPackage.class, Install.class, Uninstall.class, Upgrade.class}) public static class SoftwareManagement { } @@ -102,7 +105,7 @@ public void beatNotifyReceived(MALMessageHeader msgHeader, Identifier identifier } } } - + public static PackageManagementStub getPackageManagement() { return consumer.getSMServices().getPackageManagementService().getPackageManagementStub(); } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java index 82ec193ec..4660879eb 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java @@ -25,6 +25,7 @@ import static esa.mo.nmf.clitool.BaseCommand.consumer; import esa.mo.nmf.clitool.ExitCodes; import esa.mo.nmf.clitool.Helper; +import static esa.mo.nmf.clitool.SoftwareManagementCommands.outputSubscription; import java.util.List; import java.util.Map; import java.util.logging.Level; diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java index d053fa46c..cb775cb6d 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java @@ -27,15 +27,17 @@ import java.util.logging.Logger; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.structures.BooleanList; import org.ccsds.moims.mo.mal.structures.Identifier; import org.ccsds.moims.mo.mal.structures.IdentifierList; import org.ccsds.moims.mo.softwaremanagement.packagemanagement.body.FindPackageResponse; +import org.ccsds.moims.mo.softwaremanagement.packagemanagement.consumer.PackageManagementAdapter; import org.ccsds.moims.mo.softwaremanagement.packagemanagement.consumer.PackageManagementStub; import picocli.CommandLine; /** - * The AppsLauncherCommands class contains the static classes for the Apps - * Launcher service. + * The PackageManagementCommands class contains the static classes for the + * Package Management service. Launcher service. * * @author Cesar Coelho */ @@ -43,10 +45,12 @@ public class PackageManagementCommands { private static final Logger LOGGER = Logger.getLogger(PackageManagementCommands.class.getName()); - @CommandLine.Command(name = "findPackage", description = "The findPackage operation allows a consumer to find the available packages on the provider.") + @CommandLine.Command(name = "findPackage", + description = "The findPackage operation allows a consumer to find the available packages on the provider.") public static class FindPackage extends BaseCommand implements Runnable { - @CommandLine.Parameters(arity = "1", paramLabel = "", index = "0", description = "Name of the package to find.") + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "0", description = "Name of the package to find.") String name; @Override @@ -55,7 +59,7 @@ public void run() { System.exit(ExitCodes.NO_HOST); } - if (consumer.getSMServices().getAppsLauncherService() == null) { + if (consumer.getSMServices().getPackageManagementService() == null) { System.out.println("Package Management service is not available for this provider!"); System.exit(ExitCodes.UNAVAILABLE); } @@ -72,7 +76,120 @@ public void run() { System.out.println("Package name: " + packageName + installedStr); } } catch (MALInteractionException | MALException e) { - LOGGER.log(Level.SEVERE, "Error during runApp!", e); + LOGGER.log(Level.SEVERE, "Error during the execution of the findPackage operation!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + @CommandLine.Command(name = "install", + description = "The install operation allows a consumer to install the content of a package on the provider.") + public static class Install extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "0", description = "Name of the package to be installed.") + String name; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getPackageManagementService() == null) { + System.out.println("Package Management service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + PackageManagementStub packageManagement = getPackageManagement(); + IdentifierList names = new IdentifierList(); + names.add(new Identifier(name)); + FindPackageResponse response = packageManagement.findPackage(names); + for (int i = 0; i < response.getBodyElement0().size(); i++) { + String packageName = response.getBodyElement0().get(i).getValue(); + Boolean isInstalled = response.getBodyElement1().get(i); + String installedStr = isInstalled ? " (installed)" : ""; + System.out.println("Package name: " + packageName + installedStr); + } + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during the execution of the install operation!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + @CommandLine.Command(name = "uninstall", + description = "The uninstall operation allows a consumer to uninstall the content of a package on the provider.") + public static class Uninstall extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "0", description = "Name of the package to be uninstalled.") + String name; + + @CommandLine.Option(names = {"-k", "--keepConfiguration"}, paramLabel = "", + description = "It specifies if the existing configuration is to be kept.") + boolean keepConfiguration; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getPackageManagementService() == null) { + System.out.println("Package Management service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + PackageManagementStub packageManagement = getPackageManagement(); + IdentifierList names = new IdentifierList(); + names.add(new Identifier(name)); + BooleanList keepConfigurations = new BooleanList(); + keepConfigurations.add(keepConfiguration); + + packageManagement.uninstall(names, + keepConfigurations, + new PackageManagementAdapter() { + } + ); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during the execution of the uninstall operation!", e); + System.exit(ExitCodes.GENERIC_ERROR); + } + } + } + + @CommandLine.Command(name = "upgrade", + description = "The upgrade operation allows a consumer to upgrade the content of a package on the provider.") + public static class Upgrade extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "0", description = "Name of the package to be upgraded.") + String name; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + System.exit(ExitCodes.NO_HOST); + } + + if (consumer.getSMServices().getPackageManagementService() == null) { + System.out.println("Package Management service is not available for this provider!"); + System.exit(ExitCodes.UNAVAILABLE); + } + + try { + PackageManagementStub packageManagement = getPackageManagement(); + IdentifierList names = new IdentifierList(); + names.add(new Identifier(name)); + packageManagement.upgrade(names, + new PackageManagementAdapter() { + } + ); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during the execution of the upgrade operation!", e); System.exit(ExitCodes.GENERIC_ERROR); } } From dc45ee6984ada997c9122919ec323b79933cee48 Mon Sep 17 00:00:00 2001 From: "m.ciccariello" Date: Fri, 26 May 2023 15:43:58 +0200 Subject: [PATCH 171/173] [CLI] Updated software management commands --- .../main/java/esa/mo/nmf/clitool/CLITool.java | 12 ++-- .../clitool/sm/PackageManagementCommands.java | 72 +++++++++++++++++-- 2 files changed, 74 insertions(+), 10 deletions(-) diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java index 3b59a93ae..28200aca5 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java @@ -28,12 +28,12 @@ * @author marcel.mikolajko */ @Command(name = "esa.mo.nmf.clitool.CLITool", subcommands = {MCCommands.Parameter.class, MCCommands.Aggregation.class, - SoftwareManagementCommands.AppsLauncher.class, - SoftwareManagementCommands.Heartbeat.class, - PlatformCommands.GPS.class, PlatformCommands.ADCS.class, - PlatformCommands.Camera.class, ArchiveCommands.class, - LogsCommands.class}, - description = "Provides a way to use provider's services from the command line.") + SoftwareManagementCommands.AppsLauncher.class, SoftwareManagementCommands.SoftwareManagement.class, + SoftwareManagementCommands.Heartbeat.class, + PlatformCommands.GPS.class, PlatformCommands.ADCS.class, + PlatformCommands.Camera.class, ArchiveCommands.class, + LogsCommands.class}, + description = "Provides a way to use provider's services from the command line.") public class CLITool { public static final String APP_NAME = "cli-consumer"; diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java index cb775cb6d..3d46cc10f 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/PackageManagementCommands.java @@ -23,13 +23,17 @@ import esa.mo.nmf.clitool.BaseCommand; import static esa.mo.nmf.clitool.BaseCommand.consumer; import esa.mo.nmf.clitool.ExitCodes; + +import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.MALStandardError; import org.ccsds.moims.mo.mal.structures.BooleanList; import org.ccsds.moims.mo.mal.structures.Identifier; import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.transport.MALMessageHeader; import org.ccsds.moims.mo.softwaremanagement.packagemanagement.body.FindPackageResponse; import org.ccsds.moims.mo.softwaremanagement.packagemanagement.consumer.PackageManagementAdapter; import org.ccsds.moims.mo.softwaremanagement.packagemanagement.consumer.PackageManagementStub; @@ -109,8 +113,30 @@ public void run() { for (int i = 0; i < response.getBodyElement0().size(); i++) { String packageName = response.getBodyElement0().get(i).getValue(); Boolean isInstalled = response.getBodyElement1().get(i); - String installedStr = isInstalled ? " (installed)" : ""; - System.out.println("Package name: " + packageName + installedStr); + if (!isInstalled) { + packageManagement.install(names, new PackageManagementAdapter() { + @Override + public void installAckReceived(MALMessageHeader msgHeader, BooleanList integrity, Map qosProperties) { + LOGGER.log(Level.INFO, "Installing..."); + } + + @Override + public void installResponseReceived(MALMessageHeader msgHeader, Map qosProperties) { + LOGGER.log(Level.INFO, "Installed successfully"); + } + + @Override + public void installAckErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "There was an error during the install operation.", error); + } + + @Override + public void installResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "There was an error during the install operation.", error); + } + }); + System.out.println("Package name: " + packageName + " (installed)"); + } } } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Error during the execution of the install operation!", e); @@ -152,7 +178,26 @@ public void run() { packageManagement.uninstall(names, keepConfigurations, new PackageManagementAdapter() { - } + @Override + public void uninstallAckReceived(MALMessageHeader msgHeader, Map qosProperties) { + LOGGER.log(Level.INFO, "Uninstalling..."); + } + + @Override + public void uninstallResponseReceived(MALMessageHeader msgHeader, Map qosProperties) { + LOGGER.log(Level.INFO, "Uninstalled successfully"); + } + + @Override + public void uninstallAckErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "There was an error during the uninstall operation.", error); + } + + @Override + public void uninstallResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "There was an error during the uninstall operation.", error); + } + } ); } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Error during the execution of the uninstall operation!", e); @@ -186,7 +231,26 @@ public void run() { names.add(new Identifier(name)); packageManagement.upgrade(names, new PackageManagementAdapter() { - } + @Override + public void upgradeAckReceived(MALMessageHeader msgHeader, Map qosProperties) { + LOGGER.log(Level.INFO, "Upgrading..."); + } + + @Override + public void upgradeResponseReceived(MALMessageHeader msgHeader, Map qosProperties) { + LOGGER.log(Level.INFO, "Upgraded successfully"); + } + + @Override + public void upgradeAckErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "There was an error during the upgrade operation.", error); + } + + @Override + public void upgradeResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "There was an error during the upgrade operation.", error); + } + } ); } catch (MALInteractionException | MALException e) { LOGGER.log(Level.SEVERE, "Error during the execution of the upgrade operation!", e); From 2108d16aceb7b922cd3e08eeb745af3281f31afc Mon Sep 17 00:00:00 2001 From: Cesar Coelho Date: Fri, 9 Jun 2023 11:06:23 +0200 Subject: [PATCH 172/173] Refactors the cli-tool and add the Action service --- sdk/tools/cli-tool/pom.xml | 10 +- .../esa/mo/nmf/clitool/ArchiveCommands.java | 30 +- .../java/esa/mo/nmf/clitool/BaseCommand.java | 16 +- .../main/java/esa/mo/nmf/clitool/CLITool.java | 24 +- .../main/java/esa/mo/nmf/clitool/Helper.java | 2 +- .../java/esa/mo/nmf/clitool/LogsCommands.java | 74 +- .../java/esa/mo/nmf/clitool/MCCommands.java | 820 ------------------ .../adapters/ArchiveToActionsAdapter.java | 145 ++++ ...java => ArchiveToAggregationsAdapter.java} | 25 +- .../adapters/ArchiveToJsonAdapter.java | 15 +- .../adapters/ArchiveToParametersAdapter.java | 27 +- .../clitool/adapters/QueryStatusProvider.java | 5 +- .../esa/mo/nmf/clitool/mc/ActionCommands.java | 138 +++ .../nmf/clitool/mc/AggregationCommands.java | 429 +++++++++ .../esa/mo/nmf/clitool/mc/MCCommands.java | 53 ++ .../mo/nmf/clitool/mc/ParameterCommands.java | 479 ++++++++++ .../{ => platform}/PlatformCommands.java | 3 +- .../nmf/clitool/sm/AppsLauncherCommands.java | 2 +- .../{ => sm}/SoftwareManagementCommands.java | 4 +- 19 files changed, 1354 insertions(+), 947 deletions(-) delete mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/MCCommands.java create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToActionsAdapter.java rename sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/{ArchiveToAggreationsAdapter.java => ArchiveToAggregationsAdapter.java} (86%) create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ActionCommands.java create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/AggregationCommands.java create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java create mode 100644 sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java rename sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/{ => platform}/PlatformCommands.java (99%) rename sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/{ => sm}/SoftwareManagementCommands.java (97%) diff --git a/sdk/tools/cli-tool/pom.xml b/sdk/tools/cli-tool/pom.xml index c34f27e43..8764d2d59 100644 --- a/sdk/tools/cli-tool/pom.xml +++ b/sdk/tools/cli-tool/pom.xml @@ -58,13 +58,9 @@ - - int.esa.ccsds.mo - API_MAL - int.esa.nmf.core - generic-composite-model + ground-mo-adapter info.picocli @@ -86,10 +82,6 @@ sqlite-jdbc 3.32.3.2 - - int.esa.nmf.core.moservices.api - com-nmf - diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ArchiveCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ArchiveCommands.java index b0a4816ed..e11b02795 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ArchiveCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/ArchiveCommands.java @@ -29,6 +29,17 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.clitool.adapters.ArchiveToBackupAdapter; import esa.mo.nmf.clitool.adapters.ArchiveToJsonAdapter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.sql.*; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import org.ccsds.moims.mo.com.COMHelper; import org.ccsds.moims.mo.com.archive.ArchiveHelper; import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; @@ -41,20 +52,9 @@ import org.ccsds.moims.mo.mal.structures.*; import org.json.simple.JSONArray; import org.json.simple.JSONObject; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.net.MalformedURLException; -import java.sql.*; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -import picocli.CommandLine.*; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; /** * Archive commands implementations @@ -161,6 +161,7 @@ public static class DumpFormattedArchive extends BaseCommand implements Runnable " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") String endTime; + @Override public void run() { // prepare comType filter int areaNumber = 0; @@ -295,6 +296,7 @@ public static class BackupProvider extends BaseCommand implements Runnable { " - format: key1.key2.[...].keyN.\n" + " - example: esa.NMF_SDK.nanosat-mo-supervisor") String domainId; + @Override public void run() { if (!super.initRemoteConsumer()) { return; diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java index b7fe702b4..bb91b52d5 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/BaseCommand.java @@ -20,6 +20,7 @@ */ package esa.mo.nmf.clitool; +import esa.mo.nmf.clitool.sm.SoftwareManagementCommands; import esa.mo.com.impl.consumer.ArchiveConsumerServiceImpl; import esa.mo.com.impl.provider.ArchiveProviderServiceImpl; import esa.mo.helpertools.connections.SingleConnectionDetails; @@ -27,6 +28,9 @@ import esa.mo.nmf.NMFConsumer; import esa.mo.nmf.clitool.adapters.ArchiveToAppAdapter; import esa.mo.nmf.clitool.adapters.QueryStatusProvider; +import esa.mo.nmf.clitool.mc.AggregationCommands; +import esa.mo.nmf.clitool.mc.ParameterCommands; +import esa.mo.nmf.groundmoadapter.GroundMOAdapterImpl; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; @@ -80,7 +84,7 @@ public abstract class BaseCommand { description = "Name of the provider we want to connect to") public String providerName; - public static NMFConsumer consumer; + public static GroundMOAdapterImpl consumer; public static IdentifierList domain; public static ArchiveConsumerServiceImpl localArchive; @@ -176,7 +180,7 @@ public boolean initRemoteConsumer() { return false; } - consumer = new NMFConsumer(provider); + consumer = new GroundMOAdapterImpl(provider); consumer.init(); domain = provider.getProviderKey().getDomain(); @@ -246,15 +250,15 @@ public static void closeConsumer() { if (consumer != null) { IdentifierList ids = new IdentifierList(); try { - if (MCCommands.parameterSubscription != null) { + if (ParameterCommands.parameterSubscription != null) { ids.clear(); - ids.add(MCCommands.parameterSubscription); + ids.add(ParameterCommands.parameterSubscription); consumer.getMCServices().getParameterService().getParameterStub().monitorValueDeregister(ids); } - if (MCCommands.aggregationSubscription != null) { + if (AggregationCommands.aggregationSubscription != null) { ids.clear(); - ids.add(MCCommands.aggregationSubscription); + ids.add(AggregationCommands.aggregationSubscription); consumer.getMCServices().getAggregationService().getAggregationStub().monitorValueDeregister(ids); } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java index 28200aca5..8876a00bf 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java @@ -20,6 +20,10 @@ */ package esa.mo.nmf.clitool; +import esa.mo.nmf.clitool.mc.AggregationCommands; +import esa.mo.nmf.clitool.mc.MCCommands; +import esa.mo.nmf.clitool.platform.PlatformCommands; +import esa.mo.nmf.clitool.sm.SoftwareManagementCommands; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Option; @@ -27,14 +31,22 @@ /** * @author marcel.mikolajko */ -@Command(name = "esa.mo.nmf.clitool.CLITool", subcommands = {MCCommands.Parameter.class, MCCommands.Aggregation.class, - SoftwareManagementCommands.AppsLauncher.class, SoftwareManagementCommands.SoftwareManagement.class, - SoftwareManagementCommands.Heartbeat.class, - PlatformCommands.GPS.class, PlatformCommands.ADCS.class, - PlatformCommands.Camera.class, ArchiveCommands.class, - LogsCommands.class}, +@Command(name = "esa.mo.nmf.clitool.CLITool", + subcommands = { + MCCommands.Aggregation.class, + MCCommands.Parameter.class, + MCCommands.Action.class, + SoftwareManagementCommands.AppsLauncher.class, + SoftwareManagementCommands.SoftwareManagement.class, + SoftwareManagementCommands.Heartbeat.class, + PlatformCommands.GPS.class, + PlatformCommands.ADCS.class, + PlatformCommands.Camera.class, + ArchiveCommands.class, + LogsCommands.class}, description = "Provides a way to use provider's services from the command line.") public class CLITool { + public static final String APP_NAME = "cli-consumer"; @Option(names = {"-h", "--help"}, usageHelp = true, description = "display a help message") diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java index 199de2f74..c2b3b06fd 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/Helper.java @@ -148,5 +148,5 @@ public ProviderAppDetails(Long id, AppDetails appDetails) { this.id = id; } } - + } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java index 6d689b779..2fa40bb4b 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/LogsCommands.java @@ -24,6 +24,9 @@ import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.clitool.adapters.ArchiveToAppListAdapter; import esa.mo.nmf.clitool.adapters.ArchiveToLogAdapter; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; import org.ccsds.moims.mo.com.structures.ObjectId; @@ -34,12 +37,9 @@ import org.ccsds.moims.mo.softwaremanagement.SoftwareManagementHelper; import org.ccsds.moims.mo.softwaremanagement.appslauncher.AppsLauncherHelper; import org.ccsds.moims.mo.softwaremanagement.commandexecutor.CommandExecutorHelper; - -import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; - -import picocli.CommandLine.*; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; /** * Log commands implementations @@ -48,29 +48,30 @@ * @author Marcel Mikołajko */ @Command(name = "log", subcommands = {LogsCommands.ListLogs.class, LogsCommands.GetLogs.class}, - description = "Gets or lists NMF app logs using the content of a local or remote COM archive.") + description = "Gets or lists NMF app logs using the content of a local or remote COM archive.") public class LogsCommands { private static final Logger LOGGER = Logger.getLogger(LogsCommands.class.getName()); @Command(name = "list", description = "Lists NMF apps having logs in the content of a local or remote COM archive.") public static class ListLogs extends BaseCommand implements Runnable { + @Option(names = {"-d", "--domain"}, paramLabel = "", - description = "Restricts the list to NMF apps in a specific domain\n" + - " - default: search for app in all domains\n" + " - format: key1.key2.[...].keyN.\n" + - " - example: esa.NMF_SDK.nanosat-mo-supervisor") + description = "Restricts the list to NMF apps in a specific domain\n" + + " - default: search for app in all domains\n" + " - format: key1.key2.[...].keyN.\n" + + " - example: esa.NMF_SDK.nanosat-mo-supervisor") String domainId; @Option(names = {"-s", "--start"}, paramLabel = "", - description = "Restricts the list to NMF apps having logs logged after the given time\n" + - " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-04 08:37:58.482\"") + description = "Restricts the list to NMF apps having logs logged after the given time\n" + + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-04 08:37:58.482\"") String startTime; @Option(names = {"-e", "--end"}, paramLabel = "", - description = "Restricts the list to NMF apps having logs logged before the given time. " + - "If this option is provided without the -s option, returns the single " - + "object that has the closest timestamp to, but not greater than \n" + - " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") + description = "Restricts the list to NMF apps having logs logged before the given time. " + + "If this option is provided without the -s option, returns the single " + + "object that has the closest timestamp to, but not greater than \n" + + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") String endTime; @Override @@ -78,7 +79,7 @@ public void run() { // Query all objects from SoftwareManagement area filtering for // StandardOutput and StandardError events and App object is done in the query adapter ObjectType objectsTypes = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, - new UShort(0), SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION, new UShort(0)); + new UShort(0), SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION, new UShort(0)); boolean consumerCreated = false; if (providerURI != null) { @@ -97,7 +98,7 @@ public void run() { FineTime startTimeF = startTime == null ? null : HelperTime.readableString2FineTime(startTime); FineTime endTimeF = endTime == null ? null : HelperTime.readableString2FineTime(endTime); ArchiveQuery archiveQuery = new ArchiveQuery(domain, null, null, 0L, null, startTimeF, endTimeF, null, - null); + null); archiveQueryList.add(archiveQuery); // execute query @@ -118,8 +119,9 @@ public void run() { } @Command(name = "get", - description = "Dumps to a LOG file an NMF app logs using the content of a local or remote COM archive.") + description = "Dumps to a LOG file an NMF app logs using the content of a local or remote COM archive.") public static class GetLogs extends BaseCommand implements Runnable { + @Parameters(arity = "1", paramLabel = "", description = "Name of the NMF app we want the logs for") String appName; @@ -127,21 +129,21 @@ public static class GetLogs extends BaseCommand implements Runnable { String logFile; @Option(names = {"-d", "--domain"}, paramLabel = "", - description = "Domain of the NMF app we want the logs for\n" + - " - default: search for app in all domains\n" + " - format: key1.key2.[...].keyN.\n" + - " - example: esa.NMF_SDK.nanosat-mo-supervisor") + description = "Domain of the NMF app we want the logs for\n" + + " - default: search for app in all domains\n" + " - format: key1.key2.[...].keyN.\n" + + " - example: esa.NMF_SDK.nanosat-mo-supervisor") String domainId; @Option(names = {"-s", "--start"}, paramLabel = "", - description = "Restricts the dump to logs logged after the given time\n" + - " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-04 08:37:58.482\"") + description = "Restricts the dump to logs logged after the given time\n" + + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-04 08:37:58.482\"") String startTime; @Option(names = {"-e", "--end"}, paramLabel = "", - description = "Restricts the dump to logs logged before the given time. " + - "If this option is provided without the -s option, returns the single " - + "object that has the closest timestamp to, but not greater than \n" + - " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") + description = "Restricts the dump to logs logged before the given time. " + + "If this option is provided without the -s option, returns the single " + + "object that has the closest timestamp to, but not greater than \n" + + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") String endTime; @Option(names = {"-t", "--timestamped"}, paramLabel = "", @@ -153,12 +155,12 @@ public void run() { // Query all objects from SoftwareManagement area and CommandExecutor service, // filtering for StandardOutput and StandardError events is done in the query adapter ObjectType outputObjectTypes = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, - CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NUMBER, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION, new UShort(0)); + CommandExecutorHelper.COMMANDEXECUTOR_SERVICE_NUMBER, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION, new UShort(0)); ObjectType eventObjectTypes = new ObjectType(SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_NUMBER, - AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, - SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION, new UShort(0)); + AppsLauncherHelper.APPSLAUNCHER_SERVICE_NUMBER, + SoftwareManagementHelper.SOFTWAREMANAGEMENT_AREA_VERSION, new UShort(0)); boolean consumerCreated = false; if (providerURI != null) { @@ -178,10 +180,10 @@ public void run() { if (appObjectId == null) { if (databaseFile == null) { LOGGER.log(Level.SEVERE, String.format("Couldn't find App with name %s in provider at %s", appName, - providerURI)); + providerURI)); } else { LOGGER.log(Level.SEVERE, String.format("Couldn't find App with name %s in database at %s", appName, - databaseFile)); + databaseFile)); } return; } @@ -191,7 +193,7 @@ public void run() { FineTime startTimeF = startTime == null ? null : HelperTime.readableString2FineTime(startTime); FineTime endTimeF = endTime == null ? null : HelperTime.readableString2FineTime(endTime); ArchiveQuery outputArchiveQuery = new ArchiveQuery(domain, null, null, 0L, appObjectId, startTimeF, - endTimeF, null, null); + endTimeF, null, null); archiveQueryList.add(outputArchiveQuery); // execute query @@ -200,7 +202,7 @@ public void run() { archiveQueryList.clear(); ArchiveQuery eventArchiveQuery = new ArchiveQuery(domain, null, null, appObjectId.getKey().getInstId(), - null, startTimeF, endTimeF, null, null); + null, startTimeF, endTimeF, null, null); archiveQueryList.add(eventArchiveQuery); adapter.resetAdapter(); queryArchive(eventObjectTypes, archiveQueryList, adapter, adapter); diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/MCCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/MCCommands.java deleted file mode 100644 index db1c8e0ce..000000000 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/MCCommands.java +++ /dev/null @@ -1,820 +0,0 @@ -/* ---------------------------------------------------------------------------- - * Copyright (C) 2021 European Space Agency - * European Space Operations Centre - * Darmstadt - * Germany - * ---------------------------------------------------------------------------- - * System : ESA NanoSat MO Framework - * ---------------------------------------------------------------------------- - * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 - * You may not use this file except in compliance with the License. - * - * Except as expressly set forth in this License, the Software is provided to - * You on an "as is" basis and without warranties of any kind, including without - * limitation merchantability, fitness for a particular purpose, absence of - * defects or errors, accuracy or non-infringement of intellectual property rights. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * ---------------------------------------------------------------------------- - */ -package esa.mo.nmf.clitool; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import esa.mo.helpertools.helpers.HelperMisc; -import esa.mo.helpertools.helpers.HelperTime; -import esa.mo.nmf.clitool.adapters.ArchiveToAggreationsAdapter; -import esa.mo.nmf.clitool.adapters.ArchiveToParametersAdapter; -import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; -import org.ccsds.moims.mo.com.archive.consumer.ArchiveStub; -import org.ccsds.moims.mo.com.archive.structures.ArchiveDetails; -import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; -import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; -import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; -import org.ccsds.moims.mo.com.structures.InstanceBooleanPair; -import org.ccsds.moims.mo.com.structures.InstanceBooleanPairList; -import org.ccsds.moims.mo.com.structures.ObjectIdList; -import org.ccsds.moims.mo.com.structures.ObjectType; -import org.ccsds.moims.mo.mal.MALException; -import org.ccsds.moims.mo.mal.MALHelper; -import org.ccsds.moims.mo.mal.MALInteractionException; -import org.ccsds.moims.mo.mal.MALStandardError; -import org.ccsds.moims.mo.mal.structures.*; -import org.ccsds.moims.mo.mal.transport.MALMessageHeader; -import org.ccsds.moims.mo.mc.MCHelper; -import org.ccsds.moims.mo.mc.aggregation.AggregationHelper; -import org.ccsds.moims.mo.mc.aggregation.consumer.AggregationAdapter; -import org.ccsds.moims.mo.mc.aggregation.consumer.AggregationStub; -import org.ccsds.moims.mo.mc.aggregation.structures.*; -import org.ccsds.moims.mo.mc.parameter.ParameterHelper; -import org.ccsds.moims.mo.mc.parameter.consumer.ParameterAdapter; -import org.ccsds.moims.mo.mc.parameter.consumer.ParameterStub; -import org.ccsds.moims.mo.mc.parameter.structures.ParameterValueList; -import org.ccsds.moims.mo.mc.structures.ObjectInstancePair; -import org.ccsds.moims.mo.mc.structures.ObjectInstancePairList; -import picocli.CommandLine.*; - -import java.io.FileWriter; -import java.io.IOException; -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -/** - * @author marcel.mikolajko - */ -public class MCCommands { - static Logger LOGGER = Logger.getLogger(MCCommands.class.getName()); - - public static Identifier parameterSubscription; - public static Identifier aggregationSubscription; - - @Command(name = "parameter", subcommands = {MCCommands.ParameterMonitorValue.class, - MCCommands.ParameterEnableGeneration.class, - MCCommands.ParameterDisableGeneration.class, - MCCommands.GetParameters.class, MCCommands.ListParameters.class}) - public static class Parameter { - } - - @Command(name = "aggregation", subcommands = {MCCommands.AggregationMonitorValue.class, - MCCommands.AggregationEnableGeneration.class, - MCCommands.AggregationDisableGeneration.class}) - public static class Aggregation { - } - - public static void enableOrDisableParameterGeneration(ParameterStub parameterService, List parameters, - boolean enable) { - IdentifierList request = new IdentifierList(); - if (parameters == null || parameters.isEmpty()) { - request.add(new Identifier("*")); - } else { - for (String name : parameters) { - request.add(new Identifier(name)); - } - } - - try { - ObjectInstancePairList ids = parameterService.listDefinition(request); - InstanceBooleanPairList enableInstances = new InstanceBooleanPairList(); - - for (ObjectInstancePair pair : ids) { - enableInstances.add(new InstanceBooleanPair(pair.getObjIdentityInstanceId(), enable)); - } - - parameterService.enableGeneration(false, enableInstances); - System.out.println((enable ? "Enable " : "Disable ") + "successful."); - } catch (MALInteractionException e) { - MALStandardError error = e.getStandardError(); - if (error.getErrorNumber().equals(MALHelper.UNKNOWN_ERROR_NUMBER)) { - System.out.println("Provided parameters don't exist in the provider:"); - for (UInteger id : (UIntegerList) error.getExtraInformation()) { - System.out.println("- " + request.get((int) id.getValue())); - } - } else { - LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); - } - } catch (MALException e) { - LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); - } - } - - @Command(name = "enable", description = "Enables generation of specified parameters") - public static class ParameterEnableGeneration extends BaseCommand implements Runnable { - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the parameters to enable. If non are specified enable all") - List parameterNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - return; - } - - if (consumer.getMCServices().getParameterService() == null) { - System.out.println("Parameter service is not available for this provider!"); - return; - } - enableOrDisableParameterGeneration(consumer.getMCServices().getParameterService().getParameterStub(), - parameterNames, true); - } - } - - @Command(name = "disable", description = "Disables generation of specified parameters") - public static class ParameterDisableGeneration extends BaseCommand implements Runnable { - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the parameters to disable. If non are specified disable all") - List parameterNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - return; - } - - if (consumer.getMCServices().getParameterService() == null) { - System.out.println("Parameter service is not available for this provider!"); - return; - } - enableOrDisableParameterGeneration(consumer.getMCServices().getParameterService().getParameterStub(), - parameterNames, false); - } - } - - public static void enableOrDisableAggregationGeneration(AggregationStub aggregationService, - List aggregations, boolean enable) { - IdentifierList request = new IdentifierList(); - if (aggregations == null || aggregations.isEmpty()) { - request.add(new Identifier("*")); - } else { - for (String name : aggregations) { - request.add(new Identifier(name)); - } - } - - try { - ObjectInstancePairList ids = aggregationService.listDefinition(request); - InstanceBooleanPairList enableInstances = new InstanceBooleanPairList(); - - for (ObjectInstancePair pair : ids) { - enableInstances.add(new InstanceBooleanPair(pair.getObjIdentityInstanceId(), enable)); - } - - aggregationService.enableGeneration(false, enableInstances); - System.out.println((enable ? "Enable " : "Disable ") + "successful."); - } catch (MALInteractionException e) { - MALStandardError error = e.getStandardError(); - if (error.getErrorNumber().equals(MALHelper.UNKNOWN_ERROR_NUMBER)) { - System.out.println("Provided aggregations don't exist in the provider:"); - for (UInteger id : (UIntegerList) error.getExtraInformation()) { - System.out.println("- " + request.get((int) id.getValue())); - } - } else { - LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); - } - } catch (MALException e) { - LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); - } - } - - @Command(name = "enable", description = "Enables generation of specified aggregations") - public static class AggregationEnableGeneration extends BaseCommand implements Runnable { - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the aggregations to enable. If non are specified enable all") - List aggregationNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - return; - } - - if (consumer.getMCServices().getAggregationService() == null) { - System.out.println("Aggregation service is not available for this provider!"); - return; - } - enableOrDisableAggregationGeneration(consumer.getMCServices().getAggregationService().getAggregationStub(), - aggregationNames, true); - } - } - - @Command(name = "disable", description = "Disables generation of specified aggregations") - public static class AggregationDisableGeneration extends BaseCommand implements Runnable { - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the aggregations to disable. If non are specified disable all") - List aggregationNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - return; - } - - if (consumer.getMCServices().getAggregationService() == null) { - System.out.println("Aggregation service is not available for this provider!"); - return; - } - enableOrDisableAggregationGeneration(consumer.getMCServices().getAggregationService().getAggregationStub(), - aggregationNames, false); - } - } - - @Command(name = "subscribe", description = "Subscribes to specified parameters") - public static class ParameterMonitorValue extends BaseCommand implements Runnable { - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the parameters to subscribe to. If non are specified subscribe to all.\n" + - " - examples: param1 or param1 param2") - List parameterNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - return; - } - - if (consumer.getMCServices().getParameterService() == null) { - System.out.println("Parameter service is not available for this provider!"); - return; - } - - Identifier subscriptionId = new Identifier("CLI-Consumer-ParameterSubscription"); - EntityKeyList entityKeys = new EntityKeyList(); - if (parameterNames == null || parameterNames.isEmpty()) { - EntityKey entitykey = new EntityKey(new Identifier("*"), 0L, 0L, 0L); - entityKeys.add(entitykey); - } else { - for (String parameter : parameterNames) { - EntityKey entitykey = new EntityKey(new Identifier(parameter), 0L, 0L, 0L); - entityKeys.add(entitykey); - } - } - EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); - EntityRequestList entities = new EntityRequestList(); - entities.add(entity); - - ParameterStub stub = consumer.getMCServices().getParameterService().getParameterStub(); - Subscription subscription = new Subscription(subscriptionId, entities); - parameterSubscription = subscriptionId; - final Object lock = new Object(); - try { - stub.monitorValueRegister(subscription, new ParameterAdapter() { - @Override - public void monitorValueNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, - UpdateHeaderList updateHeaderList, ObjectIdList objectIdList, - ParameterValueList parameterValueList, Map qosProperties) { - String parameterName = updateHeaderList.get(0).getKey().getFirstSubKey().getValue() - .toLowerCase(); - long timestamp = updateHeaderList.get(0).getTimestamp().getValue(); - String value = parameterValueList.get(0).getRawValue().toString(); - - System.out.println("[" + timestamp + "] - " + parameterName + ": " + value); - } - - @Override - public void monitorValueRegisterErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - } catch (MALInteractionException | MALException e) { - LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", e); - } - - try { - synchronized (lock) { - lock.wait(); - } - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Interrupted exception!", e); - } - } - } - - @Command(name = "subscribe", description = "Subscribes to specified aggregations") - public static class AggregationMonitorValue extends BaseCommand implements Runnable { - @Parameters(arity = "0..*", paramLabel = "", index = "0", - description = "Names of the aggregations to subscribe to. If non are specified subscribe to all.\n" + - " - examples: aggregation1 or aggregation1 aggregation2") - List aggregationNames; - - @Override - public void run() { - if (!super.initRemoteConsumer()) { - return; - } - - if (consumer.getMCServices().getAggregationService() == null) { - System.out.println("Aggregation service is not available for this provider!"); - return; - } - - AggregationStub stub = consumer.getMCServices().getAggregationService().getAggregationStub(); - try { - IdentifierList names = new IdentifierList(); - if (aggregationNames == null || aggregationNames.isEmpty()) { - names.add(new Identifier("*")); - } else { - for (String name : aggregationNames) { - names.add(new Identifier(name)); - } - } - - ObjectInstancePairList result = stub.listDefinition(names); - - ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); - LongList aggregationDefinitionsIds = new LongList(); - LongList aggregationIdentitiesIds = new LongList(); - LongList parameterIds = new LongList(); - - for (ObjectInstancePair pair : result) { - long aggregationIdentityId = pair.getObjIdentityInstanceId(); - long aggregationDefinitionId = pair.getObjDefInstanceId(); - - aggregationIdentitiesIds.add(aggregationIdentityId); - aggregationDefinitionsIds.add(aggregationDefinitionId); - } - - final Object lock = new Object(); - - Map aggregationIdentities = new HashMap<>(); - archive.retrieve(AggregationHelper.AGGREGATIONIDENTITY_OBJECT_TYPE, domain, aggregationIdentitiesIds, - new ArchiveAdapter() { - @Override - public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, - ElementList objBodies, Map qosProperties) { - for (int i = 0; i < objDetails.size(); ++i) { - aggregationIdentities.put(objDetails.get(i).getInstId(), ((Identifier) objBodies.get(i)) - .getValue()); - } - - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void retrieveResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive retrieve!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - // System.out.println("Aggregation ids"); - // System.out.println(aggregationDefinitionsIds.stream().map(Object::toString).collect(Collectors.joining(", "))); - archive.retrieve(AggregationHelper.AGGREGATIONDEFINITION_OBJECT_TYPE, domain, aggregationDefinitionsIds, - new ArchiveAdapter() { - @Override - public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, - ElementList objBodies, Map qosProperties) { - for (int i = 0; i < objDetails.size(); ++i) { - AggregationDefinitionDetails details = (AggregationDefinitionDetails) objBodies.get(i); - if (details.getGenerationEnabled()) { - for (AggregationParameterSet set : details.getParameterSets()) { - parameterIds.addAll(set.getParameters()); - } - } else { - System.out.println("Aggregation " + aggregationIdentities.get(objDetails.get(i) - .getDetails().getRelated()) + " is disabled!"); - } - - if (!details.getSendDefinitions()) { - System.out.println("sendDefinitions is set to false for aggregation: " + - aggregationIdentities.get(objDetails.get(i).getDetails().getRelated()) + ". " + - "Parameter names will not be available."); - } - - } - - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void retrieveResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive retrieve!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - if (parameterIds.isEmpty()) { - return; - } - - // System.out.println("Parameter ids"); - // System.out.println(parameterIds.stream().map(Object::toString).collect(Collectors.joining(", "))); - Map identityIdToName = new HashMap<>(); - archive.retrieve(ParameterHelper.PARAMETERIDENTITY_OBJECT_TYPE, domain, parameterIds, - new ArchiveAdapter() { - @Override - public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, - ElementList objBodies, Map qosProperties) { - for (int i = 0; i < objDetails.size(); ++i) { - identityIdToName.put(objDetails.get(i).getInstId(), ((Identifier) objBodies.get(i)) - .getValue()); - } - - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void retrieveResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive retrieve!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - ArchiveQueryList queries = new ArchiveQueryList(); - for (Long id : parameterIds) { - queries.add(new ArchiveQuery(domain, null, null, id, null, null, null, null, null)); - } - Map definitionIdToIdentity = new HashMap<>(); - - archive.query(false, ParameterHelper.PARAMETERDEFINITION_OBJECT_TYPE, queries, null, - new ArchiveAdapter() { - @Override - public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, - IdentifierList domain, ArchiveDetailsList objDetails, ElementList objBodies, - Map qosProperties) { - for (ArchiveDetails details : objDetails) { - definitionIdToIdentity.put(details.getInstId(), identityIdToName.get(details - .getDetails().getRelated())); - } - } - - @Override - public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, - IdentifierList domain, ArchiveDetailsList objDetails, ElementList objBodies, - Map qosProperties) { - for (ArchiveDetails details : objDetails) { - definitionIdToIdentity.put(details.getInstId(), identityIdToName.get(details - .getDetails().getRelated())); - } - - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive query!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - - @Override - public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during archive query!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - Identifier subscriptionId = new Identifier("CLI-Consumer-AggregationSubscription"); - EntityKeyList entityKeys = new EntityKeyList(); - if (aggregationNames == null || aggregationNames.isEmpty()) { - EntityKey entitykey = new EntityKey(new Identifier("*"), 0L, 0L, 0L); - entityKeys.add(entitykey); - } else { - for (String aggregation : aggregationNames) { - EntityKey entitykey = new EntityKey(new Identifier(aggregation), 0L, 0L, 0L); - entityKeys.add(entitykey); - } - } - EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); - EntityRequestList entities = new EntityRequestList(); - entities.add(entity); - Subscription subscription = new Subscription(subscriptionId, entities); - aggregationSubscription = subscriptionId; - stub.monitorValueRegister(subscription, new AggregationAdapter() { - @Override - public void monitorValueNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, - UpdateHeaderList updateHeaderList, ObjectIdList objectIdList, - AggregationValueList aggregationValueList, Map qosProperties) { - String aggregationName = updateHeaderList.get(0).getKey().getFirstSubKey().getValue() - .toLowerCase(); - long timestamp = updateHeaderList.get(0).getTimestamp().getValue(); - AggregationParameterValueList values = aggregationValueList.get(0).getParameterSetValues().get( - 0).getValues(); - System.out.println("[" + timestamp + "] - " + aggregationName + ": "); - int index = 1; - for (AggregationParameterValue value : values) { - String name = definitionIdToIdentity.get(value.getParamDefInstId()); - System.out.println(" " + (name == null ? "parameter " + index : name) + ": " + value - .getValue().getRawValue().toString()); - index += 1; - } - System.out.println(); - } - - @Override - public void monitorValueRegisterErrorReceived(MALMessageHeader msgHeader, MALStandardError error, - Map qosProperties) { - LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", error); - synchronized (lock) { - lock.notifyAll(); - } - } - }); - - synchronized (lock) { - lock.wait(); - } - - } catch (MALInteractionException | MALException | InterruptedException e) { - LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", e); - } - } - } - - @Command(name = "get", description = "Dumps to a file MO parameters samples from COM archive.") - public static class GetParameters extends BaseCommand implements Runnable { - @Parameters(arity = "1", paramLabel = "", index = "0", - description = "Target file for the parameters samples") - String file; - - @Parameters(arity = "0..*", paramLabel = "", index = "1", - description = "Names of the parameters to retrieve\n" + " - examples: param1 or param1 param2") - List parameterNames; - - @Option(names = {"-d", "--domain"}, paramLabel = "", - description = "Restricts the dump to parameters in a specific domain\n" + - " - format: key1.key2.[...].keyN.\n" + " - example: esa.NMF_SDK.nanosat-mo-supervisor") - String domainId; - - @Option(names = {"-s", "--start"}, paramLabel = "", - description = "Restricts the dump to parameters generated after the given time\n" + - " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-04 08:37:58.482\"") - String startTime; - - @Option(names = {"-e", "--end"}, paramLabel = "", - description = "Restricts the dump to parameters generated before the given time. " + - "If this option is provided without the -s option, returns the single object that has the closest timestamp to, but not greater than \n" + - " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") - String endTime; - - @Option(names = {"-j", "--json"}, paramLabel = "", - description = "If specified output will be in JSON format") - boolean json; - - @Override - public void run() { - boolean consumerCreated = false; - if (providerURI != null) { - consumerCreated = initRemoteConsumer(); - } else if (databaseFile != null) { - consumerCreated = initLocalConsumer(databaseFile); - } - - if (!consumerCreated) { - LOGGER.log(Level.SEVERE, "Failed to create consumer!"); - return; - } - // prepare domain, time and object id filters - ArchiveQueryList archiveQueryList = new ArchiveQueryList(); - FineTime startTimeF = startTime == null ? null : HelperTime.readableString2FineTime(startTime); - FineTime endTimeF = endTime == null ? null : HelperTime.readableString2FineTime(endTime); - IdentifierList domain = domainId == null ? null : HelperMisc.domainId2domain(domainId); - - ArchiveQuery archiveQuery = new ArchiveQuery(domain, null, null, 0L, null, startTimeF, endTimeF, null, - null); - archiveQueryList.add(archiveQuery); - - ArchiveToParametersAdapter parametersAdapter = new ArchiveToParametersAdapter(); - ObjectType parameterObjectType = new ObjectType(MCHelper.MC_AREA_NUMBER, - ParameterHelper.PARAMETER_SERVICE_NUMBER, MCHelper.MC_AREA_VERSION, new UShort(0)); - queryArchive(parameterObjectType, archiveQueryList, parametersAdapter, parametersAdapter); - - ArchiveToAggreationsAdapter aggregationsAdapter = new ArchiveToAggreationsAdapter(); - ObjectType aggregationObjectType = new ObjectType(MCHelper.MC_AREA_NUMBER, - AggregationHelper.AGGREGATION_SERVICE_NUMBER, MCHelper.MC_AREA_VERSION, new UShort(0)); - queryArchive(aggregationObjectType, archiveQueryList, aggregationsAdapter, aggregationsAdapter); - - Map>> allParameters = parametersAdapter - .getParameterValues(); - - // Display list of aggregations - Map>> aggregationValuesMap = aggregationsAdapter - .getAggregationValues(); - if (aggregationValuesMap != null) { - //Make the parameter map - for (IdentifierList domainKey : aggregationValuesMap.keySet()) { - for (Map.Entry> entry : aggregationValuesMap.get(domainKey) - .entrySet()) { - Long definitionId = entry.getKey(); - AggregationDefinitionDetails definition = aggregationsAdapter.getAggregationDefinitions().get( - domainKey).get(definitionId); - - for (TimestampedAggregationValue aggregationValue : entry.getValue()) { - for (int i = 0; - i < aggregationValue.getAggregationValue().getParameterSetValues().size(); - i++) { - AggregationSetValue values = aggregationValue.getAggregationValue() - .getParameterSetValues().get(i); - AggregationParameterSet definitions = definition.getParameterSets().get(i); - - int valueSetNumber = 0; - double deltaTime = values.getDeltaTime() != null ? values.getDeltaTime().getValue() : 0; - double intervalTime = values.getIntervalTime() != null ? values.getIntervalTime() - .getValue() : 0; - long valueSetTimestamp = aggregationValue.getTimestamp().getValue() + - (long) (deltaTime * 1000L); - - for (int n = 0; n < values.getValues().size(); n++) { - // Check if we are starting a new set of values compared to the given definition list - if (n % definitions.getParameters().size() == 0) { - valueSetNumber++; - } - - AggregationParameterValue value = values.getValues().get(n); - Long parameterId = definitions.getParameters().get(n % definitions.getParameters() - .size()); - - TimestampedParameterValue paramValue = new TimestampedParameterValue(value - .getValue(), new FineTime(valueSetTimestamp + (long) (valueSetNumber * - intervalTime * 1000L))); - - Identifier parameterName = parametersAdapter.getIdentitiesMap().get(domainKey).get( - parameterId); - if (allParameters.get(domainKey).containsKey(parameterName)) { - allParameters.get(domainKey).get(parameterName).add(paramValue); - } else { - List list = new ArrayList<>(); - list.add(paramValue); - allParameters.get(domainKey).put(parameterName, list); - } - } - } - } - } - } - } - - try { - if (!allParameters.isEmpty()) { - if (json && !file.endsWith(".json")) { - file = file + ".json"; - } - - FileWriter writer = new FileWriter(file); - - Map>> parameters = new HashMap<>(); - if (parameterNames != null && !parameterNames.isEmpty()) { - for (String name : parameterNames) { - for (IdentifierList domainKey : allParameters.keySet()) { - List values = allParameters.get(domainKey).get( - new Identifier(name)); - if (values == null) { - continue; - } - values.sort(Comparator.comparingLong(TimestampedParameterValue::getTimestamp)); - if (!parameters.containsKey(domainKey)) { - parameters.put(domainKey, new HashMap<>()); - } - parameters.get(domainKey).put(new Identifier(name), values); - } - } - } else { - parameters = allParameters; - for (IdentifierList domainKey : parameters.keySet()) { - for (Map.Entry> entry : parameters.get( - domainKey).entrySet()) { - entry.getValue().sort(Comparator.comparingLong( - TimestampedParameterValue::getTimestamp)); - } - } - } - - if (json) { - Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); - gson.toJson(parameters, writer); - } else { - for (IdentifierList domainKey : parameters.keySet()) { - writer.write("Domain: " + HelperMisc.domain2domainId(domainKey) + "\n"); - List keys = parameters.get(domainKey).keySet().stream().map(Identifier::getValue) - .sorted().collect(Collectors.toList()); - for (String parameter : keys) { - for (TimestampedParameterValue value : parameters.get(domainKey).get(new Identifier( - parameter))) { - String line = parameter + "\t" + value.getTimestamp() + "\t" + value - .getParameterValue() + "\n"; - writer.write(line); - } - } - } - } - writer.close(); - System.out.println("\nParameters successfully dumped to file: " + file + "\n"); - } else { - System.out.println("\nNo parameters found\n"); - } - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Error when writing to file", e); - } - } - } - - @Command(name = "list", description = "Lists available parameters in a COM archive.") - public static class ListParameters extends BaseCommand implements Runnable { - @Option(names = {"-d", "--domain"}, paramLabel = "", - description = "Restricts the dump to objects in a specific domain\n" + - " - format: key1.key2.[...].keyN.\n" + " - example: esa.NMF_SDK.nanosat-mo-supervisor") - String domainId; - - public void run() { - boolean consumerCreated = false; - if (providerURI != null) { - consumerCreated = initRemoteConsumer(); - } else if (databaseFile != null) { - consumerCreated = initLocalConsumer(databaseFile); - } - - if (!consumerCreated) { - LOGGER.log(Level.SEVERE, "Failed to create consumer!"); - return; - } - IdentifierList domain = domainId == null ? null : HelperMisc.domainId2domain(domainId); - - ArchiveQueryList archiveQueryList = new ArchiveQueryList(); - ArchiveQuery archiveQuery = new ArchiveQuery(domain, null, null, 0L, null, null, null, null, null); - archiveQueryList.add(archiveQuery); - - ArchiveToParametersAdapter adapter = new ArchiveToParametersAdapter(); - queryArchive(ParameterHelper.PARAMETERIDENTITY_OBJECT_TYPE, archiveQueryList, adapter, adapter); - - // Display list of NMF apps that have parameters - Map> parameters = adapter.getParameterIdentities(); - if (parameters.size() <= 0) { - System.out.println("\nNo parameter found in the provided archive: " + (databaseFile == null ? - providerURI : databaseFile)); - } else { - System.out.println("\nFound the following parameters: "); - for (Map.Entry> entry : parameters.entrySet()) { - System.out.println("Domain: " + entry.getKey()); - for (Identifier parameter : entry.getValue()) { - System.out.println(" - " + parameter); - } - } - System.out.println(); - } - } - } - -} -//------------------------------------------------------------------------------ \ No newline at end of file diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToActionsAdapter.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToActionsAdapter.java new file mode 100644 index 000000000..c22bca84f --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToActionsAdapter.java @@ -0,0 +1,145 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.adapters; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.Map; +import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; +import org.ccsds.moims.mo.com.archive.structures.ArchiveDetails; +import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; +import org.ccsds.moims.mo.com.structures.ObjectType; +import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.mal.structures.ElementList; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.transport.MALMessageHeader; +import org.ccsds.moims.mo.mc.action.ActionHelper; + +/** + * Archive adapter that retrieves available action names and their values. + * + * @author marcel.mikolajko + */ +public class ArchiveToActionsAdapter extends ArchiveAdapter implements QueryStatusProvider { + + private static final Logger LOGGER = Logger.getLogger(ArchiveToActionsAdapter.class.getName()); + + /** + * True if the query is over (response or any error received) + */ + private boolean isQueryOver = false; + + private final ObjectType actionIdentityType = ActionHelper.ACTIONIDENTITY_OBJECT_TYPE; + private final ObjectType actionDefinitionType = ActionHelper.ACTIONDEFINITION_OBJECT_TYPE; + + private final Map> actionIdentities = new HashMap<>(); + private final Map> identitiesMap = new HashMap<>(); + private final Map> definitionsMap = new HashMap<>(); + + @Override + public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + if (objDetails == null) { + setIsQueryOver(true); + return; + } + processObjects(objType, objDetails, objBodies, domain); + setIsQueryOver(true); + } + + @Override + public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + processObjects(objType, objDetails, objBodies, domain); + } + + /** + * Fills the maps based on the type of the object + * + * @param type Type of the objects to be processed + * @param detailsList Archive details of the objects + * @param bodiesList Bodies of the objects + */ + private void processObjects(ObjectType type, ArchiveDetailsList detailsList, + ElementList bodiesList, IdentifierList domain) { + if (!actionIdentities.containsKey(domain)) { + actionIdentities.put(domain, new ArrayList<>()); + } + + if (!identitiesMap.containsKey(domain)) { + identitiesMap.put(domain, new HashMap<>()); + } + + if (!definitionsMap.containsKey(domain)) { + definitionsMap.put(domain, new HashMap<>()); + } + + if (type == null || type.equals(actionIdentityType)) { + for (int i = 0; i < detailsList.size(); ++i) { + identitiesMap.get(domain).put(detailsList.get(i).getInstId(), (Identifier) bodiesList.get(i)); + actionIdentities.get(domain).add((Identifier) bodiesList.get(i)); + } + } else if (type.equals(actionDefinitionType)) { + for (ArchiveDetails archiveDetails : detailsList) { + definitionsMap.get(domain).put(archiveDetails.getInstId(), archiveDetails.getDetails().getRelated()); + } + } + } + + @Override + public void queryAckErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "queryAckErrorReceived", error); + setIsQueryOver(true); + } + + @Override + public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "queryUpdateErrorReceived", error); + setIsQueryOver(true); + } + + @Override + public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, Map qosProperties) { + LOGGER.log(Level.SEVERE, "queryResponseErrorReceived", error); + setIsQueryOver(true); + } + + @Override + public boolean isQueryOver() { + return isQueryOver; + } + + private synchronized void setIsQueryOver(boolean isQueryOver) { + this.isQueryOver = isQueryOver; + } + + public Map> getActionIdentities() { + return actionIdentities; + } + + public Map> getIdentitiesMap() { + return identitiesMap; + } +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToAggreationsAdapter.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToAggregationsAdapter.java similarity index 86% rename from sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToAggreationsAdapter.java rename to sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToAggregationsAdapter.java index 11ff5cc11..3a9e1e631 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToAggreationsAdapter.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToAggregationsAdapter.java @@ -19,23 +19,16 @@ import java.util.logging.Level; import java.util.logging.Logger; -public class ArchiveToAggreationsAdapter extends ArchiveAdapter implements QueryStatusProvider { +public class ArchiveToAggregationsAdapter extends ArchiveAdapter implements QueryStatusProvider { - private static final Logger LOGGER = Logger.getLogger(ArchiveToAggreationsAdapter.class.getName()); + private static final Logger LOGGER = Logger.getLogger(ArchiveToAggregationsAdapter.class.getName()); /** * True if the query is over (response or any error received) */ private boolean isQueryOver = false; - /** - * Map from Aggregation Definition Details ID to Aggregation values - */ private final Map>> aggregationValues = new HashMap<>(); - - /** - * Map from Aggregation Definition ID to AggregationDefinition - */ private final Map> aggregationDefinitions = new HashMap<>(); public Map>> getAggregationValues() { @@ -57,13 +50,13 @@ private synchronized void setIsQueryOver(boolean isQueryOver) { @Override public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { processObjects(objType, objDetails, objBodies, domain); } @Override public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, IdentifierList domain, - ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { + ArchiveDetailsList objDetails, ElementList objBodies, Map qosProperties) { if (objDetails == null) { setIsQueryOver(true); return; @@ -76,12 +69,12 @@ public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType /** * Fills the maps based on the type of the object * - * @param type Type of the objects to be processed + * @param type Type of the objects to be processed * @param detailsList Archive details of the objects - * @param bodiesList Bodies of the objects + * @param bodiesList Bodies of the objects */ private void processObjects(ObjectType type, ArchiveDetailsList detailsList, ElementList bodiesList, - IdentifierList domain) { + IdentifierList domain) { if (detailsList == null) { return; } @@ -100,7 +93,7 @@ private void processObjects(ObjectType type, ArchiveDetailsList detailsList, Ele Long definitionId = detailsList.get(i).getDetails().getRelated(); if (aggregationValues.get(domain).containsKey(definitionId)) { aggregationValues.get(domain).get(definitionId).add(new TimestampedAggregationValue(value, - detailsList.get(i).getTimestamp())); + detailsList.get(i).getTimestamp())); } else { List list = new ArrayList<>(); list.add(new TimestampedAggregationValue(value, detailsList.get(i).getTimestamp())); @@ -110,7 +103,7 @@ private void processObjects(ObjectType type, ArchiveDetailsList detailsList, Ele } else if (AggregationHelper.AGGREGATIONDEFINITION_OBJECT_TYPE.equals(type)) { for (int i = 0; i < detailsList.size(); ++i) { aggregationDefinitions.get(domain).put(detailsList.get(i).getInstId(), - (AggregationDefinitionDetails) bodiesList.get(i)); + (AggregationDefinitionDetails) bodiesList.get(i)); } } } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToJsonAdapter.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToJsonAdapter.java index 6b29d9a2c..2233c6c13 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToJsonAdapter.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToJsonAdapter.java @@ -27,6 +27,13 @@ import esa.mo.com.impl.util.HelperCOM; import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.helpers.HelperTime; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; import org.ccsds.moims.mo.com.archive.structures.ArchiveDetails; import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; @@ -38,14 +45,6 @@ import org.ccsds.moims.mo.mal.structures.IdentifierList; import org.ccsds.moims.mo.mal.transport.MALMessageHeader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Archive adapter that dumps to a JSON file every COM object received from an archive query. * diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToParametersAdapter.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToParametersAdapter.java index b014faf18..edc73ca76 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToParametersAdapter.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/ArchiveToParametersAdapter.java @@ -54,34 +54,12 @@ public class ArchiveToParametersAdapter extends ArchiveAdapter implements QueryS */ private boolean isQueryOver = false; - /** - * MC.Parameter.ParameterIdentity object type - */ private final ObjectType parameterIdentityType = ParameterHelper.PARAMETERIDENTITY_OBJECT_TYPE; - - /** - * MC.Parameter.ParameterDefinition object type - */ private final ObjectType parameterDefinitionType = ParameterHelper.PARAMETERDEFINITION_OBJECT_TYPE; - - /** - * MC.Parameter.ParameterValueInstance object type - */ private final ObjectType parameterValueType = ParameterHelper.PARAMETERVALUEINSTANCE_OBJECT_TYPE; - /** - * Available parameters names segregated based on the domain - */ private final Map> parameterIdentities = new HashMap<>(); - - /** - * Map from ParameterIdentity ID to it's name segregated based on the domain - */ private final Map> identitiesMap = new HashMap<>(); - - /** - * Map from ParameterDefinition ID to it's related ParameterIdentity ID segregated based on the domain - */ private final Map> definitionsMap = new HashMap<>(); /** @@ -131,9 +109,8 @@ public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, * @param detailsList Archive details of the objects * @param bodiesList Bodies of the objects */ - private void processObjects(ObjectType type, ArchiveDetailsList detailsList, ElementList bodiesList, - IdentifierList domain) { - + private void processObjects(ObjectType type, ArchiveDetailsList detailsList, + ElementList bodiesList, IdentifierList domain) { if (!parameterIdentities.containsKey(domain)) { parameterIdentities.put(domain, new ArrayList<>()); } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/QueryStatusProvider.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/QueryStatusProvider.java index c81e31069..e90dd6c08 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/QueryStatusProvider.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/adapters/QueryStatusProvider.java @@ -18,7 +18,6 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ - package esa.mo.nmf.clitool.adapters; /** @@ -29,8 +28,8 @@ public interface QueryStatusProvider { /** - * @return true if the query is finished ((response or any error message received), false - * otherwise. + * @return true if the query is finished ((response or any error message + * received), false otherwise. */ boolean isQueryOver(); diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ActionCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ActionCommands.java new file mode 100644 index 000000000..512b9986f --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ActionCommands.java @@ -0,0 +1,138 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.mc; + +import esa.mo.helpertools.helpers.HelperMisc; +import esa.mo.nmf.clitool.BaseCommand; +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import static esa.mo.nmf.clitool.BaseCommand.queryArchive; +import esa.mo.nmf.clitool.adapters.ArchiveToActionsAdapter; +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mc.action.ActionHelper; +import picocli.CommandLine; + +/** + * + * @author Cesar Coelho + */ +public class ActionCommands { + + private static final Logger LOGGER = Logger.getLogger(ActionCommands.class.getName()); + + @CommandLine.Command(name = "trigger", description = "Triggers a specific action.") + public static class SubmitAction extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "0", description = "Name of the action to trigger.") + String actionName; + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "1", + description = "List of the arguments to use by the action.") + List inputArguments; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getActionService() == null) { + System.out.println("Action service is not available for this provider!"); + return; + } + + Serializable[] objs = new Serializable[0]; + + if (inputArguments != null) { + objs = new Serializable[inputArguments.size()]; + + for (int i = 0; i < inputArguments.size(); i++) { + String inputValue = inputArguments.get(i); + + try { + Long longValue = Long.valueOf(inputValue); + objs[i] = longValue; + } catch (NumberFormatException ex) { + objs[i] = inputArguments.get(i); + } + } + } + + consumer.launchAction(actionName, objs); + } + } + + @CommandLine.Command(name = "list", description = "Lists available actions in a COM archive.") + public static class ListActions extends BaseCommand implements Runnable { + + @CommandLine.Option(names = {"-d", "--domain"}, paramLabel = "", + description = "Restricts the dump to objects in a specific domain\n" + + " - format: key1.key2.[...].keyN.\n" + " - example: esa.NMF_SDK.nanosat-mo-supervisor") + String domainId; + + public void run() { + boolean consumerCreated = false; + if (providerURI != null) { + consumerCreated = initRemoteConsumer(); + } else if (databaseFile != null) { + consumerCreated = initLocalConsumer(databaseFile); + } + + if (!consumerCreated) { + LOGGER.log(Level.SEVERE, "Failed to create consumer!"); + return; + } + IdentifierList domain = domainId == null ? null : HelperMisc.domainId2domain(domainId); + + ArchiveQueryList archiveQueryList = new ArchiveQueryList(); + ArchiveQuery archiveQuery = new ArchiveQuery(domain, null, null, 0L, null, null, null, null, null); + archiveQueryList.add(archiveQuery); + + ArchiveToActionsAdapter adapter = new ArchiveToActionsAdapter(); + queryArchive(ActionHelper.ACTIONIDENTITY_OBJECT_TYPE, archiveQueryList, adapter, adapter); + + // Display list of NMF apps that have actions + Map> actions = adapter.getActionIdentities(); + if (actions.size() <= 0) { + System.out.println("\nNo action found in the provided archive: " + (databaseFile == null + ? providerURI : databaseFile)); + } else { + System.out.println("\nFound the following actions: "); + for (Map.Entry> entry : actions.entrySet()) { + System.out.println("Domain: " + entry.getKey()); + for (Identifier action : entry.getValue()) { + System.out.println(" - " + action); + } + } + System.out.println(); + } + } + } + +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/AggregationCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/AggregationCommands.java new file mode 100644 index 000000000..b3c0ee0e8 --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/AggregationCommands.java @@ -0,0 +1,429 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.mc; + +import esa.mo.nmf.clitool.BaseCommand; +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.ccsds.moims.mo.com.archive.consumer.ArchiveAdapter; +import org.ccsds.moims.mo.com.archive.consumer.ArchiveStub; +import org.ccsds.moims.mo.com.archive.structures.ArchiveDetails; +import org.ccsds.moims.mo.com.archive.structures.ArchiveDetailsList; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; +import org.ccsds.moims.mo.com.structures.InstanceBooleanPair; +import org.ccsds.moims.mo.com.structures.InstanceBooleanPairList; +import org.ccsds.moims.mo.com.structures.ObjectIdList; +import org.ccsds.moims.mo.com.structures.ObjectType; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALHelper; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.mal.structures.ElementList; +import org.ccsds.moims.mo.mal.structures.EntityKey; +import org.ccsds.moims.mo.mal.structures.EntityKeyList; +import org.ccsds.moims.mo.mal.structures.EntityRequest; +import org.ccsds.moims.mo.mal.structures.EntityRequestList; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.LongList; +import org.ccsds.moims.mo.mal.structures.Subscription; +import org.ccsds.moims.mo.mal.structures.UInteger; +import org.ccsds.moims.mo.mal.structures.UIntegerList; +import org.ccsds.moims.mo.mal.structures.UpdateHeaderList; +import org.ccsds.moims.mo.mal.transport.MALMessageHeader; +import org.ccsds.moims.mo.mc.aggregation.AggregationHelper; +import org.ccsds.moims.mo.mc.aggregation.consumer.AggregationAdapter; +import org.ccsds.moims.mo.mc.aggregation.consumer.AggregationStub; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationDefinitionDetails; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationParameterSet; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationParameterValue; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationParameterValueList; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationValueList; +import org.ccsds.moims.mo.mc.parameter.ParameterHelper; +import org.ccsds.moims.mo.mc.structures.ObjectInstancePair; +import org.ccsds.moims.mo.mc.structures.ObjectInstancePairList; +import picocli.CommandLine; + +/** + * + * @author Cesar Coelho + */ +public class AggregationCommands { + + private static final Logger LOGGER = Logger.getLogger(AggregationCommands.class.getName()); + public static Identifier aggregationSubscription; + + public static void enableOrDisableAggregationGeneration(AggregationStub aggregationService, + List aggregations, boolean enable) { + IdentifierList request = new IdentifierList(); + if (aggregations == null || aggregations.isEmpty()) { + request.add(new Identifier("*")); + } else { + for (String name : aggregations) { + request.add(new Identifier(name)); + } + } + + try { + ObjectInstancePairList ids = aggregationService.listDefinition(request); + InstanceBooleanPairList enableInstances = new InstanceBooleanPairList(); + + for (ObjectInstancePair pair : ids) { + enableInstances.add(new InstanceBooleanPair(pair.getObjIdentityInstanceId(), enable)); + } + + aggregationService.enableGeneration(false, enableInstances); + System.out.println((enable ? "Enable " : "Disable ") + "successful."); + } catch (MALInteractionException e) { + MALStandardError error = e.getStandardError(); + if (error.getErrorNumber().equals(MALHelper.UNKNOWN_ERROR_NUMBER)) { + System.out.println("Provided aggregations don't exist in the provider:"); + for (UInteger id : (UIntegerList) error.getExtraInformation()) { + System.out.println("- " + request.get((int) id.getValue())); + } + } else { + LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); + } + } catch (MALException e) { + LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); + } + } + + @CommandLine.Command(name = "enable", description = "Enables generation of specified aggregations") + public static class AggregationEnableGeneration extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the aggregations to enable. If non are specified enable all") + List aggregationNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getAggregationService() == null) { + System.out.println("Aggregation service is not available for this provider!"); + return; + } + enableOrDisableAggregationGeneration(consumer.getMCServices().getAggregationService().getAggregationStub(), + aggregationNames, true); + } + } + + @CommandLine.Command(name = "disable", description = "Disables generation of specified aggregations") + public static class AggregationDisableGeneration extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the aggregations to disable. If non are specified disable all") + List aggregationNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getAggregationService() == null) { + System.out.println("Aggregation service is not available for this provider!"); + return; + } + enableOrDisableAggregationGeneration(consumer.getMCServices().getAggregationService().getAggregationStub(), + aggregationNames, false); + } + } + + @CommandLine.Command(name = "subscribe", description = "Subscribes to specified aggregations") + public static class AggregationMonitorValue extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the aggregations to subscribe to. If non are specified subscribe to all.\n" + + " - examples: aggregation1 or aggregation1 aggregation2") + List aggregationNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getAggregationService() == null) { + System.out.println("Aggregation service is not available for this provider!"); + return; + } + + AggregationStub stub = consumer.getMCServices().getAggregationService().getAggregationStub(); + try { + IdentifierList names = new IdentifierList(); + if (aggregationNames == null || aggregationNames.isEmpty()) { + names.add(new Identifier("*")); + } else { + for (String name : aggregationNames) { + names.add(new Identifier(name)); + } + } + + ObjectInstancePairList result = stub.listDefinition(names); + + ArchiveStub archive = consumer.getCOMServices().getArchiveService().getArchiveStub(); + LongList aggregationDefinitionsIds = new LongList(); + LongList aggregationIdentitiesIds = new LongList(); + LongList parameterIds = new LongList(); + + for (ObjectInstancePair pair : result) { + long aggregationIdentityId = pair.getObjIdentityInstanceId(); + long aggregationDefinitionId = pair.getObjDefInstanceId(); + + aggregationIdentitiesIds.add(aggregationIdentityId); + aggregationDefinitionsIds.add(aggregationDefinitionId); + } + + final Object lock = new Object(); + + Map aggregationIdentities = new HashMap<>(); + archive.retrieve(AggregationHelper.AGGREGATIONIDENTITY_OBJECT_TYPE, domain, aggregationIdentitiesIds, + new ArchiveAdapter() { + @Override + public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, + ElementList objBodies, Map qosProperties) { + for (int i = 0; i < objDetails.size(); ++i) { + aggregationIdentities.put(objDetails.get(i).getInstId(), ((Identifier) objBodies.get(i)) + .getValue()); + } + + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void retrieveResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive retrieve!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + // System.out.println("Aggregation ids"); + // System.out.println(aggregationDefinitionsIds.stream().map(Object::toString).collect(Collectors.joining(", "))); + archive.retrieve(AggregationHelper.AGGREGATIONDEFINITION_OBJECT_TYPE, domain, aggregationDefinitionsIds, + new ArchiveAdapter() { + @Override + public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, + ElementList objBodies, Map qosProperties) { + for (int i = 0; i < objDetails.size(); ++i) { + AggregationDefinitionDetails details = (AggregationDefinitionDetails) objBodies.get(i); + if (details.getGenerationEnabled()) { + for (AggregationParameterSet set : details.getParameterSets()) { + parameterIds.addAll(set.getParameters()); + } + } else { + System.out.println("Aggregation " + aggregationIdentities.get(objDetails.get(i) + .getDetails().getRelated()) + " is disabled!"); + } + + if (!details.getSendDefinitions()) { + System.out.println("sendDefinitions is set to false for aggregation: " + + aggregationIdentities.get(objDetails.get(i).getDetails().getRelated()) + ". " + + "Parameter names will not be available."); + } + + } + + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void retrieveResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive retrieve!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + if (parameterIds.isEmpty()) { + return; + } + + // System.out.println("Parameter ids"); + // System.out.println(parameterIds.stream().map(Object::toString).collect(Collectors.joining(", "))); + Map identityIdToName = new HashMap<>(); + archive.retrieve(ParameterHelper.PARAMETERIDENTITY_OBJECT_TYPE, domain, parameterIds, + new ArchiveAdapter() { + @Override + public void retrieveResponseReceived(MALMessageHeader msgHeader, ArchiveDetailsList objDetails, + ElementList objBodies, Map qosProperties) { + for (int i = 0; i < objDetails.size(); ++i) { + identityIdToName.put(objDetails.get(i).getInstId(), ((Identifier) objBodies.get(i)) + .getValue()); + } + + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void retrieveResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive retrieve!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + ArchiveQueryList queries = new ArchiveQueryList(); + for (Long id : parameterIds) { + queries.add(new ArchiveQuery(domain, null, null, id, null, null, null, null, null)); + } + Map definitionIdToIdentity = new HashMap<>(); + + archive.query(false, ParameterHelper.PARAMETERDEFINITION_OBJECT_TYPE, queries, null, + new ArchiveAdapter() { + @Override + public void queryUpdateReceived(MALMessageHeader msgHeader, ObjectType objType, + IdentifierList domain, ArchiveDetailsList objDetails, ElementList objBodies, + Map qosProperties) { + for (ArchiveDetails details : objDetails) { + definitionIdToIdentity.put(details.getInstId(), identityIdToName.get(details + .getDetails().getRelated())); + } + } + + @Override + public void queryResponseReceived(MALMessageHeader msgHeader, ObjectType objType, + IdentifierList domain, ArchiveDetailsList objDetails, ElementList objBodies, + Map qosProperties) { + for (ArchiveDetails details : objDetails) { + definitionIdToIdentity.put(details.getInstId(), identityIdToName.get(details + .getDetails().getRelated())); + } + + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void queryUpdateErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive query!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + + @Override + public void queryResponseErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during archive query!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + Identifier subscriptionId = new Identifier("CLI-Consumer-AggregationSubscription"); + EntityKeyList entityKeys = new EntityKeyList(); + if (aggregationNames == null || aggregationNames.isEmpty()) { + EntityKey entitykey = new EntityKey(new Identifier("*"), 0L, 0L, 0L); + entityKeys.add(entitykey); + } else { + for (String aggregation : aggregationNames) { + EntityKey entitykey = new EntityKey(new Identifier(aggregation), 0L, 0L, 0L); + entityKeys.add(entitykey); + } + } + EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); + EntityRequestList entities = new EntityRequestList(); + entities.add(entity); + Subscription subscription = new Subscription(subscriptionId, entities); + aggregationSubscription = subscriptionId; + stub.monitorValueRegister(subscription, new AggregationAdapter() { + @Override + public void monitorValueNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, + UpdateHeaderList updateHeaderList, ObjectIdList objectIdList, + AggregationValueList aggregationValueList, Map qosProperties) { + String aggregationName = updateHeaderList.get(0).getKey().getFirstSubKey().getValue() + .toLowerCase(); + long timestamp = updateHeaderList.get(0).getTimestamp().getValue(); + AggregationParameterValueList values = aggregationValueList.get(0).getParameterSetValues().get( + 0).getValues(); + System.out.println("[" + timestamp + "] - " + aggregationName + ": "); + int index = 1; + for (AggregationParameterValue value : values) { + String name = definitionIdToIdentity.get(value.getParamDefInstId()); + System.out.println(" " + (name == null ? "parameter " + index : name) + ": " + value + .getValue().getRawValue().toString()); + index += 1; + } + System.out.println(); + } + + @Override + public void monitorValueRegisterErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + + synchronized (lock) { + lock.wait(); + } + + } catch (MALInteractionException | MALException | InterruptedException e) { + LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", e); + } + } + } + +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java new file mode 100644 index 000000000..96488479f --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java @@ -0,0 +1,53 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2021 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.mc; + +import picocli.CommandLine; + +/** + * @author marcel.mikolajko + */ +public class MCCommands { + + @CommandLine.Command(name = "aggregation", subcommands = { + AggregationCommands.AggregationMonitorValue.class, + AggregationCommands.AggregationEnableGeneration.class, + AggregationCommands.AggregationDisableGeneration.class + }) + public static class Aggregation { + } + + @CommandLine.Command(name = "parameter", subcommands = { + ParameterCommands.ParameterMonitorValue.class, + ParameterCommands.ParameterEnableGeneration.class, + ParameterCommands.ParameterDisableGeneration.class, + ParameterCommands.GetParameters.class, + ParameterCommands.ListParameters.class + }) + public static class Parameter { + } + + @CommandLine.Command(name = "action", subcommands = { + ActionCommands.SubmitAction.class, + ActionCommands.ListActions.class,}) + public static class Action { + } +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java new file mode 100644 index 000000000..9d5cfab29 --- /dev/null +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java @@ -0,0 +1,479 @@ +/* ---------------------------------------------------------------------------- + * Copyright (C) 2023 European Space Agency + * European Space Operations Centre + * Darmstadt + * Germany + * ---------------------------------------------------------------------------- + * System : ESA NanoSat MO Framework + * ---------------------------------------------------------------------------- + * Licensed under European Space Agency Public License (ESA-PL) Weak Copyleft – v2.4 + * You may not use this file except in compliance with the License. + * + * Except as expressly set forth in this License, the Software is provided to + * You on an "as is" basis and without warranties of any kind, including without + * limitation merchantability, fitness for a particular purpose, absence of + * defects or errors, accuracy or non-infringement of intellectual property rights. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * ---------------------------------------------------------------------------- + */ +package esa.mo.nmf.clitool.mc; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import esa.mo.helpertools.helpers.HelperMisc; +import esa.mo.helpertools.helpers.HelperTime; +import esa.mo.nmf.clitool.BaseCommand; +import static esa.mo.nmf.clitool.BaseCommand.consumer; +import static esa.mo.nmf.clitool.BaseCommand.queryArchive; +import esa.mo.nmf.clitool.TimestampedAggregationValue; +import esa.mo.nmf.clitool.TimestampedParameterValue; +import esa.mo.nmf.clitool.adapters.ArchiveToAggregationsAdapter; +import esa.mo.nmf.clitool.adapters.ArchiveToParametersAdapter; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQuery; +import org.ccsds.moims.mo.com.archive.structures.ArchiveQueryList; +import org.ccsds.moims.mo.com.structures.InstanceBooleanPair; +import org.ccsds.moims.mo.com.structures.InstanceBooleanPairList; +import org.ccsds.moims.mo.com.structures.ObjectIdList; +import org.ccsds.moims.mo.com.structures.ObjectType; +import org.ccsds.moims.mo.mal.MALException; +import org.ccsds.moims.mo.mal.MALHelper; +import org.ccsds.moims.mo.mal.MALInteractionException; +import org.ccsds.moims.mo.mal.MALStandardError; +import org.ccsds.moims.mo.mal.structures.EntityKey; +import org.ccsds.moims.mo.mal.structures.EntityKeyList; +import org.ccsds.moims.mo.mal.structures.EntityRequest; +import org.ccsds.moims.mo.mal.structures.EntityRequestList; +import org.ccsds.moims.mo.mal.structures.FineTime; +import org.ccsds.moims.mo.mal.structures.Identifier; +import org.ccsds.moims.mo.mal.structures.IdentifierList; +import org.ccsds.moims.mo.mal.structures.Subscription; +import org.ccsds.moims.mo.mal.structures.UInteger; +import org.ccsds.moims.mo.mal.structures.UIntegerList; +import org.ccsds.moims.mo.mal.structures.UShort; +import org.ccsds.moims.mo.mal.structures.UpdateHeaderList; +import org.ccsds.moims.mo.mal.transport.MALMessageHeader; +import org.ccsds.moims.mo.mc.MCHelper; +import org.ccsds.moims.mo.mc.aggregation.AggregationHelper; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationDefinitionDetails; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationParameterSet; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationParameterValue; +import org.ccsds.moims.mo.mc.aggregation.structures.AggregationSetValue; +import org.ccsds.moims.mo.mc.parameter.ParameterHelper; +import org.ccsds.moims.mo.mc.parameter.consumer.ParameterAdapter; +import org.ccsds.moims.mo.mc.parameter.consumer.ParameterStub; +import org.ccsds.moims.mo.mc.parameter.structures.ParameterValueList; +import org.ccsds.moims.mo.mc.structures.ObjectInstancePair; +import org.ccsds.moims.mo.mc.structures.ObjectInstancePairList; +import picocli.CommandLine; + +/** + * + * @author Cesar Coelho + */ +public class ParameterCommands { + + private static final Logger LOGGER = Logger.getLogger(ParameterCommands.class.getName()); + public static Identifier parameterSubscription; + + @CommandLine.Command(name = "subscribe", description = "Subscribes to specified parameters") + public static class ParameterMonitorValue extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the parameters to subscribe to. If non are specified subscribe to all.\n" + + " - examples: param1 or param1 param2") + List parameterNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getParameterService() == null) { + System.out.println("Parameter service is not available for this provider!"); + return; + } + + Identifier subscriptionId = new Identifier("CLI-Consumer-ParameterSubscription"); + EntityKeyList entityKeys = new EntityKeyList(); + if (parameterNames == null || parameterNames.isEmpty()) { + EntityKey entitykey = new EntityKey(new Identifier("*"), 0L, 0L, 0L); + entityKeys.add(entitykey); + } else { + for (String parameter : parameterNames) { + EntityKey entitykey = new EntityKey(new Identifier(parameter), 0L, 0L, 0L); + entityKeys.add(entitykey); + } + } + EntityRequest entity = new EntityRequest(null, false, false, false, false, entityKeys); + EntityRequestList entities = new EntityRequestList(); + entities.add(entity); + + ParameterStub stub = consumer.getMCServices().getParameterService().getParameterStub(); + Subscription subscription = new Subscription(subscriptionId, entities); + parameterSubscription = subscriptionId; + final Object lock = new Object(); + try { + stub.monitorValueRegister(subscription, new ParameterAdapter() { + @Override + public void monitorValueNotifyReceived(MALMessageHeader msgHeader, Identifier identifier, + UpdateHeaderList updateHeaderList, ObjectIdList objectIdList, + ParameterValueList parameterValueList, Map qosProperties) { + String parameterName = updateHeaderList.get(0).getKey().getFirstSubKey().getValue() + .toLowerCase(); + long timestamp = updateHeaderList.get(0).getTimestamp().getValue(); + String value = parameterValueList.get(0).getRawValue().toString(); + + System.out.println("[" + timestamp + "] - " + parameterName + ": " + value); + } + + @Override + public void monitorValueRegisterErrorReceived(MALMessageHeader msgHeader, MALStandardError error, + Map qosProperties) { + LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", error); + synchronized (lock) { + lock.notifyAll(); + } + } + }); + } catch (MALInteractionException | MALException e) { + LOGGER.log(Level.SEVERE, "Error during monitorValueRegister!", e); + } + + try { + synchronized (lock) { + lock.wait(); + } + } catch (InterruptedException e) { + LOGGER.log(Level.SEVERE, "Interrupted exception!", e); + } + } + } + + @CommandLine.Command(name = "enable", description = "Enables generation of specified parameters") + public static class ParameterEnableGeneration extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the parameters to enable. If non are specified enable all") + List parameterNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getParameterService() == null) { + System.out.println("Parameter service is not available for this provider!"); + return; + } + enableOrDisableParameterGeneration(consumer.getMCServices().getParameterService().getParameterStub(), + parameterNames, true); + } + } + + @CommandLine.Command(name = "disable", description = "Disables generation of specified parameters") + public static class ParameterDisableGeneration extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "0", + description = "Names of the parameters to disable. If non are specified disable all") + List parameterNames; + + @Override + public void run() { + if (!super.initRemoteConsumer()) { + return; + } + + if (consumer.getMCServices().getParameterService() == null) { + System.out.println("Parameter service is not available for this provider!"); + return; + } + enableOrDisableParameterGeneration(consumer.getMCServices().getParameterService().getParameterStub(), + parameterNames, false); + } + } + + @CommandLine.Command(name = "get", description = "Dumps to a file MO parameters samples from COM archive.") + public static class GetParameters extends BaseCommand implements Runnable { + + @CommandLine.Parameters(arity = "1", paramLabel = "", index = "0", + description = "Target file for the parameters samples") + String file; + + @CommandLine.Parameters(arity = "0..*", paramLabel = "", index = "1", + description = "Names of the parameters to retrieve\n" + " - examples: param1 or param1 param2") + List parameterNames; + + @CommandLine.Option(names = {"-d", "--domain"}, paramLabel = "", + description = "Restricts the dump to parameters in a specific domain\n" + + " - format: key1.key2.[...].keyN.\n" + " - example: esa.NMF_SDK.nanosat-mo-supervisor") + String domainId; + + @CommandLine.Option(names = {"-s", "--start"}, paramLabel = "", + description = "Restricts the dump to parameters generated after the given time\n" + + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-04 08:37:58.482\"") + String startTime; + + @CommandLine.Option(names = {"-e", "--end"}, paramLabel = "", + description = "Restricts the dump to parameters generated before the given time. " + + "If this option is provided without the -s option, returns the single object that has the closest timestamp to, but not greater than \n" + + " - format: \"yyyy-MM-dd HH:mm:ss.SSS\"\n" + " - example: \"2021-03-05 12:05:45.271\"") + String endTime; + + @CommandLine.Option(names = {"-j", "--json"}, paramLabel = "", + description = "If specified output will be in JSON format") + boolean json; + + @Override + public void run() { + boolean consumerCreated = false; + if (providerURI != null) { + consumerCreated = initRemoteConsumer(); + } else if (databaseFile != null) { + consumerCreated = initLocalConsumer(databaseFile); + } + + if (!consumerCreated) { + LOGGER.log(Level.SEVERE, "Failed to create consumer!"); + return; + } + // prepare domain, time and object id filters + ArchiveQueryList archiveQueryList = new ArchiveQueryList(); + FineTime startTimeF = startTime == null ? null : HelperTime.readableString2FineTime(startTime); + FineTime endTimeF = endTime == null ? null : HelperTime.readableString2FineTime(endTime); + IdentifierList domain = domainId == null ? null : HelperMisc.domainId2domain(domainId); + + ArchiveQuery archiveQuery = new ArchiveQuery(domain, null, null, 0L, null, startTimeF, endTimeF, null, + null); + archiveQueryList.add(archiveQuery); + + ArchiveToParametersAdapter parametersAdapter = new ArchiveToParametersAdapter(); + ObjectType parameterObjectType = new ObjectType(MCHelper.MC_AREA_NUMBER, + ParameterHelper.PARAMETER_SERVICE_NUMBER, MCHelper.MC_AREA_VERSION, new UShort(0)); + queryArchive(parameterObjectType, archiveQueryList, parametersAdapter, parametersAdapter); + + ArchiveToAggregationsAdapter aggregationsAdapter = new ArchiveToAggregationsAdapter(); + ObjectType aggregationObjectType = new ObjectType(MCHelper.MC_AREA_NUMBER, + AggregationHelper.AGGREGATION_SERVICE_NUMBER, MCHelper.MC_AREA_VERSION, new UShort(0)); + queryArchive(aggregationObjectType, archiveQueryList, aggregationsAdapter, aggregationsAdapter); + + Map>> allParameters = parametersAdapter + .getParameterValues(); + + // Display list of aggregations + Map>> aggregationValuesMap = aggregationsAdapter + .getAggregationValues(); + if (aggregationValuesMap != null) { + //Make the parameter map + for (IdentifierList domainKey : aggregationValuesMap.keySet()) { + for (Map.Entry> entry : aggregationValuesMap.get(domainKey) + .entrySet()) { + Long definitionId = entry.getKey(); + AggregationDefinitionDetails definition = aggregationsAdapter.getAggregationDefinitions().get( + domainKey).get(definitionId); + + for (TimestampedAggregationValue aggregationValue : entry.getValue()) { + for (int i = 0; + i < aggregationValue.getAggregationValue().getParameterSetValues().size(); + i++) { + AggregationSetValue values = aggregationValue.getAggregationValue() + .getParameterSetValues().get(i); + AggregationParameterSet definitions = definition.getParameterSets().get(i); + + int valueSetNumber = 0; + double deltaTime = values.getDeltaTime() != null ? values.getDeltaTime().getValue() : 0; + double intervalTime = values.getIntervalTime() != null ? values.getIntervalTime() + .getValue() : 0; + long valueSetTimestamp = aggregationValue.getTimestamp().getValue() + + (long) (deltaTime * 1000L); + + for (int n = 0; n < values.getValues().size(); n++) { + // Check if we are starting a new set of values compared to the given definition list + if (n % definitions.getParameters().size() == 0) { + valueSetNumber++; + } + + AggregationParameterValue value = values.getValues().get(n); + Long parameterId = definitions.getParameters().get(n % definitions.getParameters() + .size()); + + TimestampedParameterValue paramValue = new TimestampedParameterValue(value + .getValue(), new FineTime(valueSetTimestamp + (long) (valueSetNumber + * intervalTime * 1000L))); + + Identifier parameterName = parametersAdapter.getIdentitiesMap().get(domainKey).get( + parameterId); + if (allParameters.get(domainKey).containsKey(parameterName)) { + allParameters.get(domainKey).get(parameterName).add(paramValue); + } else { + List list = new ArrayList<>(); + list.add(paramValue); + allParameters.get(domainKey).put(parameterName, list); + } + } + } + } + } + } + } + + try { + if (!allParameters.isEmpty()) { + if (json && !file.endsWith(".json")) { + file = file + ".json"; + } + + FileWriter writer = new FileWriter(file); + + Map>> parameters = new HashMap<>(); + if (parameterNames != null && !parameterNames.isEmpty()) { + for (String name : parameterNames) { + for (IdentifierList domainKey : allParameters.keySet()) { + List values = allParameters.get(domainKey).get( + new Identifier(name)); + if (values == null) { + continue; + } + values.sort(Comparator.comparingLong(TimestampedParameterValue::getTimestamp)); + if (!parameters.containsKey(domainKey)) { + parameters.put(domainKey, new HashMap<>()); + } + parameters.get(domainKey).put(new Identifier(name), values); + } + } + } else { + parameters = allParameters; + for (IdentifierList domainKey : parameters.keySet()) { + for (Map.Entry> entry : parameters.get( + domainKey).entrySet()) { + entry.getValue().sort(Comparator.comparingLong( + TimestampedParameterValue::getTimestamp)); + } + } + } + + if (json) { + Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + gson.toJson(parameters, writer); + } else { + for (IdentifierList domainKey : parameters.keySet()) { + writer.write("Domain: " + HelperMisc.domain2domainId(domainKey) + "\n"); + List keys = parameters.get(domainKey).keySet().stream().map(Identifier::getValue) + .sorted().collect(Collectors.toList()); + for (String parameter : keys) { + for (TimestampedParameterValue value : parameters.get(domainKey).get(new Identifier( + parameter))) { + String line = parameter + "\t" + value.getTimestamp() + "\t" + value + .getParameterValue() + "\n"; + writer.write(line); + } + } + } + } + writer.close(); + System.out.println("\nParameters successfully dumped to file: " + file + "\n"); + } else { + System.out.println("\nNo parameters found\n"); + } + } catch (IOException e) { + LOGGER.log(Level.SEVERE, "Error when writing to file", e); + } + } + } + + @CommandLine.Command(name = "list", description = "Lists available parameters in a COM archive.") + public static class ListParameters extends BaseCommand implements Runnable { + + @CommandLine.Option(names = {"-d", "--domain"}, paramLabel = "", + description = "Restricts the dump to objects in a specific domain\n" + + " - format: key1.key2.[...].keyN.\n" + " - example: esa.NMF_SDK.nanosat-mo-supervisor") + String domainId; + + public void run() { + boolean consumerCreated = false; + if (providerURI != null) { + consumerCreated = initRemoteConsumer(); + } else if (databaseFile != null) { + consumerCreated = initLocalConsumer(databaseFile); + } + + if (!consumerCreated) { + LOGGER.log(Level.SEVERE, "Failed to create consumer!"); + return; + } + IdentifierList domain = domainId == null ? null : HelperMisc.domainId2domain(domainId); + + ArchiveQueryList archiveQueryList = new ArchiveQueryList(); + ArchiveQuery archiveQuery = new ArchiveQuery(domain, null, null, 0L, null, null, null, null, null); + archiveQueryList.add(archiveQuery); + + ArchiveToParametersAdapter adapter = new ArchiveToParametersAdapter(); + queryArchive(ParameterHelper.PARAMETERIDENTITY_OBJECT_TYPE, archiveQueryList, adapter, adapter); + + // Display list of NMF apps that have parameters + Map> parameters = adapter.getParameterIdentities(); + if (parameters.size() <= 0) { + System.out.println("\nNo parameter found in the provided archive: " + (databaseFile == null + ? providerURI : databaseFile)); + } else { + System.out.println("\nFound the following parameters: "); + for (Map.Entry> entry : parameters.entrySet()) { + System.out.println("Domain: " + entry.getKey()); + for (Identifier parameter : entry.getValue()) { + System.out.println(" - " + parameter); + } + } + System.out.println(); + } + } + } + + public static void enableOrDisableParameterGeneration(ParameterStub parameterService, List parameters, + boolean enable) { + IdentifierList request = new IdentifierList(); + if (parameters == null || parameters.isEmpty()) { + request.add(new Identifier("*")); + } else { + for (String name : parameters) { + request.add(new Identifier(name)); + } + } + + try { + ObjectInstancePairList ids = parameterService.listDefinition(request); + InstanceBooleanPairList enableInstances = new InstanceBooleanPairList(); + + for (ObjectInstancePair pair : ids) { + enableInstances.add(new InstanceBooleanPair(pair.getObjIdentityInstanceId(), enable)); + } + + parameterService.enableGeneration(false, enableInstances); + System.out.println((enable ? "Enable " : "Disable ") + "successful."); + } catch (MALInteractionException e) { + MALStandardError error = e.getStandardError(); + if (error.getErrorNumber().equals(MALHelper.UNKNOWN_ERROR_NUMBER)) { + System.out.println("Provided parameters don't exist in the provider:"); + for (UInteger id : (UIntegerList) error.getExtraInformation()) { + System.out.println("- " + request.get((int) id.getValue())); + } + } else { + LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); + } + } catch (MALException e) { + LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); + } + } +} diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/platform/PlatformCommands.java similarity index 99% rename from sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java rename to sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/platform/PlatformCommands.java index 13c2ea8ab..af6fefd07 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/PlatformCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/platform/PlatformCommands.java @@ -18,8 +18,9 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.clitool; +package esa.mo.nmf.clitool.platform; +import esa.mo.nmf.clitool.BaseCommand; import org.ccsds.moims.mo.com.COMHelper; import org.ccsds.moims.mo.mal.MALException; import org.ccsds.moims.mo.mal.MALInteractionException; diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java index 4660879eb..8572bbeed 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/AppsLauncherCommands.java @@ -25,7 +25,7 @@ import static esa.mo.nmf.clitool.BaseCommand.consumer; import esa.mo.nmf.clitool.ExitCodes; import esa.mo.nmf.clitool.Helper; -import static esa.mo.nmf.clitool.SoftwareManagementCommands.outputSubscription; +import static esa.mo.nmf.clitool.sm.SoftwareManagementCommands.outputSubscription; import java.util.List; import java.util.Map; import java.util.logging.Level; diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/SoftwareManagementCommands.java similarity index 97% rename from sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java rename to sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/SoftwareManagementCommands.java index 3fdc5962d..cb7b0d6b9 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/SoftwareManagementCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/sm/SoftwareManagementCommands.java @@ -18,9 +18,11 @@ * limitations under the License. * ---------------------------------------------------------------------------- */ -package esa.mo.nmf.clitool; +package esa.mo.nmf.clitool.sm; import esa.mo.helpertools.connections.ConnectionConsumer; +import esa.mo.nmf.clitool.BaseCommand; +import esa.mo.nmf.clitool.ExitCodes; import static esa.mo.nmf.clitool.BaseCommand.consumer; import esa.mo.nmf.clitool.sm.AppsLauncherCommands.KillApp; import esa.mo.nmf.clitool.sm.AppsLauncherCommands.MonitorExecution; From 0aca9b9357874c924e5c99dec574246c58379970 Mon Sep 17 00:00:00 2001 From: "m.ciccariello" Date: Tue, 12 Mar 2024 12:42:00 +0100 Subject: [PATCH 173/173] [CLI] Updated software management commands, added command to set application parameter --- .../main/java/esa/mo/nmf/clitool/CLITool.java | 5 +- .../esa/mo/nmf/clitool/mc/MCCommands.java | 3 +- .../mo/nmf/clitool/mc/ParameterCommands.java | 82 +++++++++++++++---- 3 files changed, 72 insertions(+), 18 deletions(-) diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java index 8876a00bf..8b0866b6f 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/CLITool.java @@ -20,7 +20,6 @@ */ package esa.mo.nmf.clitool; -import esa.mo.nmf.clitool.mc.AggregationCommands; import esa.mo.nmf.clitool.mc.MCCommands; import esa.mo.nmf.clitool.platform.PlatformCommands; import esa.mo.nmf.clitool.sm.SoftwareManagementCommands; @@ -35,8 +34,8 @@ subcommands = { MCCommands.Aggregation.class, MCCommands.Parameter.class, - MCCommands.Action.class, - SoftwareManagementCommands.AppsLauncher.class, + MCCommands.Action.class, + SoftwareManagementCommands.AppsLauncher.class, SoftwareManagementCommands.SoftwareManagement.class, SoftwareManagementCommands.Heartbeat.class, PlatformCommands.GPS.class, diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java index 96488479f..3418156be 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/MCCommands.java @@ -40,7 +40,8 @@ public static class Aggregation { ParameterCommands.ParameterEnableGeneration.class, ParameterCommands.ParameterDisableGeneration.class, ParameterCommands.GetParameters.class, - ParameterCommands.ListParameters.class + ParameterCommands.ListParameters.class, + ParameterCommands.SetParameter.class }) public static class Parameter { } diff --git a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java index 9d5cfab29..7131e77fb 100644 --- a/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java +++ b/sdk/tools/cli-tool/src/main/java/esa/mo/nmf/clitool/mc/ParameterCommands.java @@ -25,8 +25,6 @@ import esa.mo.helpertools.helpers.HelperMisc; import esa.mo.helpertools.helpers.HelperTime; import esa.mo.nmf.clitool.BaseCommand; -import static esa.mo.nmf.clitool.BaseCommand.consumer; -import static esa.mo.nmf.clitool.BaseCommand.queryArchive; import esa.mo.nmf.clitool.TimestampedAggregationValue; import esa.mo.nmf.clitool.TimestampedParameterValue; import esa.mo.nmf.clitool.adapters.ArchiveToAggregationsAdapter; @@ -51,18 +49,7 @@ import org.ccsds.moims.mo.mal.MALHelper; import org.ccsds.moims.mo.mal.MALInteractionException; import org.ccsds.moims.mo.mal.MALStandardError; -import org.ccsds.moims.mo.mal.structures.EntityKey; -import org.ccsds.moims.mo.mal.structures.EntityKeyList; -import org.ccsds.moims.mo.mal.structures.EntityRequest; -import org.ccsds.moims.mo.mal.structures.EntityRequestList; -import org.ccsds.moims.mo.mal.structures.FineTime; -import org.ccsds.moims.mo.mal.structures.Identifier; -import org.ccsds.moims.mo.mal.structures.IdentifierList; -import org.ccsds.moims.mo.mal.structures.Subscription; -import org.ccsds.moims.mo.mal.structures.UInteger; -import org.ccsds.moims.mo.mal.structures.UIntegerList; -import org.ccsds.moims.mo.mal.structures.UShort; -import org.ccsds.moims.mo.mal.structures.UpdateHeaderList; +import org.ccsds.moims.mo.mal.structures.*; import org.ccsds.moims.mo.mal.transport.MALMessageHeader; import org.ccsds.moims.mo.mc.MCHelper; import org.ccsds.moims.mo.mc.aggregation.AggregationHelper; @@ -476,4 +463,71 @@ public static void enableOrDisableParameterGeneration(ParameterStub parameterSer LOGGER.log(Level.SEVERE, "Error during enableGeneration!", e); } } + + @CommandLine.Command(name = "set", description = "Set a parameter value") + public static class SetParameter extends BaseCommand implements Runnable { + + enum ParameterType { Integer, String, Long, Float, Double, Boolean } + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "0", description = "Name of parameter to update") + String parameterName; + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "1", description = "Type of parameter, choose from: ${COMPLETION-CANDIDATES} ") + ParameterType parameterType; + + @CommandLine.Parameters(arity = "1", paramLabel = "", + index = "2", description = "Value of parameter to update, for boolean types write true/false") + String parameterValue; + + @Override + public void run() { + if(!super.initRemoteConsumer()){ + return; + } + + if(consumer.getMCServices().getParameterService() == null){ + System.out.println("Parameter service not available for this provider"); + return; + } + + try { + Union parameter = convertParameter(parameterType, parameterValue); + if( parameter != null) { + consumer.setParameter(parameterName, parameter); + } else { + System.out.println("The parameter could not be converted to the correct type and set"); + } + } catch (Exception e) { + System.out.println("There was an unexpected error"); + System.out.println(e.getMessage()); + } + } + + private Union convertParameter(ParameterType type, String parameterValue){ + try{ + if(type.equals(ParameterType.Integer)){ + return new Union(Integer.parseInt(parameterValue)); + } + if(type.equals(ParameterType.Long)){ + return new Union(Long.parseLong(parameterValue)); + } + if(type.equals(ParameterType.Double)){ + return new Union(Double.parseDouble(parameterValue)); + } + if(type.equals(ParameterType.Float)){ + return new Union(Float.parseFloat(parameterValue)); + } + } catch (NumberFormatException e) { + System.out.println("Number format is wrong!"); + return null; + } + if(type.equals(ParameterType.Boolean)){ + return new Union(Boolean.parseBoolean(parameterValue)); + } + return new Union(parameterValue); + } + } + }