Skip to content
Permalink
Browse files
[AMBARI-25036] Update Stack Classloader Loading Pattern (#2716)
  • Loading branch information
ncole committed Dec 11, 2018
1 parent 2ae3987 commit 0c8286a5d39c95022c1857090b175efb5e81098a
Showing 6 changed files with 52 additions and 30 deletions.
@@ -178,7 +178,6 @@ public Set<String> getFailedPluginClassNames() {
* @param pluginChecks
* the collection to popoulate.
*/
@SuppressWarnings("unchecked")
private void loadPluginUpgradeChecksFromStack(UpgradePack upgradePack,
PluginUpgradeChecks pluginChecks) throws AmbariException {
List<String> pluginCheckClassNames = upgradePack.getPrerequisiteChecks();
@@ -189,13 +188,11 @@ private void loadPluginUpgradeChecksFromStack(UpgradePack upgradePack,
if (null != classLoader) {
for (String pluginCheckClassName : pluginCheckClassNames) {
try {
Class<? extends UpgradeCheck> upgradeCheckClass = (Class<? extends UpgradeCheck>) classLoader.loadClass(
pluginCheckClassName);
UpgradeCheck upgradeCheck = stackInfo.getLibraryInstance(m_injector, pluginCheckClassName);

UpgradeCheck upgradeCheck = m_injector.getInstance(upgradeCheckClass);
pluginChecks.m_loadedChecks.add(upgradeCheck);

LOG.info("Registered pre-upgrade check {} for stack {}", upgradeCheckClass, ownerStackId);
LOG.info("Registered pre-upgrade check {} for stack {}", pluginCheckClassName, ownerStackId);
} catch (Exception exception) {
LOG.error("Unable to load the upgrade check {}", pluginCheckClassName, exception);

@@ -83,11 +83,7 @@ public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataCont
final String pluginClassName = getActionClassName();

try {
@SuppressWarnings("unchecked")
Class<? extends UpgradeAction> upgradeActionClass = (Class<? extends UpgradeAction>) pluginClassLoader.loadClass(
pluginClassName);

upgradeAction = upgradeActionClass.newInstance();
upgradeAction = stackInfo.getLibraryInstance(pluginClassName);
} catch (Exception exception) {
LOG.error("Unable to load the upgrade action {}", pluginClassName, exception);

@@ -1545,12 +1545,9 @@ private OrchestrationOptions getOrchestrationOptions(AmbariMetaInfo metaInfo, Up

try {
StackInfo stack = metaInfo.getStack(stackId);
ClassLoader cl = stack.getLibraryClassLoader();

Class<?> clazz = (null == cl) ? Class.forName(className) :
cl.loadClass(className);
return stack.getLibraryInstance(className);

return (OrchestrationOptions) clazz.newInstance();
} catch (Exception e) {
LOG.error(String.format("Could not load orchestration options for stack {}: {}",
stackId, e.getMessage()));
@@ -50,6 +50,7 @@
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import com.google.common.io.Files;
import com.google.inject.Injector;

public class StackInfo implements Comparable<StackInfo>, Validable {
private static final Logger LOG = LoggerFactory.getLogger(StackInfo.class);
@@ -654,17 +655,8 @@ public Set<String> getServiceNames() {
public StackReleaseVersion getReleaseVersion() {

if (StringUtils.isNotEmpty(releaseVersionClass)) {

try {
Class<?> clazz = null;

if (null != libraryClassLoader) {
clazz = libraryClassLoader.loadClass(releaseVersionClass);
} else {
clazz = Class.forName(releaseVersionClass);
}

return (StackReleaseVersion) clazz.newInstance();
return getLibraryInstance(releaseVersionClass);
} catch (Exception e) {
LOG.error("Could not create stack release instance. Using default. {}", e.getMessage());
return new DefaultStackVersion();
@@ -695,4 +687,45 @@ public StackReleaseVersion getReleaseVersion() {
public void setLibraryClassLoader(ClassLoader libraryClassLoader) {
this.libraryClassLoader = libraryClassLoader;
}

/**
* Loads an instance of the class from the stack classloader, if available.
*
* @param className
* the name of the class to get an instance
* @return
* the instance of the class
* @throws Exception
* when the class cannot be loaded or instantiated
*/
public <T> T getLibraryInstance(String className) throws Exception {
return getLibraryInstance(null, className);
}

/**
* Loads an instance of the class from the stack classloader, if available.
*
* @param injector
* the injector to use, or {@code null} to invoke the default, no-arg
* constructor
* @param className
* the name of the class to get an instance
* @return
* the instance of the class
* @throws Exception
* when the class cannot be loaded or instantiated
*/
@SuppressWarnings("unchecked")
public <T> T getLibraryInstance(Injector injector, String className) throws Exception {
Class<? extends T> clazz;

if (null != libraryClassLoader) {
clazz = (Class<? extends T>) libraryClassLoader.loadClass(className);
} else {
clazz = (Class<? extends T>) Class.forName(className);
}

return (null == injector) ? clazz.newInstance() : injector.getInstance(clazz);
}

}
@@ -102,6 +102,7 @@
import org.apache.ambari.spi.upgrade.UpgradeCheckType;
import org.apache.ambari.spi.upgrade.UpgradeType;
import org.apache.commons.lang3.StringUtils;
import org.easymock.EasyMock;
import org.easymock.EasyMockSupport;
import org.junit.Assert;
import org.junit.Test;
@@ -214,12 +215,11 @@ public void testGetResources() throws Exception{
expect(serviceInfo.getChecksFolder()).andReturn(new File(checks));

ClassLoader classLoader = createNiceMock(ClassLoader.class);
Class clazz = SampleServiceCheck.class;
expect(classLoader.loadClass(TEST_SERVICE_CHECK_CLASS_NAME)).andReturn(clazz).atLeastOnce();

StackInfo stackInfo = createNiceMock(StackInfo.class);
expect(ambariMetaInfo.getStack(targetStackId)).andReturn(stackInfo).atLeastOnce();
expect(stackInfo.getLibraryClassLoader()).andReturn(classLoader).atLeastOnce();
expect(stackInfo.getLibraryInstance(EasyMock.anyObject(), EasyMock.eq(TEST_SERVICE_CHECK_CLASS_NAME)))
.andReturn(new SampleServiceCheck()).atLeastOnce();

// replay
replayAll();
@@ -49,6 +49,7 @@
import org.apache.ambari.spi.upgrade.UpgradeActionOperations;
import org.apache.ambari.spi.upgrade.UpgradeActionOperations.ConfigurationChanges;
import org.apache.ambari.spi.upgrade.UpgradeInformation;
import org.easymock.EasyMock;
import org.easymock.EasyMockSupport;
import org.junit.After;
import org.junit.Before;
@@ -128,13 +129,11 @@ public void before() throws Exception {
expect(m_mockUpgradePack.getOwnerStackId()).andReturn(m_stackId).atLeastOnce();
expect(m_mockMetaInfo.getStack(m_stackId)).andReturn(m_mockStackInfo).atLeastOnce();
expect(m_mockStackInfo.getLibraryClassLoader()).andReturn(m_mockClassLoader).atLeastOnce();
expect(m_mockStackInfo.getLibraryInstance(EasyMock.anyString())).andReturn(new MockUpgradeAction()).atLeastOnce();

expect(m_action.getClusters()).andReturn(m_mockClusters).anyTimes();
expect(m_action.getUpgradeContext(m_mockCluster)).andReturn(m_mockUpgradeContext).once();

Class clazz = MockUpgradeAction.class;
expect(m_mockClassLoader.loadClass(CLASS_NAME)).andReturn(clazz).atLeastOnce();

m_action.agentConfigsHolder = m_mockAgentConfigsHolder;

m_commandParams.put("clusterName", CLUSTER_NAME);

0 comments on commit 0c8286a

Please sign in to comment.