327725 Nested ResourceCaches
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2345 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
a6df844fa7
commit
e3fe523cc7
|
@ -9,6 +9,7 @@ jetty-7.2.0.RC1-SNAPSHOT
|
||||||
+ 327469 removed needless java6 dependencies
|
+ 327469 removed needless java6 dependencies
|
||||||
+ 327562 Implement all X-Forwarded headers in ProxyServlet
|
+ 327562 Implement all X-Forwarded headers in ProxyServlet
|
||||||
+ 327601 Multipart Filter handles quoted tokens
|
+ 327601 Multipart Filter handles quoted tokens
|
||||||
|
+ 327725 Nested ResourceCaches
|
||||||
+ JETTY-1288 Info statement when atypical classloader set on WebAppContext
|
+ JETTY-1288 Info statement when atypical classloader set on WebAppContext
|
||||||
|
|
||||||
jetty-7.2.0.RC0 1 Oct 2010
|
jetty-7.2.0.RC0 1 Oct 2010
|
||||||
|
|
|
@ -1,121 +0,0 @@
|
||||||
package org.eclipse.jetty.deploy;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.webapp.ClasspathPattern;
|
|
||||||
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
|
||||||
|
|
||||||
public class CloudLoader extends URLClassLoader
|
|
||||||
{
|
|
||||||
final WebAppClassLoader _parent;
|
|
||||||
ClasspathPattern _localPaths = new ClasspathPattern();
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public CloudLoader(WebAppClassLoader parent)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
super(parent.getURLs(),parent);
|
|
||||||
_parent=parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Add a local class pattern
|
|
||||||
* <p>Add a pattern as defined by {@link ClasspathPattern}.
|
|
||||||
*/
|
|
||||||
public void addPattern(String pattern)
|
|
||||||
{
|
|
||||||
_localPaths.addPattern(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public boolean isLocal(String name)
|
|
||||||
{
|
|
||||||
return _localPaths.match(name) && !_parent.getContext().isSystemClass(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public Enumeration<URL> getResources(String name) throws IOException
|
|
||||||
{
|
|
||||||
return isLocal(name)?findResources(name):_parent.getResources(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public URL getResource(String name)
|
|
||||||
{
|
|
||||||
if (isLocal(name))
|
|
||||||
{
|
|
||||||
URL url= this.findResource(name);
|
|
||||||
|
|
||||||
if (url == null && name.startsWith("/"))
|
|
||||||
{
|
|
||||||
if (Log.isDebugEnabled())
|
|
||||||
Log.debug("HACK leading / off " + name);
|
|
||||||
url= this.findResource(name.substring(1));
|
|
||||||
}
|
|
||||||
if (url!=null)
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
return _parent.getResource(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
|
|
||||||
{
|
|
||||||
Class<?> c= findLoadedClass(name);
|
|
||||||
|
|
||||||
if (c==null && isLocal(name))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
c= this.findClass(name);
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException e)
|
|
||||||
{
|
|
||||||
Log.ignore(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == null)
|
|
||||||
c= _parent.loadClass(name);
|
|
||||||
|
|
||||||
if (resolve)
|
|
||||||
resolveClass(c);
|
|
||||||
|
|
||||||
if (Log.isDebugEnabled())
|
|
||||||
Log.debug("loaded " + c+ " from "+c.getClassLoader());
|
|
||||||
|
|
||||||
// if loaded from direct parent, then scan for non final statics
|
|
||||||
// look for non final static fields
|
|
||||||
boolean has_non_final_static_fields=false;
|
|
||||||
for (Field field : c.getDeclaredFields())
|
|
||||||
{
|
|
||||||
int mods = field.getModifiers();
|
|
||||||
if (Modifier.isStatic(mods) && !Modifier.isFinal(mods))
|
|
||||||
{
|
|
||||||
has_non_final_static_fields=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (has_non_final_static_fields)
|
|
||||||
{
|
|
||||||
if (c.getClassLoader()==_parent)
|
|
||||||
Log.warn(name+" loaded from "+c.getClassLoader()+" has non-final static fields");
|
|
||||||
else
|
|
||||||
Log.debug(name+" loaded from "+c.getClassLoader()+" has non-final static fields");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,259 +0,0 @@
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 2006-2009 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.deploy;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.security.PermissionCollection;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
|
||||||
import org.eclipse.jetty.io.RuntimeIOException;
|
|
||||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
|
||||||
import org.eclipse.jetty.security.HashLoginService;
|
|
||||||
import org.eclipse.jetty.server.Handler;
|
|
||||||
import org.eclipse.jetty.server.NCSARequestLog;
|
|
||||||
import org.eclipse.jetty.server.ResourceCache;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
|
||||||
import org.eclipse.jetty.server.handler.DefaultHandler;
|
|
||||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
|
||||||
import org.eclipse.jetty.server.handler.RequestLogHandler;
|
|
||||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
|
||||||
import org.eclipse.jetty.util.IO;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.StdErrLog;
|
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
|
||||||
import org.eclipse.jetty.util.resource.ResourceFactory;
|
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|
||||||
import org.eclipse.jetty.webapp.ClasspathPattern;
|
|
||||||
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
|
||||||
import org.eclipse.jetty.webapp.WebAppContext;
|
|
||||||
|
|
||||||
public class CloudServer
|
|
||||||
{
|
|
||||||
public static void main(String[] args) throws Exception
|
|
||||||
{
|
|
||||||
Log.getLog().setDebugEnabled(false);
|
|
||||||
((StdErrLog)Log.getLog()).setSource(false);
|
|
||||||
|
|
||||||
String jetty_root = "..";
|
|
||||||
|
|
||||||
Server server = new Server();
|
|
||||||
server.setSendDateHeader(true);
|
|
||||||
|
|
||||||
// Setup JMX
|
|
||||||
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
|
||||||
server.getContainer().addEventListener(mbContainer);
|
|
||||||
server.addBean(mbContainer);
|
|
||||||
mbContainer.addBean(Log.getLog());
|
|
||||||
|
|
||||||
// Setup Threadpool
|
|
||||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
|
||||||
threadPool.setMaxThreads(100);
|
|
||||||
server.setThreadPool(threadPool);
|
|
||||||
|
|
||||||
// Setup Connectors
|
|
||||||
SelectChannelConnector connector0 = new SelectChannelConnector();
|
|
||||||
connector0.setPort(8080);
|
|
||||||
connector0.setMaxIdleTime(30000);
|
|
||||||
connector0.setConfidentialPort(8443);
|
|
||||||
connector0.setUseDirectBuffers(true);
|
|
||||||
server.addConnector(connector0);
|
|
||||||
|
|
||||||
HandlerCollection handlers = new HandlerCollection();
|
|
||||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
|
||||||
RequestLogHandler requestLogHandler = new RequestLogHandler();
|
|
||||||
handlers.setHandlers(new Handler[]
|
|
||||||
{ contexts, new DefaultHandler(), requestLogHandler });
|
|
||||||
server.setHandler(handlers);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HashLoginService login = new HashLoginService();
|
|
||||||
login.setName("Test Realm");
|
|
||||||
login.setConfig(jetty_root + "/test-jetty-webapp/src/main/config/etc/realm.properties");
|
|
||||||
server.addBean(login);
|
|
||||||
|
|
||||||
File log=File.createTempFile("jetty-yyyy_mm_dd-", ".log");
|
|
||||||
NCSARequestLog requestLog = new NCSARequestLog(log.toString());
|
|
||||||
requestLog.setExtended(false);
|
|
||||||
requestLogHandler.setRequestLog(requestLog);
|
|
||||||
|
|
||||||
server.setStopAtShutdown(true);
|
|
||||||
server.setSendServerVersion(true);
|
|
||||||
|
|
||||||
|
|
||||||
final Resource baseResource= Resource.newResource("../test-jetty-webapp/src/main/webapp");
|
|
||||||
|
|
||||||
ResourceFactory resources = new ResourceFactory()
|
|
||||||
{
|
|
||||||
public Resource getResource(String path)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return baseResource.addPath(path);
|
|
||||||
}
|
|
||||||
catch(IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeIOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WebAppClassLoader.Context loaderContext = new WebAppClassLoader.Context()
|
|
||||||
{
|
|
||||||
private ClasspathPattern _systemClasses = new ClasspathPattern(WebAppContext.__dftSystemClasses);
|
|
||||||
private ClasspathPattern _serverClasses = new ClasspathPattern(WebAppContext.__dftServerClasses);
|
|
||||||
|
|
||||||
public Resource newResource(String urlOrPath) throws IOException
|
|
||||||
{
|
|
||||||
return Resource.newResource(urlOrPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PermissionCollection getPermissions()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSystemClass(String clazz)
|
|
||||||
{
|
|
||||||
return _systemClasses.match(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isServerClass(String clazz)
|
|
||||||
{
|
|
||||||
return _serverClasses.match(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isParentLoaderPriority()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getExtraClasspath()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WebAppClassLoader loader = new WebAppClassLoader(loaderContext);
|
|
||||||
loader.setName("template");
|
|
||||||
loader.addClassPath("../test-jetty-webapp/target/classes");
|
|
||||||
loader.addJars(Resource.newResource("../test-jetty-webapp/target/test-jetty-webapp-7.2.0-SNAPSHOT/WEB-INF/lib"));
|
|
||||||
|
|
||||||
|
|
||||||
// Non cloud deployment first
|
|
||||||
for (int i=0;i<10;i++)
|
|
||||||
{
|
|
||||||
final WebAppContext webapp= new WebAppContext();
|
|
||||||
webapp.setWar("../test-jetty-webapp/target/test-jetty-webapp-7.2.0-SNAPSHOT.war");
|
|
||||||
webapp.setAttribute("instance",i);
|
|
||||||
|
|
||||||
if (i>0)
|
|
||||||
webapp.setVirtualHosts(new String[] {"127.0.0."+i});
|
|
||||||
contexts.addHandler(webapp);
|
|
||||||
}
|
|
||||||
|
|
||||||
server.start();
|
|
||||||
load();
|
|
||||||
|
|
||||||
Runtime.getRuntime().gc();
|
|
||||||
Runtime.getRuntime().gc();
|
|
||||||
|
|
||||||
long used_normal = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
|
||||||
System.err.println(used_normal);
|
|
||||||
|
|
||||||
server.stop();
|
|
||||||
contexts.setHandlers(null);
|
|
||||||
|
|
||||||
Runtime.getRuntime().gc();
|
|
||||||
Runtime.getRuntime().gc();
|
|
||||||
|
|
||||||
long used_stopped = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
|
||||||
System.err.println(used_stopped);
|
|
||||||
|
|
||||||
|
|
||||||
/* Cloud deploy */
|
|
||||||
boolean cloud=!Boolean.getBoolean("nocloud");
|
|
||||||
Log.info("Cloud deploy");
|
|
||||||
final WebAppContext template = new WebAppContext();
|
|
||||||
template.setClassLoader(loader);
|
|
||||||
template.setBaseResource(baseResource);
|
|
||||||
template.setAttribute("instance","-1");
|
|
||||||
template.setServer(server);
|
|
||||||
template.preConfigure();
|
|
||||||
template.configure();
|
|
||||||
template.postConfigure();
|
|
||||||
|
|
||||||
ResourceCache cache = new ResourceCache(resources,new MimeTypes(),true);
|
|
||||||
|
|
||||||
for (int i=0;i<10;i++)
|
|
||||||
{
|
|
||||||
final WebAppContext webapp = new WebAppContext(template);
|
|
||||||
webapp.setAttribute("resourceCache",cache);
|
|
||||||
webapp.setAttribute("instance",i);
|
|
||||||
CloudLoader cloud_loader = new CloudLoader((WebAppClassLoader)webapp.getClassLoader());
|
|
||||||
// cloud_loader.addPattern("com.acme.");
|
|
||||||
// cloud_loader.addPattern("org.eclipse.jetty.util.");
|
|
||||||
webapp.setClassLoader(cloud_loader);
|
|
||||||
|
|
||||||
if (i>0)
|
|
||||||
webapp.setVirtualHosts(new String[] {"127.0.0."+i});
|
|
||||||
contexts.addHandler(webapp);
|
|
||||||
}
|
|
||||||
server.start();
|
|
||||||
load();
|
|
||||||
|
|
||||||
|
|
||||||
Runtime.getRuntime().gc();
|
|
||||||
Runtime.getRuntime().gc();
|
|
||||||
|
|
||||||
long used_cloud = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
|
|
||||||
System.err.println(used_cloud);
|
|
||||||
|
|
||||||
server.stop();
|
|
||||||
|
|
||||||
System.err.println(used_normal-used_cloud);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void load() throws Exception
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int j=0;j<10;j++)
|
|
||||||
{
|
|
||||||
for (int i=0;i<10;i++)
|
|
||||||
{
|
|
||||||
// generate some load
|
|
||||||
for (String uri : new String[] {
|
|
||||||
"/",
|
|
||||||
"/d.txt",
|
|
||||||
"/da.txt",
|
|
||||||
"/dat.txt",
|
|
||||||
"/data.txt",
|
|
||||||
"/data.txt.gz",
|
|
||||||
"/dump/info"
|
|
||||||
})
|
|
||||||
{
|
|
||||||
URL url = new URL("http://127.0.0."+(i==0?10:i)+":8080"+uri);
|
|
||||||
String content = String.valueOf(IO.toString(url.openStream()));
|
|
||||||
// System.err.println("GOT "+url+" "+content.length());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -34,4 +35,76 @@ public interface HttpContent
|
||||||
long getContentLength();
|
long getContentLength();
|
||||||
InputStream getInputStream() throws IOException;
|
InputStream getInputStream() throws IOException;
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public class ResourceAsHttpContent implements HttpContent
|
||||||
|
{
|
||||||
|
final Resource _resource;
|
||||||
|
final MimeTypes _mimeTypes;
|
||||||
|
|
||||||
|
public ResourceAsHttpContent(final Resource resource, final MimeTypes mimeTypes)
|
||||||
|
{
|
||||||
|
_resource=resource;
|
||||||
|
_mimeTypes=mimeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getContentType()
|
||||||
|
{
|
||||||
|
return _mimeTypes.getMimeByExtension(_resource.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getLastModified()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getDirectBuffer()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Buffer getIndirectBuffer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ByteArrayBuffer buffer = new ByteArrayBuffer((int)_resource.length());
|
||||||
|
buffer.readFrom(_resource.getInputStream(),(int)_resource.length());
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public long getContentLength()
|
||||||
|
{
|
||||||
|
return _resource.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public InputStream getInputStream() throws IOException
|
||||||
|
{
|
||||||
|
return _resource.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public Resource getResource()
|
||||||
|
{
|
||||||
|
return _resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void release()
|
||||||
|
{
|
||||||
|
_resource.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class ResourceCache
|
||||||
private final AtomicInteger _cachedFiles;
|
private final AtomicInteger _cachedFiles;
|
||||||
private final boolean _useFileMappedBuffer;
|
private final boolean _useFileMappedBuffer;
|
||||||
private final ResourceFactory _factory;
|
private final ResourceFactory _factory;
|
||||||
|
private final ResourceCache _parent;
|
||||||
|
|
||||||
private final MimeTypes _mimeTypes;
|
private final MimeTypes _mimeTypes;
|
||||||
private int _maxCachedFileSize =4*1024*1024;
|
private int _maxCachedFileSize =4*1024*1024;
|
||||||
|
@ -59,7 +60,7 @@ public class ResourceCache
|
||||||
* @param mimeTypes Mimetype to use for meta data
|
* @param mimeTypes Mimetype to use for meta data
|
||||||
* @param fileMappedBuffers True if file mapped buffers can be used for DirectBuffers
|
* @param fileMappedBuffers True if file mapped buffers can be used for DirectBuffers
|
||||||
*/
|
*/
|
||||||
public ResourceCache(ResourceFactory factory, MimeTypes mimeTypes,boolean fileMappedBuffers)
|
public ResourceCache(ResourceCache parent, ResourceFactory factory, MimeTypes mimeTypes,boolean fileMappedBuffers)
|
||||||
{
|
{
|
||||||
_factory = factory;
|
_factory = factory;
|
||||||
_cache=new ConcurrentHashMap<String,Content>();
|
_cache=new ConcurrentHashMap<String,Content>();
|
||||||
|
@ -67,6 +68,7 @@ public class ResourceCache
|
||||||
_cachedFiles=new AtomicInteger();
|
_cachedFiles=new AtomicInteger();
|
||||||
_useFileMappedBuffer=fileMappedBuffers;
|
_useFileMappedBuffer=fileMappedBuffers;
|
||||||
_mimeTypes=mimeTypes;
|
_mimeTypes=mimeTypes;
|
||||||
|
_parent=parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -148,37 +150,62 @@ public class ResourceCache
|
||||||
* Get either a valid entry object or create a new one if possible.
|
* Get either a valid entry object or create a new one if possible.
|
||||||
*
|
*
|
||||||
* @param pathInContext The key into the cache
|
* @param pathInContext The key into the cache
|
||||||
* @return The entry matching <code>pathInContext</code>, or a new entry if no matching entry was found
|
* @return The entry matching <code>pathInContext</code>, or a new entry
|
||||||
|
* if no matching entry was found. If the content exists but is not cachable,
|
||||||
|
* then a {@link HttpContent.ResourceAsHttpContent} instance is return. If
|
||||||
|
* the resource does not exist, then null is returned.
|
||||||
* @throws IOException Problem loading the resource
|
* @throws IOException Problem loading the resource
|
||||||
*/
|
*/
|
||||||
public Content lookup(String pathInContext)
|
public HttpContent lookup(String pathInContext)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Content content=null;
|
// Is the content in this cache?
|
||||||
|
Content content =_cache.get(pathInContext);
|
||||||
// Look up cache operations
|
if (content!=null && (content).isValid())
|
||||||
content = _cache.get(pathInContext);
|
|
||||||
|
|
||||||
if (content!=null && content.isValid())
|
|
||||||
return content;
|
return content;
|
||||||
|
|
||||||
|
// try loading the content from our factory.
|
||||||
Resource resource=_factory.getResource(pathInContext);
|
Resource resource=_factory.getResource(pathInContext);
|
||||||
Content loaded = load(pathInContext,resource);
|
HttpContent loaded = load(pathInContext,resource);
|
||||||
|
if (loaded!=null)
|
||||||
return loaded;
|
return loaded;
|
||||||
|
|
||||||
|
// Is the content in the parent cache?
|
||||||
|
if (_parent!=null)
|
||||||
|
{
|
||||||
|
HttpContent httpContent=_parent.lookup(pathInContext);
|
||||||
|
if (httpContent!=null)
|
||||||
|
return httpContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
private Content load(String pathInContext, Resource resource)
|
/**
|
||||||
|
* @param resource
|
||||||
|
* @return True if the resource is cacheable. The default implementation tests the cache sizes.
|
||||||
|
*/
|
||||||
|
protected boolean isCacheable(Resource resource)
|
||||||
|
{
|
||||||
|
long len = resource.length();
|
||||||
|
|
||||||
|
// Will it fit in the cache?
|
||||||
|
return (len>0 && len<_maxCachedFileSize && len<_maxCacheSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
private HttpContent load(String pathInContext, Resource resource)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Content content=null;
|
Content content=null;
|
||||||
|
|
||||||
if (resource!=null && resource.exists() && !resource.isDirectory())
|
if (resource!=null && resource.exists() && !resource.isDirectory())
|
||||||
{
|
{
|
||||||
long len = resource.length();
|
long len = resource.length();
|
||||||
|
|
||||||
// Will it fit in the cache?
|
// Will it fit in the cache?
|
||||||
if (len>0 && len<_maxCachedFileSize && len<_maxCacheSize)
|
if (isCacheable(resource))
|
||||||
{
|
{
|
||||||
// Create the Content (to increment the cache sizes before adding the content
|
// Create the Content (to increment the cache sizes before adding the content
|
||||||
content = new Content(pathInContext,resource);
|
content = new Content(pathInContext,resource);
|
||||||
|
@ -196,8 +223,8 @@ public class ResourceCache
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
return new HttpContent.ResourceAsHttpContent(resource,_mimeTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,22 +266,6 @@ public class ResourceCache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** Remember a Resource Miss!
|
|
||||||
* @param pathInContext Path the cache resource at
|
|
||||||
* @param resource The resource to cache.
|
|
||||||
*/
|
|
||||||
public void miss(String pathInContext, Resource resource)
|
|
||||||
{
|
|
||||||
if (_maxCachedFiles>0 && _cachedFiles.get()>=_maxCachedFiles)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// check that somebody else did not fill this spot.
|
|
||||||
Miss miss = new Miss(pathInContext,resource);
|
|
||||||
if (_cache.putIfAbsent(pathInContext,miss)!=null)
|
|
||||||
miss.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
protected Buffer getIndirectBuffer(Resource resource)
|
protected Buffer getIndirectBuffer(Resource resource)
|
||||||
{
|
{
|
||||||
|
@ -343,6 +354,12 @@ public class ResourceCache
|
||||||
return _key!=null;
|
return _key!=null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public boolean isMiss()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
public Resource getResource()
|
public Resource getResource()
|
||||||
{
|
{
|
||||||
|
@ -454,33 +471,5 @@ public class ResourceCache
|
||||||
{
|
{
|
||||||
return "{"+_resource+","+_contentType+","+_lastModifiedBytes+"}";
|
return "{"+_resource+","+_contentType+","+_lastModifiedBytes+"}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/** MetaData associated with a context Resource.
|
|
||||||
*/
|
|
||||||
public class Miss extends Content
|
|
||||||
{
|
|
||||||
Miss(String pathInContext,Resource resource)
|
|
||||||
{
|
|
||||||
super(pathInContext,resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
boolean isValid()
|
|
||||||
{
|
|
||||||
if (_resource.exists())
|
|
||||||
{
|
|
||||||
if (this==_cache.remove(_key))
|
|
||||||
invalidate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,15 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.server;
|
package org.eclipse.jetty.server;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpContent;
|
||||||
import org.eclipse.jetty.http.MimeTypes;
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
import org.eclipse.jetty.server.ResourceCache.Content;
|
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.util.resource.ResourceCollection;
|
||||||
import org.eclipse.jetty.util.resource.ResourceFactory;
|
import org.eclipse.jetty.util.resource.ResourceFactory;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
@ -29,15 +32,83 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class ResourceCacheTest
|
public class ResourceCacheTest
|
||||||
{
|
{
|
||||||
private Resource directory;
|
@Test
|
||||||
private File[] files=new File[10];
|
public void testMutlipleSources1() throws Exception
|
||||||
private String[] names=new String[files.length];
|
|
||||||
private ResourceCache cache;
|
|
||||||
private ResourceFactory factory;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void init() throws Exception
|
|
||||||
{
|
{
|
||||||
|
ResourceCollection rc = new ResourceCollection(new String[]{
|
||||||
|
"../jetty-util/src/test/resources/org/eclipse/jetty/util/resource/one/",
|
||||||
|
"../jetty-util/src/test/resources/org/eclipse/jetty/util/resource/two/",
|
||||||
|
"../jetty-util/src/test/resources/org/eclipse/jetty/util/resource/three/"
|
||||||
|
});
|
||||||
|
|
||||||
|
Resource[] r = rc.getResources();
|
||||||
|
MimeTypes mime = new MimeTypes();
|
||||||
|
|
||||||
|
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false);
|
||||||
|
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false);
|
||||||
|
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false);
|
||||||
|
|
||||||
|
assertEquals("1 - one", getContent(rc1, "1.txt"));
|
||||||
|
assertEquals("2 - two", getContent(rc1, "2.txt"));
|
||||||
|
assertEquals("3 - three", getContent(rc1, "3.txt"));
|
||||||
|
|
||||||
|
assertEquals("1 - two", getContent(rc2, "1.txt"));
|
||||||
|
assertEquals("2 - two", getContent(rc2, "2.txt"));
|
||||||
|
assertEquals("3 - three", getContent(rc2, "3.txt"));
|
||||||
|
|
||||||
|
assertEquals(null, getContent(rc3, "1.txt"));
|
||||||
|
assertEquals("2 - three", getContent(rc3, "2.txt"));
|
||||||
|
assertEquals("3 - three", getContent(rc3, "3.txt"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUncacheable() throws Exception
|
||||||
|
{
|
||||||
|
ResourceCollection rc = new ResourceCollection(new String[]{
|
||||||
|
"../jetty-util/src/test/resources/org/eclipse/jetty/util/resource/one/",
|
||||||
|
"../jetty-util/src/test/resources/org/eclipse/jetty/util/resource/two/",
|
||||||
|
"../jetty-util/src/test/resources/org/eclipse/jetty/util/resource/three/"
|
||||||
|
});
|
||||||
|
|
||||||
|
Resource[] r = rc.getResources();
|
||||||
|
MimeTypes mime = new MimeTypes();
|
||||||
|
|
||||||
|
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false);
|
||||||
|
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean isCacheable(Resource resource)
|
||||||
|
{
|
||||||
|
return super.isCacheable(resource) && resource.getName().indexOf("2.txt")<0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false);
|
||||||
|
|
||||||
|
assertEquals("1 - one", getContent(rc1, "1.txt"));
|
||||||
|
assertEquals("2 - two", getContent(rc1, "2.txt"));
|
||||||
|
assertEquals("3 - three", getContent(rc1, "3.txt"));
|
||||||
|
|
||||||
|
assertEquals("1 - two", getContent(rc2, "1.txt"));
|
||||||
|
assertEquals("2 - two", getContent(rc2, "2.txt"));
|
||||||
|
assertEquals("3 - three", getContent(rc2, "3.txt"));
|
||||||
|
|
||||||
|
assertEquals(null, getContent(rc3, "1.txt"));
|
||||||
|
assertEquals("2 - three", getContent(rc3, "2.txt"));
|
||||||
|
assertEquals("3 - three", getContent(rc3, "3.txt"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResourceCache() throws Exception
|
||||||
|
{
|
||||||
|
final Resource directory;
|
||||||
|
File[] files=new File[10];
|
||||||
|
String[] names=new String[files.length];
|
||||||
|
ResourceCache cache;
|
||||||
|
|
||||||
for (int i=0;i<files.length;i++)
|
for (int i=0;i<files.length;i++)
|
||||||
{
|
{
|
||||||
files[i]=File.createTempFile("R-"+i+"-",".txt");
|
files[i]=File.createTempFile("R-"+i+"-",".txt");
|
||||||
|
@ -52,42 +123,17 @@ public class ResourceCacheTest
|
||||||
|
|
||||||
directory=Resource.newResource(files[0].getParentFile().getAbsolutePath());
|
directory=Resource.newResource(files[0].getParentFile().getAbsolutePath());
|
||||||
|
|
||||||
factory = new ResourceFactory()
|
|
||||||
{
|
|
||||||
public Resource getResource(String path)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return directory.addPath(path);
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
cache=new ResourceCache(null,directory,new MimeTypes(),false);
|
||||||
|
|
||||||
cache=new ResourceCache(factory,new MimeTypes(),false);
|
|
||||||
|
|
||||||
cache.setMaxCacheSize(95);
|
cache.setMaxCacheSize(95);
|
||||||
cache.setMaxCachedFileSize(85);
|
cache.setMaxCachedFileSize(85);
|
||||||
cache.setMaxCachedFiles(4);
|
cache.setMaxCachedFiles(4);
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void destroy() throws Exception
|
|
||||||
{
|
|
||||||
cache.flushCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testResourceCache() throws Exception
|
|
||||||
{
|
|
||||||
assertTrue(cache.lookup("does not exist")==null);
|
assertTrue(cache.lookup("does not exist")==null);
|
||||||
assertTrue(cache.lookup(names[9])==null);
|
assertTrue(cache.lookup(names[9]) instanceof HttpContent.ResourceAsHttpContent);
|
||||||
|
|
||||||
Content content;
|
HttpContent content;
|
||||||
content=cache.lookup(names[8]);
|
content=cache.lookup(names[8]);
|
||||||
assertTrue(content!=null);
|
assertTrue(content!=null);
|
||||||
assertEquals(80,content.getContentLength());
|
assertEquals(80,content.getContentLength());
|
||||||
|
@ -175,5 +221,28 @@ public class ResourceCacheTest
|
||||||
cache.flushCache();
|
cache.flushCache();
|
||||||
assertEquals(0,cache.getCachedSize());
|
assertEquals(0,cache.getCachedSize());
|
||||||
assertEquals(0,cache.getCachedFiles());
|
assertEquals(0,cache.getCachedFiles());
|
||||||
|
|
||||||
|
|
||||||
|
cache.flushCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getContent(Resource r, String path) throws Exception
|
||||||
|
{
|
||||||
|
StringBuilder buffer = new StringBuilder();
|
||||||
|
String line = null;
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(r.addPath(path).getURL().openStream()));
|
||||||
|
while((line=br.readLine())!=null)
|
||||||
|
buffer.append(line);
|
||||||
|
br.close();
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getContent(ResourceCache rc, String path) throws Exception
|
||||||
|
{
|
||||||
|
HttpContent content = rc.lookup(path);
|
||||||
|
if (content==null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return content.getIndirectBuffer().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,7 +257,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
{
|
{
|
||||||
if (_cache==null && max_cached_files>0)
|
if (_cache==null && max_cached_files>0)
|
||||||
{
|
{
|
||||||
_cache= new ResourceCache(this,_mimeTypes,_useFileMappedBuffer);
|
_cache= new ResourceCache(null,this,_mimeTypes,_useFileMappedBuffer);
|
||||||
|
|
||||||
if (max_cache_size>0)
|
if (max_cache_size>0)
|
||||||
_cache.setMaxCacheSize(max_cache_size);
|
_cache.setMaxCacheSize(max_cache_size);
|
||||||
|
@ -417,21 +417,11 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
content=_cache.lookup(pathInContextGz);
|
content=_cache.lookup(pathInContextGz);
|
||||||
|
resource=(content==null)?null:content.getResource();
|
||||||
if (content!=null)
|
|
||||||
resource=content.getResource();
|
|
||||||
else if (!(content instanceof ResourceCache.Miss))
|
|
||||||
resource=getResource(pathInContextGz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource==null || !resource.exists()|| resource.isDirectory())
|
if (resource==null || !resource.exists() || resource.isDirectory())
|
||||||
{
|
{
|
||||||
if (_cache!=null && content==null)
|
|
||||||
{
|
|
||||||
String real_path=_servletContext.getRealPath(pathInContextGz);
|
|
||||||
if (real_path!=null)
|
|
||||||
_cache.miss(pathInContextGz,_contextHandler.newResource(real_path));
|
|
||||||
}
|
|
||||||
gzip=false;
|
gzip=false;
|
||||||
pathInContextGz=null;
|
pathInContextGz=null;
|
||||||
}
|
}
|
||||||
|
@ -445,11 +435,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
content=_cache.lookup(pathInContext);
|
content=_cache.lookup(pathInContext);
|
||||||
|
resource=content==null?null:content.getResource();
|
||||||
if (content!=null)
|
|
||||||
resource=content.getResource();
|
|
||||||
else
|
|
||||||
resource=getResource(pathInContext);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,9 +444,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
|
|
||||||
// Handle resource
|
// Handle resource
|
||||||
if (resource==null || !resource.exists())
|
if (resource==null || !resource.exists())
|
||||||
if (included) {
|
{
|
||||||
throw new FileNotFoundException("Nothing at " + pathInContext);
|
if (included)
|
||||||
} else {
|
throw new FileNotFoundException("!" + pathInContext);
|
||||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||||
}
|
}
|
||||||
else if (!resource.isDirectory())
|
else if (!resource.isDirectory())
|
||||||
|
@ -477,7 +463,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
{
|
{
|
||||||
// ensure we have content
|
// ensure we have content
|
||||||
if (content==null)
|
if (content==null)
|
||||||
content=new UnCachedContent(resource);
|
content=new HttpContent.ResourceAsHttpContent(resource,_mimeTypes);
|
||||||
|
|
||||||
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
|
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
|
||||||
{
|
{
|
||||||
|
@ -547,7 +533,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
content=new UnCachedContent(resource);
|
content=new HttpContent.ResourceAsHttpContent(resource,_mimeTypes);
|
||||||
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
|
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
|
||||||
sendDirectory(request,response,resource,pathInContext);
|
sendDirectory(request,response,resource,pathInContext);
|
||||||
}
|
}
|
||||||
|
@ -1012,66 +998,4 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private class UnCachedContent implements HttpContent
|
|
||||||
{
|
|
||||||
Resource _resource;
|
|
||||||
|
|
||||||
UnCachedContent(Resource resource)
|
|
||||||
{
|
|
||||||
_resource=resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Buffer getContentType()
|
|
||||||
{
|
|
||||||
return _mimeTypes.getMimeByExtension(_resource.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Buffer getLastModified()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Buffer getDirectBuffer()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Buffer getIndirectBuffer()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public long getContentLength()
|
|
||||||
{
|
|
||||||
return _resource.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public InputStream getInputStream() throws IOException
|
|
||||||
{
|
|
||||||
return _resource.getInputStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Resource getResource()
|
|
||||||
{
|
|
||||||
return _resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void release()
|
|
||||||
{
|
|
||||||
_resource.release();
|
|
||||||
_resource=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ import org.eclipse.jetty.util.log.Log;
|
||||||
/**
|
/**
|
||||||
* Abstract resource class.
|
* Abstract resource class.
|
||||||
*/
|
*/
|
||||||
public abstract class Resource
|
public abstract class Resource implements ResourceFactory
|
||||||
{
|
{
|
||||||
public static boolean __defaultUseCaches = true;
|
public static boolean __defaultUseCaches = true;
|
||||||
volatile Object _associate;
|
volatile Object _associate;
|
||||||
|
@ -429,6 +429,25 @@ public abstract class Resource
|
||||||
public abstract Resource addPath(String path)
|
public abstract Resource addPath(String path)
|
||||||
throws IOException,MalformedURLException;
|
throws IOException,MalformedURLException;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/** Get a resource from withing this resource.
|
||||||
|
* <p>
|
||||||
|
* This method is essentially an alias for {@link #addPath(String)}, but without checked exceptions.
|
||||||
|
* This method satisfied the {@link ResourceFactory} interface.
|
||||||
|
* @see org.eclipse.jetty.util.resource.ResourceFactory#getResource(java.lang.String)
|
||||||
|
*/
|
||||||
|
public Resource getResource(String path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return addPath(path);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Log.debug(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** Encode according to this resource type.
|
/** Encode according to this resource type.
|
||||||
|
|
|
@ -16,10 +16,14 @@ package org.eclipse.jetty.util.resource;
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** ResourceFactory.
|
/** ResourceFactory.
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public interface ResourceFactory
|
public interface ResourceFactory
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/** Get a resource for a path.
|
||||||
|
* @param path The path to the resource
|
||||||
|
* @return The resource or null
|
||||||
|
*/
|
||||||
Resource getResource(String path);
|
Resource getResource(String path);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue