View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jci;
19  
20  import java.io.InputStream;
21  import java.net.URL;
22  
23  import org.apache.commons.jci.listeners.ReloadNotificationListener;
24  import org.apache.commons.jci.stores.ResourceStore;
25  import org.apache.commons.jci.stores.ResourceStoreClassLoader;
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  /**
30   * The ReloadingClassLoader uses a delegation mechansim to allow
31   * classes to be reloaded. That means that loadClass calls may
32   * return different results if the class was changed in the underlying
33   * ResourceStore.
34   * 
35   * @author tcurdt
36   */
37  public class ReloadingClassLoader extends ClassLoader implements ReloadNotificationListener {
38      
39      private final Log log = LogFactory.getLog(ReloadingClassLoader.class);
40      
41      private final ClassLoader parent;
42      private ResourceStore[] stores = new ResourceStore[0];
43      private ClassLoader delegate;
44  
45      public ReloadingClassLoader( final ClassLoader pParent ) {        
46          super(pParent);
47          parent = pParent;        
48  
49          delegate = new ResourceStoreClassLoader(parent, stores);
50      }
51  
52      public boolean addResourceStore( final ResourceStore pStore ) {
53          try {        
54              final int n = stores.length;
55              final ResourceStore[] newStores = new ResourceStore[n + 1];
56              System.arraycopy(stores, 0, newStores, 1, n);
57              newStores[0] = pStore;
58              stores = newStores;
59              delegate = new ResourceStoreClassLoader(parent, stores);            
60              return true;
61          } catch ( final RuntimeException e ) {
62              log.error("could not add resource store " + pStore);
63          }
64          return false;
65      }
66  
67      public boolean removeResourceStore( final ResourceStore pStore ) {
68  
69          final int n = stores.length;
70          int i = 0;
71             
72          // FIXME: this should be improved with a Map
73          // find the pStore and index position with var i
74          while ( ( i < n )  && ( stores[i] != pStore ) ) {
75              i++;
76          }
77                      
78          // pStore was not found
79          if ( i == n ) {
80              return false;
81          }
82          
83          // if stores length > 1 then array copy old values, else create new empty store 
84          final ResourceStore[] newStores = new ResourceStore[n - 1];
85          if (i > 0) {
86              System.arraycopy(stores, 0, newStores, 0, i);
87          }
88          if (i < n - 1) {
89              System.arraycopy(stores, i + 1, newStores, i, (n - i - 1));
90          }
91              
92          stores = newStores;
93          delegate = new ResourceStoreClassLoader(parent, stores);
94          return true;
95      }
96      
97      public void handleNotification() {
98          log.debug("reloading");
99          delegate = new ResourceStoreClassLoader(parent, stores);
100     }
101     
102     @Override
103     public void clearAssertionStatus() {
104         delegate.clearAssertionStatus();
105     }
106     @Override
107     public URL getResource(String name) {
108         return delegate.getResource(name);
109     }
110     @Override
111     public InputStream getResourceAsStream(String name) {
112         return delegate.getResourceAsStream(name);
113     }
114     @Override
115     public Class<?> loadClass(String name) throws ClassNotFoundException {
116         return delegate.loadClass(name);
117     }
118     @Override
119     public void setClassAssertionStatus(String className, boolean enabled) {
120         delegate.setClassAssertionStatus(className, enabled);
121     }
122     @Override
123     public void setDefaultAssertionStatus(boolean enabled) {
124         delegate.setDefaultAssertionStatus(enabled);
125     }
126     @Override
127     public void setPackageAssertionStatus(String packageName, boolean enabled) {
128         delegate.setPackageAssertionStatus(packageName, enabled);
129     }
130 }