+/*
+ * Copyright (c) 2014, 2017 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
package org.opendaylight.controller.config.spi;
import org.opendaylight.controller.config.api.DependencyResolver;
import org.slf4j.LoggerFactory;
/**
- * Base implementation of Module. This implementation contains base logic for Module reconfiguration with associated fields.
- * @param <M> Type of module implementation. Enables easier implementation for the {@link #isSame} method
+ * Base implementation of Module. This implementation contains base logic for
+ * Module reconfiguration with associated fields.
+ *
+ * @param <M>
+ * Type of module implementation. Enables easier implementation for
+ * the <code>isSame()</code> method
*/
-public abstract class AbstractModule<M extends AbstractModule<M>> implements org.opendaylight.controller.config.spi.Module {
+public abstract class AbstractModule<M extends AbstractModule<M>>
+ implements org.opendaylight.controller.config.spi.Module {
private static final Logger LOG = LoggerFactory.getLogger(AbstractModule.class);
- private final M oldModule;
- private final AutoCloseable oldInstance;
+ protected final DependencyResolver dependencyResolver;
protected final ModuleIdentifier identifier;
+
+ private AutoCloseable oldInstance;
+ private M oldModule;
private AutoCloseable instance;
- protected final DependencyResolver dependencyResolver;
+ private boolean canReuseInstance = true;
/**
* Called when module is configured.
*
- * @param identifier id of current instance.
- * @param dependencyResolver resolver used in dependency injection and validation.
+ * @param identifier
+ * id of current instance.
+ * @param dependencyResolver
+ * resolver used in dependency injection and validation.
*/
- public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver) {
+ public AbstractModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver) {
this(identifier, dependencyResolver, null, null);
}
/**
* Called when module is reconfigured.
*
- * @param identifier id of current instance.
- * @param dependencyResolver resolver used in dependency injection and validation.
- * @param oldModule old instance of module that is being reconfigred(replaced) by current instance. The old instance can be examined for reuse.
- * @param oldInstance old instance wrapped by the old module. This is the resource that is actually being reused if possible or closed otherwise.
+ * @param identifier
+ * id of current instance.
+ * @param dependencyResolver
+ * resolver used in dependency injection and validation.
+ * @param oldModule
+ * old instance of module that is being reconfigred(replaced) by
+ * current instance. The old instance can be examined for reuse.
+ * @param oldInstance
+ * old instance wrapped by the old module. This is the resource that
+ * is actually being reused if possible or closed otherwise.
*/
- public AbstractModule(ModuleIdentifier identifier, DependencyResolver dependencyResolver, M oldModule, AutoCloseable oldInstance) {
+ public AbstractModule(final ModuleIdentifier identifier, final DependencyResolver dependencyResolver,
+ final M oldModule, final AutoCloseable oldInstance) {
this.identifier = identifier;
this.dependencyResolver = dependencyResolver;
this.oldModule = oldModule;
return identifier;
}
+ public final void setCanReuseInstance(final boolean canReuseInstance) {
+ this.canReuseInstance = canReuseInstance;
+ }
+
/**
- *
* General algorithm for spawning/closing and reusing wrapped instances.
*
- * @return current instance of wrapped resource either by reusing the old one (if present) or constructing a brand new.
+ * @return current instance of wrapped resource either by reusing the old one
+ * (if present) or constructing a brand new.
*/
@Override
+ @SuppressWarnings("IllegalCatch")
public final AutoCloseable getInstance() {
- if(instance==null) {
- if(oldInstance!=null && canReuseInstance(oldModule)) {
+ if (instance == null) {
+ if (oldInstance != null && canReuseInstance && canReuseInstance(oldModule)) {
resolveDependencies();
instance = reuseInstance(oldInstance);
} else {
- if(oldInstance!=null) {
+ if (oldInstance != null) {
try {
oldInstance.close();
- } catch(Exception e) {
- LOG.error("An error occurred while closing old instance {} for module {}", oldInstance, getIdentifier(), e);
+ } catch (final Exception exception) {
+ LOG.error("An error occurred while closing old instance {} for module {}", oldInstance,
+ getIdentifier(), exception);
}
}
resolveDependencies();
instance = createInstance();
if (instance == null) {
- throw new IllegalStateException("Error in createInstance - null is not allowed as return value. Module: " + getIdentifier());
+ throw new IllegalStateException(
+ "Error in createInstance - null is not allowed as return value. Module: "
+ + getIdentifier());
}
}
+
+ // Prevent serial memory leak: clear these references as we will not use them
+ // again.
+ oldInstance = null;
+ oldModule = null;
}
+
return instance;
}
/**
- * @return Brand new instance of wrapped class in case no previous instance is present or reconfiguration is impossible.
+ * Create instance.
+ *
+ * @return Brand new instance of wrapped class in case no previous instance is
+ * present or reconfiguration is impossible.
*/
protected abstract AutoCloseable createInstance();
@Override
- public final boolean canReuse(Module oldModule) {
+ public final boolean canReuse(final Module oldModule) {
// Just cast into a specific instance
- // TODO unify this method with canReuseInstance (required Module interface to be generic which requires quite a lot of changes)
- return getClass().isInstance(oldModule) ? canReuseInstance((M) oldModule) : false;
+ // TODO unify this method with canReuseInstance (required Module interface to be
+ // generic which requires quite a lot of changes)
+ return canReuseInstance && getClass().isInstance(oldModule) ? canReuseInstance((M) oldModule) : false;
}
/**
+ * Users are welcome to override this method to provide custom logic for
+ * advanced reusability detection.
*
- * Users are welcome to override this method to provide custom logic for advanced reusability detection.
- *
- * @param oldModule old instance of a Module
- * @return true if the old instance is reusable false if a new one should be spawned
+ * @param oldModule
+ * old instance of a Module
+ * @return true if the old instance is reusable false if a new one should be
+ * spawned
*/
- protected abstract boolean canReuseInstance(final M oldModule);
+ protected abstract boolean canReuseInstance(M oldModule);
/**
- * By default the oldInstance is returned since this method is by default called only if the oldModule had the same configuration and dependencies configured.
- * Users are welcome to override this method to provide custom logic for advanced reusability.
+ * By default the oldInstance is returned since this method is by default called
+ * only if the oldModule had the same configuration and dependencies configured.
+ * Users are welcome to override this method to provide custom logic for
+ * advanced reusability.
*
- * @param oldInstance old instance of a class wrapped by the module
+ * @param oldInstance
+ * old instance of a class wrapped by the module
* @return reused instance
*/
- protected AutoCloseable reuseInstance(AutoCloseable oldInstance) {
- // implement if instance reuse should be supported. Override canReuseInstance to change the criteria.
+ protected AutoCloseable reuseInstance(final AutoCloseable oldInstance) {
+ // implement if instance reuse should be supported. Override canReuseInstance to
+ // change the criteria.
return oldInstance;
}