You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by ya...@apache.org on 2018/11/16 14:16:57 UTC

[struts] branch struts-2-5-x updated (415ce3e -> 11de881)

This is an automated email from the ASF dual-hosted git repository.

yasserzamani pushed a change to branch struts-2-5-x
in repository https://gitbox.apache.org/repos/asf/struts.git.


    from 415ce3e  Merge pull request #264 from JCgH4164838Gh792C124B5/localS2_2_5_x_Branch
     new 75dc4c0  pass all current tests with java 9
     new 11de881  satisfy coveralls via testing with a not URLClassLoader

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .travis.yml                                        |  1 +
 .../opensymphony/xwork2/util/ClassPathFinder.java  | 33 ++++-----
 .../com/opensymphony/xwork2/ognl/OgnlUtilTest.java | 15 ++++-
 .../xwork2/util/ClassPathFinderTest.java           | 50 +++++++++++++-
 .../test/java/org/apache/struts2/TestUtils.java    | 17 +++++
 .../struts2/jasper/JspCompilationContext.java      |  4 +-
 .../struts2/jasper/compiler/JspRuntimeContext.java | 78 +++++++++++++---------
 .../struts2/jasper/compiler/TagFileProcessor.java  |  3 +-
 .../struts2/jasper/compiler/TldLocationsCache.java | 44 ++++++------
 .../org/apache/struts2/EmbeddedJSPResultTest.java  | 27 ++++++--
 10 files changed, 187 insertions(+), 85 deletions(-)


[struts] 02/02: satisfy coveralls via testing with a not URLClassLoader

Posted by ya...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

yasserzamani pushed a commit to branch struts-2-5-x
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 11de8810e4bd2b4077e357b684a87c6a46e4f242
Author: Yasser Zamani <ya...@apache.org>
AuthorDate: Wed Nov 14 16:39:44 2018 +0330

    satisfy coveralls via testing with a not URLClassLoader
    
    See also WW-4845
    
    (cherry picked from commit 02abab3)
---
 .../xwork2/util/ClassPathFinderTest.java           | 50 +++++++++++++++++++++-
 .../org/apache/struts2/EmbeddedJSPResultTest.java  | 27 +++++++++---
 2 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/core/src/test/java/com/opensymphony/xwork2/util/ClassPathFinderTest.java b/core/src/test/java/com/opensymphony/xwork2/util/ClassPathFinderTest.java
index 0a2d264..34c0bbe 100644
--- a/core/src/test/java/com/opensymphony/xwork2/util/ClassPathFinderTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/util/ClassPathFinderTest.java
@@ -19,11 +19,17 @@
 package com.opensymphony.xwork2.util;
 
 import com.opensymphony.xwork2.XWorkTestCase;
+import org.apache.commons.io.IOUtils;
 
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Vector;
 
 public class ClassPathFinderTest extends XWorkTestCase {
-	
+
 	public void testFinder() {
 		ClassPathFinder finder = new ClassPathFinder();
 		finder.setPattern("**/xwork-test-wildcard-*.xml");
@@ -52,4 +58,46 @@ public class ClassPathFinderTest extends XWorkTestCase {
 		
 	}
 
+    public void testFinderNotURLClassLoader() throws Exception {
+        NotURLClassLoader loader = new NotURLClassLoader(Thread.currentThread().getContextClassLoader());
+        Thread.currentThread().setContextClassLoader(loader);
+
+        Class<?> clazz = loader.loadClass(ClassPathFinderTest.class.getName());
+        Object test = clazz.getConstructor().newInstance();
+
+        clazz.getMethod("testFinder").invoke(test);
+
+        Thread.currentThread().setContextClassLoader(loader.parentClassLoader);
+    }
+
+
+	private class NotURLClassLoader extends ClassLoader {
+        private Map<String, Class<?>> loadedClasses = new HashMap<>();
+        private ClassLoader parentClassLoader;
+
+        NotURLClassLoader(ClassLoader parentClassLoader) {
+            super(null);
+            this.parentClassLoader = parentClassLoader;
+        }
+
+        @Override
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            if (!loadedClasses.containsKey(name)) {
+                try {
+                    byte[] classBits = IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream(
+                            name.replace('.', '/') + ".class"));
+                    loadedClasses.put(name, defineClass(name, classBits, 0, classBits.length));
+                } catch (IOException e) {
+                    throw new ClassNotFoundException("class " + name + " is not findable", e);
+                }
+            }
+
+            return loadedClasses.get(name);
+        }
+
+        @Override
+        protected Enumeration<URL> findResources(String name) throws IOException {
+            return parentClassLoader.getResources(name);
+        }
+    }
 }
