001: /*
002: * Copyright 1999-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package com.opensymphony.webwork.util.classloader;
017:
018: import com.opensymphony.webwork.util.classloader.listeners.ReloadingListener;
019: import com.opensymphony.webwork.util.classloader.listeners.CompilingListener;
020: import com.opensymphony.webwork.util.classloader.monitor.FilesystemAlterationMonitor;
021: import com.opensymphony.webwork.util.classloader.readers.FileResourceReader;
022: import com.opensymphony.webwork.util.classloader.readers.ResourceReader;
023: import com.opensymphony.webwork.util.classloader.stores.MemoryResourceStore;
024: import com.opensymphony.webwork.util.classloader.stores.ResourceStore;
025: import com.opensymphony.webwork.util.classloader.stores.ResourceStoreClassLoader;
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028:
029: import java.io.File;
030: import java.io.InputStream;
031: import java.net.URL;
032: import java.util.*;
033:
034: /**
035: * @author tcurdt
036: */
037: public class ReloadingClassLoader extends ClassLoader {
038:
039: private final static Log log = LogFactory
040: .getLog(ReloadingClassLoader.class);
041:
042: private final ClassLoader parent;
043: private final ResourceStore store;
044: private final Collection reloadingListeners = new HashSet();
045: protected CompilingListener listener;
046:
047: private ResourceStoreClassLoader delegate;
048:
049: protected final ResourceReader reader;
050: protected final File repository;
051:
052: protected FilesystemAlterationMonitor fam;
053: protected Thread thread;
054:
055: public ReloadingClassLoader(final ClassLoader pParent,
056: final File pRepository) {
057: this (pParent, pRepository, new MemoryResourceStore());
058: }
059:
060: public ReloadingClassLoader(final ClassLoader pParent,
061: final File pRepository, final ResourceStore pStore) {
062: super (pParent);
063:
064: parent = pParent;
065: repository = pRepository;
066: reader = new FileResourceReader(repository);
067: store = pStore;
068:
069: delegate = new ResourceStoreClassLoader(parent, store);
070: }
071:
072: public void start() {
073: fam = new FilesystemAlterationMonitor();
074: fam.addListener(new ReloadingListener(store) {
075: protected void notifyOfCheck(boolean pReload) {
076: super .notifyOfCheck(pReload);
077: if (pReload) {
078: ReloadingClassLoader.this .reload();
079: } else {
080: ReloadingClassLoader.this
081: .notifyReloadingListeners(false);
082: }
083: }
084: }, repository);
085: thread = new Thread(fam);
086: thread.start();
087: }
088:
089: public void stop() {
090: fam.stop();
091: try {
092: thread.join();
093: } catch (final InterruptedException e) {
094: ;
095: }
096: }
097:
098: public void addListener(final ReloadingClassLoaderListener pListener) {
099: synchronized (reloadingListeners) {
100: reloadingListeners.add(pListener);
101: }
102: }
103:
104: public boolean removeListener(
105: final ReloadingClassLoaderListener pListener) {
106: synchronized (reloadingListeners) {
107: return reloadingListeners.remove(pListener);
108: }
109: }
110:
111: protected void reload() {
112: log.debug("reloading");
113:
114: delegate = new ResourceStoreClassLoader(parent, store);
115:
116: notifyReloadingListeners(true);
117: }
118:
119: private void notifyReloadingListeners(final boolean pReload) {
120: synchronized (reloadingListeners) {
121: for (final Iterator it = reloadingListeners.iterator(); it
122: .hasNext();) {
123: final ReloadingClassLoaderListener listener = (ReloadingClassLoaderListener) it
124: .next();
125: listener.hasReloaded(pReload);
126: }
127: }
128: }
129:
130: public static String clazzName(final File base, final File file) {
131: final int rootLength = base.getAbsolutePath().length();
132: final String absFileName = file.getAbsolutePath();
133: final int p = absFileName.lastIndexOf('.');
134: final String relFileName = absFileName.substring(
135: rootLength + 1, p);
136: final String clazzName = relFileName.replace(
137: File.separatorChar, '.');
138: return clazzName;
139: }
140:
141: public void clearAssertionStatus() {
142: delegate.clearAssertionStatus();
143: }
144:
145: public URL getResource(String name) {
146: return delegate.getResource(name);
147: }
148:
149: public InputStream getResourceAsStream(String name) {
150: return delegate.getResourceAsStream(name);
151: }
152:
153: public Class loadClass(String name) throws ClassNotFoundException {
154: return delegate.loadClass(name);
155: }
156:
157: public void setClassAssertionStatus(String className,
158: boolean enabled) {
159: delegate.setClassAssertionStatus(className, enabled);
160: }
161:
162: public void setDefaultAssertionStatus(boolean enabled) {
163: delegate.setDefaultAssertionStatus(enabled);
164: }
165:
166: public void setPackageAssertionStatus(String packageName,
167: boolean enabled) {
168: delegate.setPackageAssertionStatus(packageName, enabled);
169: }
170: }
|