You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-user@logging.apache.org by Al...@materna.de on 2013/10/24 15:53:51 UTC

Log4J2 with custom Plugins and Java Web Start

Hi,
I've got an Application that is deployed via Java Web Start.
I also have custom @Plugin(s) i.e. a LogEventPatternConverter. Log4j2 picks the packages directive of the config but fails to collect the plugins when started via Web Start.


2013-10-24 13:49:29,617 DEBUG Found Plugin Map at jar:https://myserver.mydomain/lib/thirdparty/log4j-core-2.0-beta9.jar.pack.gz!/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
2013-10-24 13:49:29,619 INFO Scanning for classes in [https://myserver.mydomain/lib/myjarname.jar.pack.gz] matching criteria: annotated with @Plugin
2013-10-24 13:49:29,620 ERROR Could not search jar file 'https:\myserver.mydomain\lib\myjarname.jar.pack.gz ' for classes matching criteria: annotated with @Plugin file not found
2013-10-24 13:49:29,620 DEBUG Generated plugins in 0.004778509 seconds

This is caused by ResolverUtil.findInPackage(Test, String) calling loadImplementationsInJar(Test, String, File) which tries to construct a FileInputStream - which will obviously fail for a https url.

Am I missing something or is this a bug?

Best Regards,
Alex



AW: Log4J2 with custom Plugins and Java Web Start

Posted by Al...@materna.de.
Hi again,

this is all I could come up with.
I can't find another way but reflection atm.
This is so ugly. But it works.

Your thoughts on this?

Index: src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java
===================================================================
--- src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java	(revision 1533024)
+++ src/main/java/org/apache/logging/log4j/core/config/plugins/ResolverUtil.java	(working copy)
@@ -21,6 +21,8 @@
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLDecoder;
@@ -210,8 +212,9 @@
         for (final String pkg : packageNames) {
             findInPackage(test, pkg);
         }
-    }
+	}
 