diff --git a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java
index ec65539..952cd84 100644
--- a/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java
+++ b/plugins/embeddedjsp/src/test/java/org/apache/struts2/EmbeddedJSPResultTest.java
@@ -31,7 +31,6 @@ import com.opensymphony.xwork2.util.ValueStack;
 import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
 import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate;
 import com.opensymphony.xwork2.util.fs.DefaultFileManager;
-import com.sun.net.httpserver.HttpsParameters;
 import junit.framework.TestCase;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.struts2.dispatcher.HttpParameters;
@@ -46,11 +45,7 @@ import javax.servlet.Servlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.CyclicBarrier;
 
@@ -231,6 +226,19 @@ public class EmbeddedJSPResultTest extends TestCase {
         assertEquals("WhoamI?", StringUtils.deleteWhitespace(response.getContentAsString()));
     }
 
+    public void testNotURLClassLoader() throws Exception {
+        ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();
+        NotURLClassLoader loader = new NotURLClassLoader(parentClassLoader);
+        Thread.currentThread().setContextClassLoader(loader);
+
+        result.setLocation("org/apache/struts2/tag0.jsp");
+        result.execute(null);
+
+        assertEquals("Thissessionisnotsecure.OtherText", StringUtils.deleteWhitespace(response.getContentAsString()));
+
+        Thread.currentThread().setContextClassLoader(parentClassLoader);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
@@ -374,3 +382,10 @@ class CountingClassLoaderInterface extends ClassLoaderInterfaceDelegate {
         return super.getResourceAsStream(name);
     }
 }
+
+class NotURLClassLoader extends ClassLoader {
+
+    NotURLClassLoader(ClassLoader parentClassLoader) {
+        super(parentClassLoader);
+    }
+}


[struts] 01/02: pass all current tests with java 9

Posted by ya...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

yasserzamani pushed a commit to branch struts-2-5-x
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 75dc4c00d20a1bde86897dc73ff5098b91eaf0f0
Author: Yasser Zamani <ya...@apache.org>
AuthorDate: Sun Nov 11 14:31:35 2018 +0330

    pass all current tests with java 9
    
    See also WW-4845
    
    (cherry picked from commit a5d888a)
---
 .travis.yml                                        |  1 +
 .../opensymphony/xwork2/util/ClassPathFinder.java  | 33 ++++-----
 .../com/opensymphony/xwork2/ognl/OgnlUtilTest.java | 15 ++++-
 .../test/java/org/apache/struts2/TestUtils.java    | 17 +++++
 .../struts2/jasper/JspCompilationContext.java      |  4 +-
 .../struts2/jasper/compiler/JspRuntimeContext.java | 78 +++++++++++++---------
 .../struts2/jasper/compiler/TagFileProcessor.java  |  3 +-
 .../struts2/jasper/compiler/TldLocationsCache.java | 44 ++++++------
 8 files changed, 117 insertions(+), 78 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 14daf85..8d98574 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,7 @@ sudo: false
 jdk:
   - openjdk7
   - oraclejdk8
+  - oraclejdk9
 
 install: true
 script: mvn test -DskipAssembly
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java b/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java
index 5188149..5838abd 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java
@@ -27,6 +27,7 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Vector;
 import java.util.zip.ZipEntry;
