@@ -294,6 +294,45 @@ public class DefaultPluginManager implements PluginManager { | |||
} | |||
} | |||
@Override | |||
public boolean unloadPlugin(String pluginId) { | |||
try { | |||
PluginState state = stopPlugin(pluginId); | |||
if (!PluginState.STOPPED.equals(state)) { | |||
return false; | |||
} | |||
PluginWrapper pluginWrapper = plugins.get(pluginId); | |||
PluginDescriptor descriptor = pluginWrapper.getDescriptor(); | |||
List<PluginDependency> dependencies = descriptor.getDependencies(); | |||
for (PluginDependency dependency : dependencies) { | |||
if (!unloadPlugin(dependency.getPluginId())) { | |||
return false; | |||
} | |||
} | |||
// remove the plugin | |||
plugins.remove(pluginId); | |||
resolvedPlugins.remove(pluginWrapper); | |||
pathToIdMap.remove(pluginWrapper.getPluginPath()); | |||
// remove the classloader | |||
if (pluginClassLoaders.containsKey(pluginId)) { | |||
PluginClassLoader classLoader = pluginClassLoaders.remove(pluginId); | |||
compoundClassLoader.removeLoader(classLoader); | |||
try { | |||
classLoader.close(); | |||
} catch (IOException e) { | |||
log.error(e.getMessage(), e); | |||
} | |||
} | |||
return true; | |||
} catch (IllegalArgumentException e) { | |||
// ignore not found exceptions because this method is recursive | |||
} | |||
return false; | |||
} | |||
/** | |||
* Get plugin class loader for this path. | |||
*/ |
@@ -71,6 +71,14 @@ public interface PluginManager { | |||
*/ | |||
public PluginState stopPlugin(String pluginId); | |||
/** | |||
* Unload a plugin. | |||
* | |||
* @param pluginId | |||
* @return true if the plugin was unloaded | |||
*/ | |||
public boolean unloadPlugin(String pluginId); | |||
public PluginClassLoader getPluginClassLoader(String pluginId); | |||
public <T> List<T> getExtensions(Class<T> type); |
@@ -1,11 +1,11 @@ | |||
/* | |||
* Copyright 2012 Decebal Suiu | |||
* | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with | |||
* the License. You may obtain a copy of the License in the LICENSE file, or 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. | |||
@@ -23,7 +23,7 @@ import java.util.Set; | |||
/** | |||
* A class loader that has multiple loaders and uses them for loading classes and resources. | |||
* | |||
* | |||
* @author Decebal Suiu | |||
*/ | |||
public class CompoundClassLoader extends ClassLoader { | |||
@@ -34,6 +34,10 @@ public class CompoundClassLoader extends ClassLoader { | |||
loaders.add(loader); | |||
} | |||
public void removeLoader(ClassLoader loader) { | |||
loaders.remove(loader); | |||
} | |||
@Override | |||
public Class<?> findClass(String name) throws ClassNotFoundException { | |||
for (ClassLoader loader : loaders) { | |||
@@ -43,7 +47,7 @@ public class CompoundClassLoader extends ClassLoader { | |||
// try next | |||
} | |||
} | |||
throw new ClassNotFoundException(name); | |||
} | |||
@@ -55,7 +59,7 @@ public class CompoundClassLoader extends ClassLoader { | |||
return url; | |||
} | |||
} | |||
return null; | |||
} | |||
@@ -65,8 +69,8 @@ public class CompoundClassLoader extends ClassLoader { | |||
for (ClassLoader loader : loaders) { | |||
resources.addAll(Collections.list(loader.getResources(name))); | |||
} | |||
return Collections.enumeration(resources); | |||
} | |||
} |