You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by me...@apache.org on 2014/02/10 20:49:57 UTC
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/...
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 {
* <p>
* 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<String> m_searchPath = new ArrayList<String>();
+ private ArrayList<String> m_searchPath = new ArrayList<String>();
+
+ private ArrayList<String> m_externalJars = new ArrayList<String>();
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<String> searchPath, List<String> 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<String> searchPath, List<String> 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<String> searchPath, List<String> 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<String, String> c_classMappings = new Hashtable<String, String>();
+ 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<String> 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<String> list = new ArrayList<String>();
- 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