Issue #1448 - Reduce unncessary URL creation

This commit is contained in:
Joakim Erdfelt 2017-04-04 09:08:44 -07:00
parent c285d6f8bb
commit f53776628f
4 changed files with 203 additions and 8 deletions

View File

@ -34,8 +34,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.servlet.ServletContainerInitializer;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -723,7 +721,7 @@ public class TypeUtil
{
try
{
return Resource.newResource(URIUtil.getJarSource(url.toString()));
return Resource.newResource(URIUtil.getJarSource(url.toURI()));
}
catch(Exception e)
{

View File

@ -0,0 +1,78 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.webapp;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLStreamHandlerFactory;
import java.util.Arrays;
import java.util.Optional;
public final class URLStreamHandlerUtil
{
public static void setFactory(URLStreamHandlerFactory factory)
{
try
{
// First, reset the factory field
Field factoryField = getURLStreamHandlerFactoryField();
factoryField.setAccessible(true);
factoryField.set(null, null);
if(factory != null)
{
// Next, set the factory
URL.setURLStreamHandlerFactory(factory);
}
}
catch(Throwable ignore)
{
ignore.printStackTrace(System.err);
}
}
public static URLStreamHandlerFactory getFactory()
{
try
{
// First, reset the factory field
Field factoryField = getURLStreamHandlerFactoryField();
factoryField.setAccessible(true);
return (URLStreamHandlerFactory) factoryField.get(null);
}
catch(Throwable ignore)
{
return null;
}
}
private static Field getURLStreamHandlerFactoryField()
{
Optional<Field> optFactoryField = Arrays.stream(URL.class.getDeclaredFields())
.filter((f) -> Modifier.isStatic(f.getModifiers()) &&
f.getType().equals(URLStreamHandlerFactory.class))
.findFirst();
if(optFactoryField.isPresent())
return optFactoryField.get();
throw new RuntimeException( "Cannot find URLStreamHandlerFactory field in " + URL.class.getName() );
}
}

View File

@ -18,15 +18,18 @@
package org.eclipse.jetty.webapp;
import static org.eclipse.jetty.toolchain.test.ExtraMatchers.*;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.eclipse.jetty.toolchain.test.ExtraMatchers.ordered;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.security.ProtectionDomain;
import java.util.ArrayList;
@ -48,7 +51,7 @@ public class WebAppClassLoaderTest
private Path testWebappDir;
private WebAppContext _context;
private WebAppClassLoader _loader;
protected WebAppClassLoader _loader;
@Before
public void init() throws Exception
@ -241,6 +244,9 @@ public class WebAppClassLoaderTest
@Test
public void testResources() throws Exception
{
// The existence of a URLStreamHandler changes the behavior
assumeThat("No URLStreamHandler in place", URLStreamHandlerUtil.getFactory(), nullValue());
List<URL> expected = new ArrayList<>();
List<URL> resources;

View File

@ -0,0 +1,113 @@
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.webapp;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.util.HashMap;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
public class WebAppClassLoaderUrlStreamTest extends WebAppClassLoaderTest
{
public static class URLHandlers implements URLStreamHandlerFactory
{
private static final String[] STREAM_HANDLER_PREFIXES;
static
{
STREAM_HANDLER_PREFIXES = new String[]{
"sun.net.www.protocol",
"org.apache.harmony.luni.internal.net.www.protocol",
"javax.net.ssl"
};
}
private Map<String, URLStreamHandler> handlers = new HashMap<>();
private ClassLoader loader;
public URLHandlers(ClassLoader loader)
{
this.loader = loader;
}
private URLStreamHandler getBuiltInHandler(String protocol, ClassLoader classLoader)
{
URLStreamHandler handler = handlers.get(protocol);
if (handler == null)
{
for (String prefix : STREAM_HANDLER_PREFIXES)
{
String className = prefix + '.' + protocol + ".Handler";
try
{
Class<?> clazz = Class.forName(className, false, classLoader);
handler = (URLStreamHandler) clazz.newInstance();
break;
}
catch (Exception ignore)
{
ignore.printStackTrace(System.err);
}
}
if (handler != null)
{
handlers.put(protocol, handler);
}
}
if (handler == null)
{
throw new RuntimeException("Unable to find handler for protocol [" + protocol + "]");
}
return handler;
}
@Override
public URLStreamHandler createURLStreamHandler(String protocol)
{
try
{
return getBuiltInHandler(protocol, loader);
}
catch (Exception e)
{
throw new RuntimeException("Unable to create URLStreamHandler for protocol [" + protocol + "]");
}
}
}
@After
public void cleanupURLStreamHandlerFactory()
{
URLStreamHandlerUtil.setFactory(null);
}
@Before
public void init() throws Exception
{
super.init();
URLStreamHandlerUtil.setFactory(new URLHandlers(_loader));
}
}