View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.webapp;
20  
21  import java.io.IOException;
22  import java.net.URL;
23  import java.util.concurrent.ConcurrentHashMap;
24  
25  import org.eclipse.jetty.util.ConcurrentHashSet;
26  import org.eclipse.jetty.util.annotation.ManagedObject;
27  import org.eclipse.jetty.util.annotation.ManagedOperation;
28  
29  
30  /**
31   * A WebAppClassLoader that caches {@link #getResource(String)} results.
32   * Specifically this ClassLoader caches not found classes and resources,
33   * which can greatly increase performance for applications that search 
34   * for resources.
35   */
36  @ManagedObject
37  public class CachingWebAppClassLoader extends WebAppClassLoader
38  {
39      private final ConcurrentHashSet<String> _notFound = new ConcurrentHashSet<>();
40      private final ConcurrentHashMap<String,URL> _cache = new ConcurrentHashMap<>();
41      
42      public CachingWebAppClassLoader(ClassLoader parent, Context context) throws IOException
43      {
44          super(parent,context);
45      }
46  
47      public CachingWebAppClassLoader(Context context) throws IOException
48      {
49          super(context);
50      }
51  
52      @Override
53      public URL getResource(String name)
54      {
55          if (_notFound.contains(name))
56              return null;
57          
58          URL url = _cache.get(name);
59          
60          if (name==null)
61          {
62              url = super.getResource(name);
63          
64              if (url==null)
65              {
66                  _notFound.add(name);
67              }
68              else
69              {
70                  _cache.putIfAbsent(name,url);
71              }
72          }
73          
74          return url;
75      }
76  
77      @Override
78      protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
79      {
80          if (_notFound.contains(name))
81              throw new ClassNotFoundException(name+": in notfound cache");
82          try
83          {
84              return super.loadClass(name,resolve);
85          }
86          catch (ClassNotFoundException nfe)
87          {
88              _notFound.add(name);
89              throw nfe; 
90          }
91      }
92  
93      @Override
94      protected Class<?> findClass(String name) throws ClassNotFoundException
95      {
96          if (_notFound.contains(name))
97              throw new ClassNotFoundException(name+": in notfound cache");
98          try
99          {
100             return super.findClass(name);
101         }
102         catch (ClassNotFoundException nfe)
103         {
104             _notFound.add(name);
105             throw nfe; 
106         }
107     }
108 
109     @ManagedOperation
110     public void clearCache()
111     {
112         _cache.clear();
113         _notFound.clear();
114     }
115     
116     @Override
117     public String toString()
118     {
119         return "Caching["+super.toString()+"]";
120     }
121 }