implement WebResourceLoaders for loading plugin web resources

This commit is contained in:
Sebastian Sdorra
2014-08-27 21:01:05 +02:00
parent ad686cb787
commit a3be1c775b
15 changed files with 1029 additions and 79 deletions

View File

@@ -56,6 +56,8 @@ import java.util.Collection;
import java.util.Enumeration;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@@ -81,13 +83,17 @@ public class DefaultPluginLoader implements PluginLoader
/**
* Constructs ...
*
* @param servletContext
* @param parent
* @param wrappedPlugins
* @param installedPlugins
*/
public DefaultPluginLoader(ClassLoader parent,
Set<PluginWrapper> wrappedPlugins)
public DefaultPluginLoader(ServletContext servletContext, ClassLoader parent,
Set<PluginWrapper> installedPlugins)
{
this.uberClassLoader = new UberClassLoader(parent, wrappedPlugins);
this.installedPlugins = installedPlugins;
this.uberClassLoader = new UberClassLoader(parent, installedPlugins);
this.uberWebResourceLoader =
new DefaultUberWebResourceLoader(servletContext, installedPlugins);
try
{
@@ -96,16 +102,8 @@ public class DefaultPluginLoader implements PluginLoader
modules = getInstalled(parent, context, PATH_MODULECONFIG);
// hidden plugins ???
Set<Plugin> ips = getInstalled(parent, context, PATH_PLUGINCONFIG);
Builder<Plugin> builder = ImmutableSet.builder();
builder.addAll(ips);
builder.addAll(PluginsInternal.unwrap(wrappedPlugins));
plugins = builder.build();
appendExtensions(multiple, single, extensions, modules);
appendExtensions(multiple, single, extensions, plugins);
appendExtensions(multiple, single, extensions, unwrap());
}
catch (IOException | JAXBException ex)
{
@@ -127,7 +125,7 @@ public class DefaultPluginLoader implements PluginLoader
logger.info("start processing extensions");
appendExtensions(multiple, single, extensions, modules);
appendExtensions(multiple, single, extensions, plugins);
appendExtensions(multiple, single, extensions, unwrap());
if (logger.isInfoEnabled())
{
@@ -173,9 +171,9 @@ public class DefaultPluginLoader implements PluginLoader
* @return
*/
@Override
public Collection<Plugin> getInstalledPlugins()
public Collection<PluginWrapper> getInstalledPlugins()
{
return plugins;
return installedPlugins;
}
/**
@@ -190,6 +188,18 @@ public class DefaultPluginLoader implements PluginLoader
return uberClassLoader;
}
/**
* Method description
*
*
* @return
*/
@Override
public UberWebResourceLoader getUberWebResourceLoader()
{
return uberWebResourceLoader;
}
//~--- methods --------------------------------------------------------------
/**
@@ -242,6 +252,17 @@ public class DefaultPluginLoader implements PluginLoader
}
}
/**
* Method description
*
*
* @return
*/
private Iterable<Plugin> unwrap()
{
return PluginsInternal.unwrap(installedPlugins);
}
//~--- get methods ----------------------------------------------------------
/**
@@ -282,15 +303,18 @@ public class DefaultPluginLoader implements PluginLoader
/** Field description */
private final ClassLoader uberClassLoader;
/** Field description */
private final UberWebResourceLoader uberWebResourceLoader;
/** Field description */
private Set<PluginWrapper> installedPlugins;
/** Field description */
private Set<ScmModule> modules;
/** Field description */
private Set<Class> multiple = Sets.newHashSet();
/** Field description */
private Set<Plugin> plugins;
/** Field description */
private Set<Class> single = Sets.newHashSet();

View File

@@ -98,10 +98,6 @@ public class DefaultPluginManager implements PluginManager
/** Field description */
public static final String ENCODING = "UTF-8";
/** Field description */
private static final String ADVANCED_CONFIGURATION =
"advanced-configuration.xml";
/** the logger for DefaultPluginManager */
private static final Logger logger =
LoggerFactory.getLogger(DefaultPluginManager.class);
@@ -133,10 +129,11 @@ public class DefaultPluginManager implements PluginManager
this.configuration = configuration;
this.cache = cacheManager.getCache(CACHE_NAME);
this.clientProvider = clientProvider;
installedPlugins = new HashMap<String, Plugin>();
installedPlugins = new HashMap<>();
for (Plugin plugin : pluginLoader.getInstalledPlugins())
for (PluginWrapper wrapper : pluginLoader.getInstalledPlugins())
{
Plugin plugin = wrapper.getPlugin();
PluginInformation info = plugin.getInformation();
if ((info != null) && info.isValid())
@@ -247,15 +244,17 @@ public class DefaultPluginManager implements PluginManager
throw new PluginConditionFailedException(condition);
}
/*AetherPluginHandler aph = new AetherPluginHandler(this, context,
configuration);
Collection<PluginRepository> repositories =
Sets.newHashSet(new PluginRepository("package-repository",
"file://".concat(tempDirectory.getAbsolutePath())));
aph.setPluginRepositories(repositories);
aph.install(plugin.getInformation().getId());*/
/*
* AetherPluginHandler aph = new AetherPluginHandler(this, context,
* configuration);
* Collection<PluginRepository> repositories =
* Sets.newHashSet(new PluginRepository("package-repository",
* "file://".concat(tempDirectory.getAbsolutePath())));
*
* aph.setPluginRepositories(repositories);
*
* aph.install(plugin.getInformation().getId());
*/
plugin.getInformation().setState(PluginState.INSTALLED);
installedPlugins.put(plugin.getInformation().getId(), plugin);
@@ -300,12 +299,14 @@ public class DefaultPluginManager implements PluginManager
throw new PluginNotInstalledException(id.concat(" is not install"));
}
/*if (pluginHandler == null)
{
getPluginCenter();
}
pluginHandler.uninstall(id);*/
/*
* if (pluginHandler == null)
* {
* getPluginCenter();
* }
*
* pluginHandler.uninstall(id);
*/
installedPlugins.remove(id);
preparePlugins(getPluginCenter());
}
@@ -394,7 +395,7 @@ public class DefaultPluginManager implements PluginManager
AssertUtil.assertIsNotNull(predicate);
SecurityUtil.assertIsAdmin();
Set<PluginInformation> infoSet = new HashSet<PluginInformation>();
Set<PluginInformation> infoSet = new HashSet<>();
filter(infoSet, getInstalled(), predicate);
filter(infoSet, getPluginCenter().getPlugins(), predicate);
@@ -431,7 +432,7 @@ public class DefaultPluginManager implements PluginManager
{
SecurityUtil.assertIsAdmin();
Set<PluginInformation> availablePlugins = new HashSet<PluginInformation>();
Set<PluginInformation> availablePlugins = new HashSet<>();
Set<PluginInformation> centerPlugins = getPluginCenter().getPlugins();
for (PluginInformation info : centerPlugins)
@@ -470,7 +471,7 @@ public class DefaultPluginManager implements PluginManager
{
SecurityUtil.assertIsAdmin();
Set<PluginInformation> infoSet = new LinkedHashSet<PluginInformation>();
Set<PluginInformation> infoSet = new LinkedHashSet<>();
for (Plugin plugin : installedPlugins.values())
{
@@ -642,16 +643,18 @@ public class DefaultPluginManager implements PluginManager
preparePlugins(center);
cache.put(PluginCenter.class.getName(), center);
/*if (pluginHandler == null)
{
pluginHandler = new AetherPluginHandler(this,
SCMContext.getContext(), configuration,
advancedPluginConfiguration);
}
pluginHandler.setPluginRepositories(center.getRepositories());*/
/*
* if (pluginHandler == null)
* {
* pluginHandler = new AetherPluginHandler(this,
* SCMContext.getContext(), configuration,
* advancedPluginConfiguration);
* }
*
* pluginHandler.setPluginRepositories(center.getRepositories());
*/
}
catch (Exception ex)
catch (IOException | JAXBException ex)
{
logger.error("could not load plugins from plugin center", ex);
}

View File

@@ -0,0 +1,231 @@
/**
* Copyright (c) 2014, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import javax.servlet.ServletContext;
/**
* Default implementation of the {@link UberWebResourceLoader}.
*
* @author Sebastian Sdorra
* @since 2.0.0
*/
public class DefaultUberWebResourceLoader implements UberWebResourceLoader
{
/**
* the logger for DefaultUberWebResourceLoader
*/
private static final Logger logger =
LoggerFactory.getLogger(DefaultUberWebResourceLoader.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param servletContext
* @param plugins
*/
public DefaultUberWebResourceLoader(ServletContext servletContext,
Iterable<PluginWrapper> plugins)
{
this.servletContext = servletContext;
this.plugins = plugins;
this.cache = CacheBuilder.newBuilder().build();
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param path
*
* @return
*/
@Override
public URL getResource(String path)
{
URL resource = cache.getIfPresent(path);
if (resource == null)
{
resource = find(path);
if (resource != null)
{
cache.put(path, resource);
}
}
else
{
logger.trace("return web resource {} from cache", path);
}
return resource;
}
/**
* Method description
*
*
* @param path
*
* @return
*/
@Override
public List<URL> getResources(String path)
{
// caching ???
Builder<URL> resources = ImmutableList.builder();
try
{
URL ctxResource = servletContext.getResource(path);
if (ctxResource != null)
{
logger.trace("found path {} at ServletContext", path);
resources.add(ctxResource);
}
for (PluginWrapper wrapper : plugins)
{
URL resource = wrapper.getWebResourceLoader().getResource(path);
if (resource != null)
{
resources.add(resource);
}
}
}
catch (MalformedURLException ex)
{
// TODO define an extra exception
throw Throwables.propagate(ex);
}
return resources.build();
}
/**
* Method description
*
*
* @return
*/
@VisibleForTesting
Cache<String, URL> getCache()
{
return cache;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param path
*
* @return
*/
private URL find(String path)
{
URL resource = null;
try
{
resource = servletContext.getResource(path);
if (resource == null)
{
for (PluginWrapper wrapper : plugins)
{
resource = wrapper.getWebResourceLoader().getResource(path);
if (resource != null)
{
break;
}
}
}
else
{
logger.trace("found path {} at ServletContext", path);
}
}
catch (MalformedURLException ex)
{
// TODO define an extra exception
throw Throwables.propagate(ex);
}
return resource;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Cache<String, URL> cache;
/** Field description */
private final Iterable<PluginWrapper> plugins;
/** Field description */
private final ServletContext servletContext;
}

View File

@@ -0,0 +1,162 @@
/**
* Copyright (c) 2014, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Load web resources from a plugin webapp directory.
*
* @author Sebastian Sdorra
* @since 2.0.0
*/
public class PathWebResourceLoader implements WebResourceLoader
{
/** Field description */
private static final String DEFAULT_SEPARATOR = "/";
/**
* the logger for PathWebResourceLoader
*/
private static final Logger logger =
LoggerFactory.getLogger(PathWebResourceLoader.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param directory
*/
public PathWebResourceLoader(Path directory)
{
this.directory = directory;
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @param path
*
* @return
*/
@Override
public URL getResource(String path)
{
URL resource = null;
Path file = directory.resolve(filePath(path));
if (Files.exists(file))
{
logger.trace("found path {} at {}", path, file);
try
{
resource = file.toUri().toURL();
}
catch (MalformedURLException ex)
{
logger.error("could not transform path to url", ex);
}
}
return resource;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param path
*
* @return
*/
private String filePath(String path)
{
// TODO handle illegal path parts, such as ..
String filePath = filePath(DEFAULT_SEPARATOR, path);
if (!DEFAULT_SEPARATOR.equals(File.separator))
{
filePath = filePath(File.separator, path);
}
return filePath;
}
/**
* Method description
*
*
* @param separator
* @param path
*
* @return
*/
private String filePath(String separator, String path)
{
String filePath = path;
if (filePath.startsWith(separator))
{
filePath = filePath.substring(separator.length());
}
return filePath;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Path directory;
}

View File

@@ -491,7 +491,8 @@ public final class PluginProcessor
throws IOException
{
PluginWrapper wrapper = null;
Path descriptor = smp.getPath().resolve(PluginConstants.FILE_DESCRIPTOR);
Path directory = smp.getPath();
Path descriptor = directory.resolve(PluginConstants.FILE_DESCRIPTOR);
if (Files.exists(descriptor))
{
@@ -499,7 +500,8 @@ public final class PluginProcessor
Plugin plugin = createPlugin(cl, descriptor);
wrapper = new PluginWrapper(plugin, cl, smp.getPath());
wrapper = new PluginWrapper(plugin, cl,
new PathWebResourceLoader(directory), directory);
}
else
{