Return-Path: X-Original-To: apmail-jspwiki-commits-archive@www.apache.org Delivered-To: apmail-jspwiki-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 360FF10EC8 for ; Mon, 10 Feb 2014 19:50:25 +0000 (UTC) Received: (qmail 52821 invoked by uid 500); 10 Feb 2014 19:50:24 -0000 Delivered-To: apmail-jspwiki-commits-archive@jspwiki.apache.org Received: (qmail 52790 invoked by uid 500); 10 Feb 2014 19:50:24 -0000 Mailing-List: contact commits-help@jspwiki.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jspwiki.apache.org Delivered-To: mailing list commits@jspwiki.apache.org Received: (qmail 52780 invoked by uid 99); 10 Feb 2014 19:50:24 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 10 Feb 2014 19:50:24 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 10 Feb 2014 19:50:19 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id A64BD238889B; Mon, 10 Feb 2014 19:49:57 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1566717 - in /jspwiki/trunk: ./ jspwiki-war/src/main/java/org/apache/wiki/ jspwiki-war/src/main/java/org/apache/wiki/api/engine/ jspwiki-war/src/main/java/org/apache/wiki/plugin/ jspwiki-war/src/main/java/org/apache/wiki/util/ jspwiki-war/... Date: Mon, 10 Feb 2014 19:49:57 -0000 To: commits@jspwiki.apache.org From: metskem@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140210194957.A64BD238889B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: metskem Date: Mon Feb 10 19:49:56 2014 New Revision: 1566717 URL: http://svn.apache.org/r1566717 Log: 2014-02-10 Harry Metske (metskem@apache.org) * 2.10.0-svn-72 * Fixed JSPWIKI-812 - plugin jars should be loadable from outside the war Modified: jspwiki/trunk/ChangeLog jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/api/engine/PluginManager.java jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/util/ClassUtil.java jspwiki/trunk/jspwiki-war/src/main/resources/ini/jspwiki.properties Modified: jspwiki/trunk/ChangeLog URL: http://svn.apache.org/viewvc/jspwiki/trunk/ChangeLog?rev=1566717&r1=1566716&r2=1566717&view=diff ============================================================================== --- jspwiki/trunk/ChangeLog (original) +++ jspwiki/trunk/ChangeLog Mon Feb 10 19:49:56 2014 @@ -1,9 +1,17 @@ +2014-02-10 Harry Metske (metskem@apache.org) + + * 2.10.0-svn-72 + + * Fixed JSPWIKI-812 - plugin jars should be loadable from outside the war + 2014-02-09 Harry Metske (metskem@apache.org) + * 2.10.0-svn-71 * Fixed JSPWIKI-813 - ReferenceManagerTest - two cases fail, patch by Brian Burch 2014-02-08 Harry Metske (metskem@apache.org) + * 2.10.0-svn-70 * Fixed JSPWIKI-817 - Install.jsp is broken ==> Translation corrections required (EN en NL done) Modified: jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java?rev=1566717&r1=1566716&r2=1566717&view=diff ============================================================================== --- jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java (original) +++ jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/Release.java Mon Feb 10 19:49:56 2014 @@ -72,7 +72,7 @@ public final class Release { *

