View Javadoc

1   /*
2    * $Id: FineGrainedControlClassLoader.java 22850 2011-09-04 00:18:09Z mariano.capurro $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.launcher;
12  
13  import org.mule.util.StringUtils;
14  
15  import java.net.URL;
16  import java.util.Collections;
17  import java.util.HashSet;
18  import java.util.Set;
19  
20  /**
21   * TODO document overrides, blocked, systemPackages and syntax for specifying those.
22   */
23  public class FineGrainedControlClassLoader extends GoodCitizenClassLoader
24  {
25  
26      protected String appName;
27  
28      // Finished with '.' so that we can use startsWith to verify
29      protected String[] systemPackages = {
30              "java.",
31              "javax.",
32              "org.mule.",
33              "com.mulesoft.",
34              "com.mulesource."
35      };
36  
37      protected Set<String> overrides = new HashSet<String>();
38      protected Set<String> blocked = new HashSet<String>();
39  
40      public FineGrainedControlClassLoader(URL[] urls, ClassLoader parent)
41      {
42          this(urls, parent, Collections.<String>emptySet());
43      }
44  
45      public FineGrainedControlClassLoader(URL[] urls, ClassLoader parent, Set<String> overrides)
46      {
47          super(urls, parent);
48          processOverrides(overrides);
49      }
50  
51      protected void processOverrides(Set<String> overrides)
52      {
53          if (overrides != null && !overrides.isEmpty())
54          {
55              for (String override : overrides)
56              {
57                  override = StringUtils.defaultString(override).trim();
58                  // 'blocked' package definitions come with a '-' prefix
59                  if (override.startsWith("-"))
60                  {
61                      override = override.substring(1);
62                      this.blocked.add(override);
63                  }
64                  this.overrides.add(override);
65  
66                  for (String systemPackage : systemPackages)
67                  {
68                      if (override.startsWith(systemPackage))
69                      {
70                          throw new IllegalArgumentException("Can't override a system package. Offending value: " + override);
71                      }
72                  }
73              }
74          }
75      }
76  
77      @Override
78      protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
79      {
80          Class<?> result = findLoadedClass(name);
81  
82          if (result != null)
83          {
84              return result;
85          }
86          boolean overrideMatch = isOverridden(name);
87  
88  
89          if (overrideMatch)
90          {
91              boolean blockedMatch = isBlocked(name);
92  
93              if (blockedMatch)
94              {
95                  // load this class from the child ONLY, don't attempt parent, let CNFE exception propagate
96                  result = findClass(name);
97              }
98              else
99              {
100                 // load this class from the child
101                 try
102                 {
103                     result = findClass(name);
104                 }
105                 catch (ClassNotFoundException e)
106                 {
107                     // let it fail with CNFE
108                     result = findParentClass(name);
109                 }
110             }
111 
112 
113         }
114         else
115         {
116             // no overrides, regular parent-first lookup
117             try
118             {
119                 result = findParentClass(name);
120             }
121             catch (ClassNotFoundException e)
122             {
123                 result = findClass(name);
124             }
125         }
126 
127         if (resolve)
128         {
129             resolveClass(result);
130         }
131 
132         return result;
133     }
134 
135     protected boolean isOverridden(String name)
136     {
137         // find a match
138         boolean overrideMatch = false;
139         for (String override : overrides)
140         {
141             if (name.equals(override) || name.startsWith(override + "."))
142             {
143                 overrideMatch = true;
144                 break;
145             }
146         }
147         return overrideMatch;
148     }
149 
150     protected boolean isBlocked(String name)
151     {
152         boolean blockedMatch = false;
153         for (String b : blocked)
154         {
155             if (name.equals(b) || name.startsWith(b + "."))
156             {
157                 blockedMatch = true;
158                 break;
159             }
160         }
161         return blockedMatch;
162     }
163 
164     protected Class<?> findParentClass(String name) throws ClassNotFoundException
165     {
166         if (getParent() != null)
167         {
168             return getParent().loadClass(name);
169         }
170         else
171         {
172             return findSystemClass(name);
173         }
174     }
175 
176     @Override
177     protected Class<?> findClass(String name) throws ClassNotFoundException
178     {
179         return super.findClass(name);
180     }
181 
182 }