@@ -77,11 +78,7 @@ public class ClassPathFinder {
      */
 	public Vector<String> findMatches() {
 		Vector<String> matches = new Vector<>();
-		URLClassLoader cl = getURLClassLoader();
-		if (cl == null ) {
-			throw new XWorkException("unable to attain an URLClassLoader") ;
-		}
-		URL[] parentUrls = cl.getURLs();
+		URL[] parentUrls = getClassLoaderURLs();
 		compiledPattern = patternMatcher.compilePattern(pattern);
 		for (URL url : parentUrls) {
 			if (!"file".equals(url.getProtocol())) {
@@ -173,20 +170,24 @@ public class ClassPathFinder {
 		this.patternMatcher = patternMatcher;
 	}
 
-	private URLClassLoader getURLClassLoader() {
-		URLClassLoader ucl = null;
+	private URL[] getClassLoaderURLs() {
+		URL[] urls;
 		ClassLoader loader = Thread.currentThread().getContextClassLoader();
-		
-		if(! (loader instanceof URLClassLoader)) {
+
+		if (!(loader instanceof URLClassLoader)) {
 			loader = ClassPathFinder.class.getClassLoader();
-			if (loader instanceof URLClassLoader) {
-				ucl = (URLClassLoader) loader ;
-			}
 		}
-		else {
-			ucl = (URLClassLoader) loader;
+
+		if (loader instanceof URLClassLoader) {
+			urls = ((URLClassLoader) loader).getURLs();
+		} else {    //jdk9 or later
+			try {
+				urls = Collections.list(loader.getResources("")).toArray(new URL[0]);
+			} catch (IOException e) {
+				throw new XWorkException("unable to get ClassLoader URLs", e);
+			}
 		}
-		
-		return ucl ;
+
+		return urls;
 	}
 }
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
index ca11433..d6372fd 100644
--- a/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
@@ -27,6 +27,7 @@ import com.opensymphony.xwork2.test.User;
 import com.opensymphony.xwork2.util.*;
 import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
 import ognl.*;
+import org.apache.struts2.TestUtils;
 
 import java.lang.reflect.Method;
 import java.util.*;
@@ -374,8 +375,18 @@ public class OgnlUtilTest extends XWorkTestCase {
         assertEquals(cal.getTime(), foo.getBirthday());
         
         //UK style test
-        props.put("event", "18/10/2006 14:23:45");
-        props.put("meeting", "09/09/2006 14:30");
+        if (TestUtils.isJdk9OrLater()) {
+            /* In JDK 9 and later, the default locale data uses data derived from the
+            Unicode Consortium's Common Locale Data Repository (CLDR). The short date-time format is ‹{1}, {0}› in the
+            CLDR locale, as opposed to {1} {0} in the JRE locale data.
+            Please refer : http://www.oracle.com/technetwork/java/javase/9-relnote-issues-3704069.html#JDK-8008577 */
+            props.put("event", "18/10/2006, 14:23:45");
+            props.put("meeting", "09/09/2006, 14:30");
+        }
+        else {
+            props.put("event", "18/10/2006 14:23:45");
+            props.put("meeting", "09/09/2006 14:30");
+        }
         context.put(ActionContext.LOCALE, Locale.UK);
 
         ognlUtil.setProperties(props, foo, context);
diff --git a/core/src/test/java/org/apache/struts2/TestUtils.java b/core/src/test/java/org/apache/struts2/TestUtils.java
index 88789e1..111cd89 100644
--- a/core/src/test/java/org/apache/struts2/TestUtils.java
+++ b/core/src/test/java/org/apache/struts2/TestUtils.java
@@ -20,6 +20,7 @@ package org.apache.struts2;
 
 import java.io.InputStream;
 import java.net.URL;
+import java.net.URLClassLoader;
 import java.util.StringTokenizer;
 
 /**
@@ -90,4 +91,20 @@ public class TestUtils {
 
         return buffer.toString();
     }
+
+    public static boolean isJdk9OrLater() {
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+        if(loader instanceof URLClassLoader) {
+            return false;
+        }
+
+        loader = TestUtils.class.getClassLoader();
+
+        if(loader instanceof URLClassLoader) {
+            return false;
+        }
+
+        return true;
+    }
 }
diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/JspCompilationContext.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/JspCompilationContext.java
index a8fbb60..b0bb32c 100644
--- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/JspCompilationContext.java
+++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/JspCompilationContext.java
@@ -80,7 +80,7 @@ public class JspCompilationContext {
     protected String baseURI;
     protected String outputDir;
     protected ServletContext context;
-    protected URLClassLoader loader;
+    protected ClassLoader loader;
 
     protected JspRuntimeContext rctxt;
 
@@ -177,7 +177,7 @@ public class JspCompilationContext {
         return rctxt.getParentClassLoader();
     }
 
-    public void setClassLoader(URLClassLoader loader) {
+    public void setClassLoader(ClassLoader loader) {
         this.loader = loader;
     }
 
diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/JspRuntimeContext.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/JspRuntimeContext.java
index b2316b5..e9698e2 100644
--- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/JspRuntimeContext.java
+++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/JspRuntimeContext.java
@@ -33,12 +33,14 @@ import javax.servlet.jsp.JspFactory;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FilePermission;
+import java.io.IOException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.security.CodeSource;
 import java.security.PermissionCollection;
 import java.security.Policy;
 import java.security.cert.Certificate;
+import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -121,11 +123,9 @@ public final class JspRuntimeContext {
         this.options = options;
 
         // Get the parent class loader
-        parentClassLoader =
-                (URLClassLoader) Thread.currentThread().getContextClassLoader();
+        parentClassLoader = Thread.currentThread().getContextClassLoader();
         if (parentClassLoader == null) {
-            parentClassLoader =
-                    (URLClassLoader) this.getClass().getClassLoader();
+            parentClassLoader = this.getClass().getClassLoader();
         }
 
         if (log.isDebugEnabled()) {
@@ -138,7 +138,11 @@ public final class JspRuntimeContext {
             }
         }
 
-        initClassPath();
+        try {
+            initClassPath();
+        } catch (IOException e) {
+            context.log("ClassPath Init for context failed", e);
+        }
 
         if (context instanceof JspCServletContext) {
             return;
@@ -165,7 +169,7 @@ public final class JspRuntimeContext {
      */
     private ServletContext context;
     private Options options;
-    private URLClassLoader parentClassLoader;
+    private ClassLoader parentClassLoader;
     private PermissionCollection permissionCollection;
     private CodeSource codeSource;
     private String classpath;
@@ -233,7 +237,7 @@ public final class JspRuntimeContext {
      *
      * @return URLClassLoader parent
      */
-    public URLClassLoader getParentClassLoader() {
+    public ClassLoader getParentClassLoader() {
         return parentClassLoader;
     }
 
@@ -333,9 +337,14 @@ public final class JspRuntimeContext {
     /**
      * Method used to initialize classpath for compiles.
      */
-    private void initClassPath() {
+    private void initClassPath() throws IOException {
 
-        URL[] urls = parentClassLoader.getURLs();
+        URL[] urls;
+        if (parentClassLoader instanceof URLClassLoader) {
+            urls = ((URLClassLoader) parentClassLoader).getURLs();
+        } else {    //jdk9 or later
+            urls = Collections.list(parentClassLoader.getResources("")).toArray(new URL[0]);
+        }
         StringBuffer cpath = new StringBuffer();
         String sep = System.getProperty("path.separator");
 
@@ -418,34 +427,37 @@ public final class JspRuntimeContext {
                 permissionCollection.add(new RuntimePermission(
                         "accessClassInPackage.org.apache.struts2.jasper.runtime"));
 
+                URL[] urls;
                 if (parentClassLoader instanceof URLClassLoader) {
-                    URL[] urls = parentClassLoader.getURLs();
-                    String jarUrl = null;
-                    String jndiUrl = null;
-                    for (int i = 0; i < urls.length; i++) {
-                        if (jndiUrl == null
-                                && urls[i].toString().startsWith("jndi:")) {
-                            jndiUrl = urls[i].toString() + "-";
-                        }
-                        if (jarUrl == null
-                                && urls[i].toString().startsWith("jar:jndi:")
-                                ) {
-                            jarUrl = urls[i].toString();
-                            jarUrl = jarUrl.substring(0, jarUrl.length() - 2);
-                            jarUrl = jarUrl.substring(0,
-                                    jarUrl.lastIndexOf('/')) + "/-";
-                        }
+                    urls = ((URLClassLoader) parentClassLoader).getURLs();
+                } else {    //jdk9 or later
+                    urls = Collections.list(parentClassLoader.getResources("")).toArray(new URL[0]);
+                }
+                String jarUrl = null;
+                String jndiUrl = null;
+                for (URL url1 : urls) {
+                    if (jndiUrl == null
+                            && url1.toString().startsWith("jndi:")) {
+                        jndiUrl = url1.toString() + "-";
                     }
-                    if (jarUrl != null) {
-                        permissionCollection.add(
-                                new FilePermission(jarUrl, "read"));
-                        permissionCollection.add(
-                                new FilePermission(jarUrl.substring(4), "read"));
+                    if (jarUrl == null
+                            && url1.toString().startsWith("jar:jndi:")
+                            ) {
+                        jarUrl = url1.toString();
+                        jarUrl = jarUrl.substring(0, jarUrl.length() - 2);
+                        jarUrl = jarUrl.substring(0,
+                                jarUrl.lastIndexOf('/')) + "/-";
                     }
-                    if (jndiUrl != null)
-                        permissionCollection.add(
-                                new FilePermission(jndiUrl, "read"));
                 }
+                if (jarUrl != null) {
+                    permissionCollection.add(
+                            new FilePermission(jarUrl, "read"));
+                    permissionCollection.add(
+                            new FilePermission(jarUrl.substring(4), "read"));
+                }
+                if (jndiUrl != null)
+                    permissionCollection.add(
+                            new FilePermission(jndiUrl, "read"));
             } catch (Exception e) {
                 context.log("Security Init for context failed", e);
             }
diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagFileProcessor.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagFileProcessor.java
index 5f3d13a..bbf2417 100644
--- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagFileProcessor.java
+++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TagFileProcessor.java
@@ -594,8 +594,7 @@ class TagFileProcessor {
                 rctxt.addWrapper(tagFileJarPath + tagFilePath, wrapper);
 
                 // Use same classloader and classpath for compiling tag files
-                wrapper.getJspEngineContext().setClassLoader(
-                        (URLClassLoader) ctxt.getClassLoader());
+                wrapper.getJspEngineContext().setClassLoader(ctxt.getClassLoader());
                 wrapper.getJspEngineContext().setClassPath(ctxt.getClassPath());
             } else {
                 // Make sure that JspCompilationContext gets the latest TagInfo
diff --git a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TldLocationsCache.java b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TldLocationsCache.java
index 0bac6fa..a8a26be 100644
--- a/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TldLocationsCache.java
+++ b/plugins/embeddedjsp/src/main/java/org/apache/struts2/jasper/compiler/TldLocationsCache.java
@@ -25,12 +25,7 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.net.URLConnection;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.StringTokenizer;
+import java.util.*;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import org.xml.sax.InputSource;
@@ -508,24 +503,27 @@ public class TldLocationsCache {
         ClassLoader loader = webappLoader;
 
         while (loader != null) {
+            URL[] urls;
             if (loader instanceof URLClassLoader) {
-                URL[] urls = ((URLClassLoader) loader).getURLs();
-                for (int i=0; i<urls.length; i++) {
-                    URLConnection conn = urls[i].openConnection();
-                    if (conn instanceof JarURLConnection) {
-                        if (needScanJar(loader, webappLoader,
-                                        ((JarURLConnection) conn).getJarFile().getName())) {
-                            scanJar((JarURLConnection) conn, true);
-                        }
-                    } else {
-                        String urlStr = urls[i].toString();
-                        if (urlStr.startsWith(FILE_PROTOCOL)
-                                && urlStr.endsWith(JAR_FILE_SUFFIX)
-                                && needScanJar(loader, webappLoader, urlStr)) {
-                            URL jarURL = new URL("jar:" + urlStr + "!/");
-                            scanJar((JarURLConnection) jarURL.openConnection(),
-                                    true);
-                        }
+                urls = ((URLClassLoader) loader).getURLs();
+            } else {    //jdk9 or later
+                urls = Collections.list(loader.getResources("")).toArray(new URL[0]);
+            }
+            for (URL url : urls) {
+                URLConnection conn = url.openConnection();
+                if (conn instanceof JarURLConnection) {
+                    if (needScanJar(loader, webappLoader,
+                            ((JarURLConnection) conn).getJarFile().getName())) {
+                        scanJar((JarURLConnection) conn, true);
+                    }
+                } else {
+                    String urlStr = url.toString();
+                    if (urlStr.startsWith(FILE_PROTOCOL)
+                            && urlStr.endsWith(JAR_FILE_SUFFIX)
+                            && needScanJar(loader, webappLoader, urlStr)) {
+                        URL jarURL = new URL("jar:" + urlStr + "!/");
+                        scanJar((JarURLConnection) jarURL.openConnection(),
+                                true);
                     }
                 }
             }