* If the build identifier is empty, it is not added. */ - public static final String BUILD = "71"; + public static final String BUILD = "72"; /** * This is the generic version string you should use when printing out the version. It is of Modified: jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/api/engine/PluginManager.java URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/api/engine/PluginManager.java?rev=1566717&r1=1566716&r2=1566717&view=diff ============================================================================== --- jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/api/engine/PluginManager.java (original) +++ jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/api/engine/PluginManager.java Mon Feb 10 19:49:56 2014 @@ -30,10 +30,13 @@ import org.apache.wiki.api.plugin.WikiPl public interface PluginManager { - - /** The property name defining which packages will be searched for properties. */ + + /** The property name defining which packages will be searched for plugin classes. */ String PROP_SEARCHPATH = "jspwiki.plugin.searchPath"; - + + /** The property name defining which external jars will be added to the classpath when searching for plugin classes. */ + String PROP_EXTERNALJARS = "jspwiki.plugin.externalJars"; + /** This is the default package to try in case the instantiation fails. */ String DEFAULT_PACKAGE = "org.apache.wiki.plugin"; Modified: jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java?rev=1566717&r1=1566716&r2=1566717&view=diff ============================================================================== --- jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java (original) +++ jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/plugin/DefaultPluginManager.java Mon Feb 10 19:49:56 2014 @@ -166,7 +166,9 @@ public class DefaultPluginManager extend private static final String DEFAULT_FORMS_PACKAGE = "org.apache.wiki.forms"; - private ArrayList m_searchPath = new ArrayList(); + private ArrayList m_searchPath = new ArrayList(); + + private ArrayList m_externalJars = new ArrayList(); private Pattern m_pluginPattern; @@ -195,6 +197,16 @@ public class DefaultPluginManager extend } } + String externalJars = props.getProperty( PROP_EXTERNALJARS ); + + if( externalJars != null ) { + StringTokenizer tok = new StringTokenizer( externalJars, "," ); + + while( tok.hasMoreTokens() ) { + m_externalJars.add( tok.nextToken().trim() ); + } + } + registerPlugins(); // @@ -253,7 +265,7 @@ public class DefaultPluginManager extend * @throws ClassNotFoundException if no such class exists. */ private Class< ? > findPluginClass( String classname ) throws ClassNotFoundException { - return ClassUtil.findClass( m_searchPath, classname ); + return ClassUtil.findClass( m_searchPath, m_externalJars, classname ); } /** @@ -531,7 +543,7 @@ public class DefaultPluginManager extend m_pluginClassMap.put( name, pluginClass ); } - pluginClass.initializePlugin( m_engine ); + pluginClass.initializePlugin( m_engine , m_searchPath, m_externalJars); } private void registerPlugins() { @@ -545,7 +557,7 @@ public class DefaultPluginManager extend // for( Element pluginEl : plugins ) { String className = pluginEl.getAttributeValue( "class" ); - WikiPluginInfo pluginInfo = WikiPluginInfo.newInstance( className, pluginEl ); + WikiPluginInfo pluginInfo = WikiPluginInfo.newInstance( className, pluginEl ,m_searchPath, m_externalJars); if( pluginInfo != null ) { registerPlugin( pluginInfo ); @@ -557,7 +569,6 @@ public class DefaultPluginManager extend * Contains information about a bunch of plugins. * * - * @since */ // FIXME: This class needs a better interface to return all sorts of possible // information from the plugin XML. In fact, it probably should have @@ -576,11 +587,13 @@ public class DefaultPluginManager extend * @param className Either a fully qualified class name, or a "short" name which is then * checked against the internal list of plugin packages. * @param el A JDOM Element containing the information about this class. + * @param searchPath A List of Strings, containing different package names. + * @param externalJars the list of external jars to search * @return A WikiPluginInfo object. */ - protected static WikiPluginInfo newInstance( String className, Element el ) { + protected static WikiPluginInfo newInstance( String className, Element el, List searchPath, List externalJars ) { if( className == null || className.length() == 0 ) return null; - + WikiPluginInfo info = new WikiPluginInfo( className ); info.initializeFromXML( el ); return info; @@ -590,14 +603,16 @@ public class DefaultPluginManager extend * Initializes a plugin, if it has not yet been initialized. * * @param engine The WikiEngine + * @param searchPath A List of Strings, containing different package names. + * @param externalJars the list of external jars to search */ - protected void initializePlugin( WikiEngine engine ) { + protected void initializePlugin( WikiEngine engine , List searchPath, List externalJars) { if( !m_initialized ) { // This makes sure we only try once per class, even if init fails. m_initialized = true; try { - WikiPlugin p = newPluginInstance(); + WikiPlugin p = newPluginInstance(searchPath, externalJars); if( p instanceof InitializablePlugin ) { ( ( InitializablePlugin )p ).initialize( engine ); } @@ -655,14 +670,17 @@ public class DefaultPluginManager extend /** * Creates a new plugin instance. * + * @param searchPath A List of Strings, containing different package names. + * @param externalJars the list of external jars to search + * @return A new plugin. * @throws ClassNotFoundException If the class declared was not found. * @throws InstantiationException If the class cannot be instantiated- * @throws IllegalAccessException If the class cannot be accessed. */ - public WikiPlugin newPluginInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException { + public WikiPlugin newPluginInstance(List searchPath, List externalJars) throws ClassNotFoundException, InstantiationException, IllegalAccessException { if( m_clazz == null ) { - m_clazz = Class.forName(m_className); + m_clazz = ClassUtil.findClass(searchPath, externalJars ,m_className); } return (WikiPlugin) m_clazz.newInstance(); @@ -774,7 +792,7 @@ public class DefaultPluginManager extend String msg = "Plugin '" + pluginInfo.getName() + "' not compatible with this version of JSPWiki"; log.info( msg ); } else { - plugin = pluginInfo.newPluginInstance(); + plugin = pluginInfo.newPluginInstance(m_searchPath, m_externalJars); } } catch( ClassNotFoundException e ) { throw new PluginException( MessageFormat.format( rb.getString( "plugin.error.couldnotfind" ), pluginName ), e ); Modified: jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/util/ClassUtil.java URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/util/ClassUtil.java?rev=1566717&r1=1566716&r2=1566717&view=diff ============================================================================== --- jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/util/ClassUtil.java (original) +++ jspwiki/trunk/jspwiki-war/src/main/java/org/apache/wiki/util/ClassUtil.java Mon Feb 10 19:49:56 2014 @@ -23,7 +23,9 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.net.JarURLConnection; +import java.net.MalformedURLException; import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; @@ -36,6 +38,8 @@ import java.util.jar.JarFile; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.apache.wiki.WikiEngine; +import org.apache.wiki.api.engine.PluginManager; import org.apache.wiki.api.exceptions.WikiException; import org.jdom2.Element; @@ -56,6 +60,10 @@ public final class ClassUtil { private static Map c_classMappings = new Hashtable(); + private static boolean classLoaderSetup = false; + private static ClassLoader loader = null; + + /** * Initialize the class mappings document. */ @@ -88,23 +96,24 @@ public final class ClassUtil { * attempt to find the class based on just the className parameter, but * should that fail, will iterate through the "packages" -list, prefixes * the package name to the className, and then tries to find the class - * again. If that still fails, we try the old (pre-2.9) com.ecyrd.jspwiki package. + * again. * - * @param packages A List of Strings, containing different package names. + * @param packages A List of Strings, containing different package names. * @param className The name of the class to find. - * @return The class, if it was found. + * @return The class, if it was found. * @throws ClassNotFoundException if this particular class cannot be found * from the list. */ - public static Class findClass( List< String > packages, String className ) throws ClassNotFoundException { - ClassLoader loader = ClassUtil.class.getClassLoader(); + public static Class findClass( List< String > packages, List< String > externaljars, String className ) throws ClassNotFoundException { + if (!classLoaderSetup) { + loader = setupClassLoader(externaljars); + } try { return loader.loadClass( className ); } catch( ClassNotFoundException e ) { for( Iterator< String > i = packages.iterator(); i.hasNext(); ) { String packageName = i.next(); - try { return loader.loadClass( packageName + "." + className ); } catch( ClassNotFoundException ex ) { @@ -112,21 +121,44 @@ public final class ClassUtil { } } - // try the old (pre 2.9) package name for compatibility : - try { - className = className.replaceFirst( "com\\.ecyrd\\.jspwiki", "org.apache.wiki" ); - return loader.loadClass( className ); - } catch( ClassNotFoundException ex ) { - // This is okay, if we fail we throw our own CNFE.. - } - } throw new ClassNotFoundException( "Class '" + className + "' not found in search path!" ); } - + + /** + * Setup the plugin classloader. + * Check if there are external JARS to add via property {@link org.apache.wiki.api.engine.PluginManager#PROP_EXTERNALJARS} + * + * @return the classloader that can load classes from the configured external jars or + * ,if not specified, the classloader that loaded this class. + * @param externaljars + */ + private static ClassLoader setupClassLoader(List externaljars) { + classLoaderSetup = true; + log.info("setting up classloaders for external (plugin) jars"); + if (externaljars.size() == 0) { + log.info("no external jars configured, using standard classloading"); + return ClassUtil.class.getClassLoader(); + } + URL[] urls = new URL[externaljars.size()]; + int i = 0; + try { + for (String externaljar : externaljars) { + File jarFile = new File(externaljar); + URL ucl = jarFile.toURI().toURL(); + urls[i++] = ucl; + log.info("added " + ucl + " to list of external jars"); + } + } catch (MalformedURLException e) { + log.error("exception while setting up classloaders for external jars via property" + PluginManager.PROP_EXTERNALJARS + ", continuing without external jars."); + return ClassUtil.class.getClassLoader(); + } + return new URLClassLoader(urls, ClassUtil.class.getClassLoader()); + } + /** - * A shortcut for findClass when you only have a singular package to search. + * * It will first attempt to instantiate the class directly from the className, * and will then try to prefix it with the packageName. * @@ -136,11 +168,12 @@ public final class ClassUtil { * @throws ClassNotFoundException if this particular class cannot be found. */ - public static Class findClass( String packageName, String className ) throws ClassNotFoundException { - ArrayList list = new ArrayList(); - list.add( packageName ); - - return findClass( list, className ); + public static Class findClass(String packageName, String className) throws ClassNotFoundException { + try { + return ClassUtil.class.getClassLoader().loadClass(className); + } catch (ClassNotFoundException e) { + return ClassUtil.class.getClassLoader().loadClass(packageName + "." + className); + } } /** Modified: jspwiki/trunk/jspwiki-war/src/main/resources/ini/jspwiki.properties URL: http://svn.apache.org/viewvc/jspwiki/trunk/jspwiki-war/src/main/resources/ini/jspwiki.properties?rev=1566717&r1=1566716&r2=1566717&view=diff ============================================================================== --- jspwiki/trunk/jspwiki-war/src/main/resources/ini/jspwiki.properties (original) +++ jspwiki/trunk/jspwiki-war/src/main/resources/ini/jspwiki.properties Mon Feb 10 19:49:56 2014 @@ -392,6 +392,11 @@ jspwiki.specialPage.FindPage = FindPage. # jspwiki.plugin.searchPath = +# You can specify external jars containing plugin classes. These will be added to the classpath +# when plugins are loaded. +# Using this you don't have to put the jars in your WEB-INF/lib directory thereby preventing war-surgery. +jspwiki.plugin.externalJars = + ############################################################################# # # Page filters