Bug 59274

Summary: web-fragment.xml ordering broken with unpackWARs="false" (MalformedURLException: no !/ in spec)
Product: Tomcat 8 Reporter: Thomas Meyer <thomas>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED DUPLICATE    
Severity: normal    
Priority: P2    
Version: 8.0.28   
Target Milestone: ----   
Hardware: PC   
OS: All   

Description Thomas Meyer 2016-04-05 12:01:18 UTC
Hi,

when using web-fragment.xml to define a order between JARs inside a WAR file and when running Tomcat with unpackWARs="false" the container fails with an MalformedURLException. Stack trace is:
Daemon Thread [localhost-startStop-1] (Suspended (exception MalformedURLException))	
	owns: ContextConfig  (id=65)	
	owns: StandardContext  (id=66)	
	URL.<init>(URL, String, URLStreamHandler) line: 622	
	URL.<init>(URL, String) line: 483	
	URL.<init>(String) line: 432	
	JarURLConnection(JarURLConnection).parseSpecs(URL) line: 175	
	JarURLConnection(JarURLConnection).<init>(URL) line: 158	
	JarURLConnection.<init>(URL, Handler) line: 81	
	Handler.openConnection(URL) line: 41	
	URL.openConnection() line: 972	
	URL.openStream() line: 1038	
	WebappServiceLoader<T>.parseConfigFile(LinkedHashSet<String>, URL) line: 161	
	WebappServiceLoader<T>.load(Class<T>) line: 118	
	ContextConfig.processServletContainerInitializers() line: 1616	
	ContextConfig.webConfig() line: 1128	
	ContextConfig.configureStart() line: 771	
	ContextConfig.lifecycleEvent(LifecycleEvent) line: 305	
	LifecycleSupport.fireLifecycleEvent(String, Object) line: 95	
	StandardContext(LifecycleBase).fireLifecycleEvent(String, Object) line: 90	
	StandardContext.startInternal() line: 5080	
	StandardContext(LifecycleBase).start() line: 150	
	StandardHost(ContainerBase).addChildInternal(Container) line: 725	
	StandardHost(ContainerBase).addChild(Container) line: 701	
	StandardHost.addChild(Container) line: 717	
	HostConfig.deployWAR(ContextName, File) line: 945	
	HostConfig$DeployWar.run() line: 1798	
	Executors$RunnableAdapter<T>.call() line: 511	
	FutureTask<V>.run() line: 266	
	ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1142	
	ThreadPoolExecutor$Worker.run() line: 617	
	Thread.run() line: 745	

The problem seems to be in class WebappServiceLoader which has this flawed logic in the load() method:
                String base = jarUrl.toExternalForm();
                URL url;
                if (base.endsWith("/")) {
                    url = new URL(base + configFile);
                } else {
                    url = new URL("jar:" + base + "!/" + configFile);
                }

I think the problem is that when running in unpackWARs="false" the base URL can be something like this:
jar:file:/path/to/tomcat/installation/webapps/webapp.war!/WEB-INF/lib/library-file.jar

it then adds another jar: infront of the URL resulting in a URL of:
jar:jar:file:/path/to/tomcat/installation/webapps/webapp.war!/WEB-INF/lib/library-file.jar

which cannot be parsed be the URL class:
java.net.MalformedURLException: no !/ in spec

I think this bug was introduced in commit 646bba33e0e269a2c1ffa03d92da3aea3a36d95a ( Fix for https://issues.apache.org/bugzilla/show_bug.cgi?id=55287 )

When running with unpackWARs="true" the web-fragment.xml ordering is correctly processed.
Comment 1 Violeta Georgieva 2016-04-05 12:08:08 UTC

*** This bug has been marked as a duplicate of bug 58490 ***