diff --git a/codebase/build.properties b/codebase/build.properties index 1854a2b0..5699c932 100644 --- a/codebase/build.properties +++ b/codebase/build.properties @@ -23,7 +23,7 @@ build.longname = Open LVC Disco build.shortname = disco build.version = 1.2.0 -build.number = 7 +build.number = 8 ################################# # Java Development Kit Settings # diff --git a/codebase/src/java/disco/org/openlvc/disco/configuration/RprConfiguration.java b/codebase/src/java/disco/org/openlvc/disco/configuration/RprConfiguration.java index 97fdc9f0..8d852081 100644 --- a/codebase/src/java/disco/org/openlvc/disco/configuration/RprConfiguration.java +++ b/codebase/src/java/disco/org/openlvc/disco/configuration/RprConfiguration.java @@ -193,6 +193,8 @@ public void setRtiProvider( RtiProvider provider ) loadDefaultModules(); // re-add extension modules + // Doing this last means that extension modules don't + // respect overrides, which is intentional. registerExtensionModules( this.extensionModules.toArray(new String[0]) ); } } @@ -455,7 +457,7 @@ public File getFomOverridePath() ///////////////////////////////////////////////////////////////////////////////////////// /** * Get the list of all registered FOM modules. This is the union of the set of default - * modules plus any added through {@link #registerExtensionModules(File...)}. + * modules plus any added through {@link #registerExtensionModules}. *
* If you have a custom FOM Mapper, remember to make sure any required FOM Module is also * getting loaded. diff --git a/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprConnection.java b/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprConnection.java index 0edebd58..d02ad19e 100644 --- a/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprConnection.java +++ b/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprConnection.java @@ -26,6 +26,7 @@ import java.util.Random; import java.util.stream.Stream; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.openlvc.disco.DiscoException; import org.openlvc.disco.OpsCenter; @@ -60,7 +61,6 @@ import hla.rti1516e.ParameterHandleValueMap; import hla.rti1516e.RTIambassador; import hla.rti1516e.ResignAction; -import hla.rti1516e.RtiFactoryFactory; import hla.rti1516e.exceptions.FederateAlreadyExecutionMember; import hla.rti1516e.exceptions.FederateNameAlreadyInUse; import hla.rti1516e.exceptions.FederationExecutionAlreadyExists; @@ -355,7 +355,7 @@ private void initializeFederation() try { logger.debug( "Connecting to RTI" ); - this.rtiamb = RtiFactoryFactory.getRtiFactory().getRtiAmbassador(); + this.rtiamb = RprRtiFactoryFactory.getRtiFactory().getRtiAmbassador(); this.fedamb = new FederateAmbassador( this ); this.rtiamb.connect( this.fedamb, CallbackModel.HLA_IMMEDIATE, @@ -475,6 +475,7 @@ private void cleanupFederation() try { // Resign from the federation + logger.info( "Resigning from HLA federation" ); this.rtiamb.resignFederationExecution( ResignAction.DELETE_OBJECTS_THEN_DIVEST ); } catch( RTIexception rtie ) @@ -482,24 +483,31 @@ private void cleanupFederation() logger.warn( "Error while resigning from HLA federation: "+rtie.getMessage() ); } - // Delete the federation, to be a good citizen. Will get told off if people are - // still using it, so expect that. - try - { - this.rtiamb.destroyFederationExecution( rprConfiguration.getFederationName() ); - } - catch( RTIexception rtie ) + // Delete the federation, to be a good citizen (unless we're + // using the MAK RTI, which prefers to clean it up automatically + // after we disconnect). + // Will get told off if people are still using it, so expect that. + if( rprConfiguration.getRtiProvider() != RtiProvider.Mak ) { - // no-op - } - catch( Exception e ) - { - e.printStackTrace(); + try + { + logger.info( "Destroying federation execution" ); + this.rtiamb.destroyFederationExecution( rprConfiguration.getFederationName() ); + } + catch( RTIexception rtie ) + { + logger.catching( Level.WARN, rtie ); + } + catch( Exception e ) + { + logger.catching( e ); + } } // Disconnect from the RTI and then we are allll cleaned up try { + logger.info( "Disconnecting from RTI" ); this.rtiamb.disconnect(); this.rtiambConnected = false; } @@ -507,6 +515,8 @@ private void cleanupFederation() { throw new DiscoException( "Error disconnecting from RTI: "+rtie.getMessage(), rtie ); } + + logger.info( "Successfully disconnected from RTI" ); } diff --git a/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprRtiFactoryFactory.java b/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprRtiFactoryFactory.java new file mode 100644 index 00000000..b53a8ee4 --- /dev/null +++ b/codebase/src/java/disco/org/openlvc/disco/connection/rpr/RprRtiFactoryFactory.java @@ -0,0 +1,117 @@ +/* + * Copyright 2015 Open LVC Project. + * + * This file is part of Open LVC Disco. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openlvc.disco.connection.rpr; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.Set; + +import hla.rti1516e.RtiFactory; +import hla.rti1516e.exceptions.RTIinternalError; + +/** + * A custom implementation of {@link hla.rti1516e.RtiFactoryFactory} that ensures that the same + * classloader is used for all attempts to {@link hla.rti1516e.RtiFactory}. + *
+ * Note: the first invocation of a method from this class MUST occur on the same thread
+ * as the prior invocation of {@link org.openlvc.disco.utils.ClassLoaderUtils#extendClasspath}.
+ */
+public class RprRtiFactoryFactory
+{
+ //----------------------------------------------------------
+ // STATIC VARIABLES
+ //----------------------------------------------------------
+ private static ClassLoader classLoader;
+
+ //----------------------------------------------------------
+ // INSTANCE VARIABLES
+ //----------------------------------------------------------
+
+ //----------------------------------------------------------
+ // CONSTRUCTORS
+ //----------------------------------------------------------
+ public RprRtiFactoryFactory() {}
+
+ //----------------------------------------------------------
+ // INSTANCE METHODS
+ //----------------------------------------------------------
+
+ //==========================================================================================
+ //----------------------------- Accessor and Mutator Methods -------------------------------
+ //==========================================================================================
+
+ //----------------------------------------------------------
+ // STATIC METHODS
+ //----------------------------------------------------------
+
+ public static RtiFactory getRtiFactory( String name ) throws RTIinternalError
+ {
+ for( RtiFactory rtiFactory : ServiceLoader.load(RtiFactory.class, getClassLoader()) )
+ {
+ if( rtiFactory.rtiName().equals(name) )
+ {
+ return rtiFactory;
+ }
+ }
+
+ throw new RTIinternalError( "Cannot find factory matching "+name );
+ }
+
+ public static RtiFactory getRtiFactory() throws RTIinternalError
+ {
+ ServiceLoader
+ * Note: because we're altering the current thread's classloader, this is only useful
+ * if performed on the same thread as the first call to a method of
+ * {@link org.openlvc.disco.connection.rpr.RprRtiFactoryFactory}.
*
* @param paths The paths to add to the lookup set
* @throws DiscoException If there any invalid files are provided