001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free SoftwareFoundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.loader;
031:
032: import com.caucho.config.ConfigException;
033: import com.caucho.log.Log;
034: import com.caucho.util.CharBuffer;
035: import com.caucho.vfs.JarPath;
036: import com.caucho.vfs.Path;
037:
038: import javax.annotation.PostConstruct;
039: import java.net.URL;
040: import java.security.CodeSource;
041: import java.security.cert.Certificate;
042: import java.util.*;
043: import java.util.logging.Level;
044: import java.util.logging.Logger;
045:
046: /**
047: * Class loader which checks for changes in class files and automatically
048: * picks up new jars.
049: */
050: public class SimpleLoader extends Loader {
051: private static final Logger log = Log.open(SimpleLoader.class);
052:
053: // The class directory
054: private Path _path;
055: private String _prefix;
056: private String _pathPrefix;
057:
058: private CodeSource _codeSource;
059:
060: /**
061: * Null constructor for the simple loader.
062: */
063: public SimpleLoader() {
064: }
065:
066: /**
067: * Creates the simple loader with the specified path.
068: *
069: * @param path specifying the root of the resources
070: */
071: public SimpleLoader(Path path) {
072: setPath(path);
073: }
074:
075: /**
076: * Creates the simple loader with the specified path and prefix.
077: *
078: * @param path specifying the root of the resources
079: * @param prefix the prefix that the resources must match
080: */
081: public SimpleLoader(Path path, String prefix) {
082: setPath(path);
083: setPrefix(prefix);
084: }
085:
086: /**
087: * Create a class loader based on the SimpleLoader
088: *
089: * @param parent parent class loader
090: * @param path traditional classpath
091: * @param prefix the class prefix restriction
092: *
093: * @return the new ClassLoader
094: */
095: public static DynamicClassLoader create(ClassLoader parent,
096: Path path, String prefix) {
097: DynamicClassLoader loader = new DynamicClassLoader(parent,
098: false);
099:
100: loader.addLoader(new SimpleLoader(path, prefix));
101:
102: loader.init();
103:
104: return loader;
105: }
106:
107: /**
108: * Create a class loader based on the SimpleLoader
109: *
110: * @param parent parent class loader
111: * @param path traditional classpath
112: *
113: * @return the new ClassLoader
114: */
115: public static DynamicClassLoader create(ClassLoader parent,
116: Path path) {
117: DynamicClassLoader loader = new DynamicClassLoader(parent,
118: false);
119:
120: loader.addLoader(new SimpleLoader(path));
121:
122: loader.init();
123:
124: return loader;
125: }
126:
127: /**
128: * Create a class loader based on the SimpleLoader
129: *
130: * @param path traditional classpath
131: *
132: * @return the new ClassLoader
133: */
134: public static DynamicClassLoader create(Path path) {
135: ClassLoader parent = Thread.currentThread()
136: .getContextClassLoader();
137:
138: return create(parent, path);
139: }
140:
141: /**
142: * Sets the resource directory.
143: */
144: public void setPath(Path path) {
145: if (path.getPath().endsWith(".jar")
146: || path.getPath().endsWith(".zip")) {
147: path = JarPath.create(path);
148: }
149:
150: _path = path;
151: }
152:
153: /**
154: * Gets the resource path.
155: */
156: public Path getPath() {
157: return _path;
158: }
159:
160: /**
161: * Sets the resource prefix
162: */
163: public void setPrefix(String prefix) {
164: _prefix = prefix;
165:
166: if (prefix != null)
167: _pathPrefix = prefix.replace('.', '/');
168: }
169:
170: /**
171: * Gets the resource prefix
172: */
173: public String getPrefix() {
174: return _prefix;
175: }
176:
177: /**
178: * Sets the owning class loader.
179: */
180: public void setLoader(DynamicClassLoader loader) {
181: super .setLoader(loader);
182:
183: loader.addURL(_path);
184: }
185:
186: /**
187: * Initializes the loader.
188: */
189: @PostConstruct
190: public void init() throws ConfigException {
191: try {
192: _codeSource = new CodeSource(new URL(_path.getURL()),
193: (Certificate[]) null);
194: } catch (Exception e) {
195: log.log(Level.FINE, e.toString(), e);
196: }
197: }
198:
199: /**
200: * Given a class or resource name, returns a patch to that resource.
201: *
202: * @param name the class or resource name.
203: *
204: * @return the path representing the class or resource.
205: */
206: public Path getPath(String name) {
207: if (_prefix != null && _pathPrefix == null)
208: _pathPrefix = _prefix.replace('.', '/');
209:
210: if (_pathPrefix != null && !name.startsWith(_pathPrefix))
211: return null;
212:
213: if (name.startsWith("/"))
214: return _path.lookup("." + name);
215: else
216: return _path.lookup(name);
217: }
218:
219: /**
220: * Returns the code source for the directory.
221: */
222: protected CodeSource getCodeSource(Path path) {
223: return _codeSource;
224: }
225:
226: /**
227: * Adds the class of this resource.
228: */
229: @Override
230: protected void buildClassPath(ArrayList<String> pathList) {
231: String path = null;
232:
233: if (_path instanceof JarPath)
234: path = ((JarPath) _path).getContainer().getNativePath();
235: else if (_path.isDirectory())
236: path = _path.getNativePath();
237:
238: if (path != null && !pathList.contains(path))
239: pathList.add(path);
240: }
241:
242: /**
243: * Returns a printable representation of the loader.
244: */
245: public String toString() {
246: if (_prefix != null)
247: return "SimpleLoader[" + _path + ",prefix=" + _prefix + "]";
248: else
249: return "SimpleLoader[" + _path + "]";
250: }
251: }
|