+
     /**
      * Scans for classes starting at the package provided and descending into subpackages.
      * Each class is offered up to the Test as it is discovered, and if the Test returns
@@ -265,6 +268,9 @@
                 } else if (BUNDLE_RESOURCE.equals(url.getProtocol())) {
                     loadImplementationsInBundle(test, packageName);
                 } else {
+    				if(urlPath.startsWith("http:") || urlPath.startsWith("https:")) {
+    					urlPath = tryLookupCachedJar(urlPath);
+    				}
                     final File file = new File(urlPath);
                     if (file.isDirectory()) {
                         loadImplementationsInDirectory(test, packageName, file);
@@ -429,6 +435,103 @@
         }
     }
 
+
+	/**
+	 * Tries to lookup the locally cached path for a resource using reflection (sorry).
+	 * Should work in Java Web Start environments and gracefully return the given path unaltered in any other case.
+	 * 
+	 * @param urlPath the path to the resource that should be looked up
+	 * @return the path to the cached resource if found, the supplied <code>urlPath</code> otherwise.
+	 */
+	private String tryLookupCachedJar(String urlPath) {
+		LOGGER.debug("Will try to lookup cached resource for {}", urlPath);
+		Class<?> cacheClass = null;
+		try {
+			cacheClass = ClassLoader.getSystemClassLoader().loadClass("com.sun.deploy.cache.Cache");
+		}
+		catch( ClassNotFoundException ex ) {
+			LOGGER.debug("Could not load JWS Cache class {}", ex.getMessage());
+		}
+		if( cacheClass == null ) {
+			return urlPath;
+		}
+
+		java.lang.reflect.Method getCacheEntry = null;
+		try {
+			getCacheEntry = cacheClass.getMethod("getCacheEntry", java.net.URL.class, String.class);
+		}
+		catch( NoSuchMethodException ex ) {
+			LOGGER.debug("Could not lookup getCacheEntry method {}", ex.getMessage());
+		}
+		catch( SecurityException ex ) {
+			LOGGER.debug("Could not lookup getCacheEntry method {}", ex.getMessage());
+		}
+		if( getCacheEntry == null ) {
+			return urlPath;
+		}
+		
+		Object cacheEntry = null;
+		try {
+			cacheEntry = getCacheEntry.invoke(null, new URL(urlPath), null);
+		}
+		catch( IllegalAccessException ex ) {
+			LOGGER.debug("Could not invoke getCacheEntry method {}", ex.getMessage());
+		}
+		catch( IllegalArgumentException ex ) {
+			LOGGER.debug("Could not invoke getCacheEntry method {}", ex.getMessage());
+		}
+		catch( InvocationTargetException ex ) {
+			LOGGER.debug("Could not invoke getCacheEntry method {}", ex.getMessage());
+		}
+		catch( MalformedURLException ex ) {
+			LOGGER.debug("Could not invoke getCacheEntry method {}", ex.getMessage());
+		}
+		if( cacheEntry == null ) {
+			return urlPath;
+		}
+
+		Class<?> ce = null;
+		try {
+			ce = ClassLoader.getSystemClassLoader().loadClass("com.sun.deploy.cache.CacheEntry");
+		}
+		catch( ClassNotFoundException ex ) {
+			LOGGER.debug("Could not load JWS CacheEntry class {}", ex.getMessage());
+		}
+		if( ce == null ) {
+			return urlPath;
+		}
+		
+		java.lang.reflect.Method getResourceFilename = null;
+		try {
+			getResourceFilename = ce.getMethod("getResourceFilename");
+		}
+		catch( NoSuchMethodException ex ) {
+			LOGGER.debug("Could not lookup getResourceFilename method {}", ex.getMessage());
+		}
+		catch( SecurityException ex ) {
+			LOGGER.debug("Could not lookup getResourceFilename method {}", ex.getMessage());
+		}
+		if( getResourceFilename == null ) {
+			return urlPath;
+		}
+		
+		try {
+			String cachedPath = (String)getResourceFilename.invoke(cacheEntry);
+			LOGGER.debug("Found cached resource: {}", cachedPath);
+			return cachedPath;
+		}
+		catch( IllegalAccessException ex ) {
+			LOGGER.debug("Could not invoke getResourceFilename method {}", ex.getMessage());
+		}
+		catch( IllegalArgumentException ex ) {
+			LOGGER.debug("Could not invoke getResourceFilename method {}", ex.getMessage());
+		}
+		catch( InvocationTargetException ex ) {
+			LOGGER.debug("Could not invoke getResourceFilename method {}", ex.getMessage());
+		}
+		return urlPath;
+	}
+
     /**
      * A simple interface that specifies how to test classes to determine if they
      * are to be included in the results produced by the ResolverUtil.

Best Regards,
Alex

-----Ursprüngliche Nachricht-----
Von: Rathai, Alexander 
Gesendet: Donnerstag, 24. Oktober 2013 15:54
An: log4j-user@logging.apache.org
Betreff: Log4J2 with custom Plugins and Java Web Start

Hi,
I've got an Application that is deployed via Java Web Start.
I also have custom @Plugin(s) i.e. a LogEventPatternConverter. Log4j2 picks the packages directive of the config but fails to collect the plugins when started via Web Start.


2013-10-24 13:49:29,617 DEBUG Found Plugin Map at jar:https://myserver.mydomain/lib/thirdparty/log4j-core-2.0-beta9.jar.pack.gz!/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat
2013-10-24 13:49:29,619 INFO Scanning for classes in [https://myserver.mydomain/lib/myjarname.jar.pack.gz] matching criteria: annotated with @Plugin
2013-10-24 13:49:29,620 ERROR Could not search jar file 'https:\myserver.mydomain\lib\myjarname.jar.pack.gz ' for classes matching criteria: annotated with @Plugin file not found
2013-10-24 13:49:29,620 DEBUG Generated plugins in 0.004778509 seconds

This is caused by ResolverUtil.findInPackage(Test, String) calling loadImplementationsInJar(Test, String, File) which tries to construct a FileInputStream - which will obviously fail for a https url.

Am I missing something or is this a bug?

Best Regards,
Alex



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org