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