001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.gsfpath.api.classpath;
043:
044: import java.beans.PropertyChangeListener;
045: import java.net.URL;
046: import java.util.*;
047:
048: import org.openide.execution.NbClassLoader;
049: import org.openide.filesystems.*;
050: import org.openide.util.WeakListeners;
051: import org.openide.ErrorManager;
052: import org.openide.util.Lookup;
053: import org.openide.util.LookupEvent;
054: import org.openide.util.LookupListener;
055:
056: /** Classloader for the filesystem pool. Attaches itself as a listener to
057: * each file a class has been loaded from. If such a file is deleted, modified
058: * or renamed clears the global variable that holds "current" classloader, so
059: * on next request for current one new is created.
060: *
061: * @author Jaroslav Tulach
062: */
063: class ClassLoaderSupport extends NbClassLoader implements
064: FileChangeListener, PropertyChangeListener {
065:
066: public static ClassLoader create(ClassPath cp) {
067: try {
068: return new ClassLoaderSupport(cp);
069: } catch (FileStateInvalidException e) {
070: // Should not happen, we already trimmed unused roots:
071: throw new AssertionError(e);
072: }
073: }
074:
075: /** change listener */
076: private org.openide.filesystems.FileChangeListener listener;
077:
078: /** PropertyChangeListener */
079: private java.beans.PropertyChangeListener propListener;
080:
081: /** contains AllPermission */
082: private static java.security.PermissionCollection allPermission;
083:
084: private static boolean firstTime = true;
085:
086: /**
087: * The ClassPath to load classes from.
088: */
089: private ClassPath classPath;
090:
091: /** Constructor that attaches itself to the filesystem pool.
092: */
093: private ClassLoaderSupport(ClassPath cp)
094: throws FileStateInvalidException {
095: super (cp.getRoots(), ClassLoader.getSystemClassLoader(), null);
096: this .classPath = cp;
097:
098: setDefaultPermissions(getAllPermissions());
099: listener = FileUtil.weakFileChangeListener(this , null);
100: propListener = WeakListeners.propertyChange(this , null);
101: cp.addPropertyChangeListener(propListener);
102: }
103:
104: /**
105: * Tries to locate the .class file on the ClassPath
106: * @param name
107: * @return
108: * @throws ClassNotFoundException
109: */
110: protected Class findClass(String name)
111: throws ClassNotFoundException {
112: Class c = super .findClass(name);
113: if (c != null) {
114: org.openide.filesystems.FileObject fo;
115: String resName = name.replace('.', '/') + ".class"; // NOI18N
116: fo = classPath.findResource(resName);
117: if (fo != null) {
118: // if the file is from the file system pool,
119: // register to catch its changes
120: fo.addFileChangeListener(listener);
121: }
122: }
123: return c;
124: }
125:
126: /**
127: * Tries to locate the resource on the ClassPath
128: * @param name
129: * @return URL of the resource
130: */
131: public URL findResource(String name) {
132: URL url = super .findResource(name);
133: if (url != null) {
134: FileObject fo = classPath.findResource(name);
135: if (fo != null) {
136: // if the file is from the file system pool,
137: // register to catch its changes
138: fo.addFileChangeListener(listener);
139: }
140: }
141: return url;
142: }
143:
144: /** Tests whether this object is current loader and if so,
145: * clears the loader.
146: * @param fo file object that initiated the action
147: */
148: private void test(org.openide.filesystems.FileObject fo) {
149: classPath.resetClassLoader(this );
150: fo.removeFileChangeListener(listener);
151: }
152:
153: /** Resets the loader, removes it from listneing on all known objects.
154: */
155: private void reset() {
156: classPath.resetClassLoader(this );
157: }
158:
159: /** If this object is not current classloader, removes it from
160: * listening on given file object.
161: */
162: private void testRemove(org.openide.filesystems.FileObject fo) {
163: fo.removeFileChangeListener(listener);
164: }
165:
166: /** Fired when a new folder has been created. This action can only be
167: * listened in folders containing the created file up to the root of
168: * file system.
169: *
170: * @param fe the event describing context where action has taken place
171: */
172: public void fileFolderCreated(org.openide.filesystems.FileEvent fe) {
173: testRemove(fe.getFile());
174: }
175:
176: /** Fired when a new file has been created. This action can only be
177: * listened in folders containing the created file up to the root of
178: * file system.
179: *
180: * @param fe the event describing context where action has taken place
181: */
182: public void fileDataCreated(org.openide.filesystems.FileEvent fe) {
183: testRemove(fe.getFile());
184: }
185:
186: /** Fired when a file has been changed.
187: * @param fe the event describing context where action has taken place
188: */
189: public void fileChanged(org.openide.filesystems.FileEvent fe) {
190: test(fe.getFile());
191: }
192:
193: /** Fired when a file has been deleted.
194: * @param fe the event describing context where action has taken place
195: */
196: public void fileDeleted(org.openide.filesystems.FileEvent fe) {
197: test(fe.getFile());
198: }
199:
200: /** Fired when a file has been renamed.
201: * @param fe the event describing context where action has taken place
202: * and the original name and extension.
203: */
204: public void fileRenamed(org.openide.filesystems.FileRenameEvent fe) {
205: test(fe.getFile());
206: }
207:
208: /** Fired when a file attribute has been changed.
209: * @param fe the event describing context where action has taken place,
210: * the name of attribute and old and new value.
211: */
212: public void fileAttributeChanged(
213: org.openide.filesystems.FileAttributeEvent fe) {
214: testRemove(fe.getFile());
215: }
216:
217: /** Getter for allPermissions */
218: static synchronized java.security.PermissionCollection getAllPermissions() {
219: if (allPermission == null) {
220: allPermission = new java.security.Permissions();
221: allPermission.add(new java.security.AllPermission());
222: }
223: return allPermission;
224: }
225:
226: /**
227: * This method gets called when a bound property is changed.
228: * @param evt A PropertyChangeEvent object describing the event source
229: * and the property that has changed.
230: */
231: public void propertyChange(java.beans.PropertyChangeEvent evt) {
232: if (ClassPath.PROP_ROOTS.equals(evt.getPropertyName()))
233: reset();
234: }
235: }
|