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: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.loader;
030:
031: import com.caucho.config.ConfigException;
032: import com.caucho.config.types.FileSetType;
033: import com.caucho.config.types.PathPatternType;
034: import com.caucho.make.DependencyContainer;
035: import com.caucho.server.util.CauchoSystem;
036: import com.caucho.util.CharBuffer;
037: import com.caucho.vfs.Depend;
038: import com.caucho.vfs.Dependency;
039: import com.caucho.vfs.JarPath;
040: import com.caucho.vfs.Path;
041:
042: import javax.annotation.PostConstruct;
043: import java.net.URL;
044: import java.util.*;
045: import java.util.logging.Level;
046: import java.util.logging.Logger;
047: import java.io.*;
048: import java.util.zip.*;
049:
050: /**
051: * Class loader which checks for changes in class files and automatically
052: * picks up new jars.
053: */
054: public class LibraryLoader extends JarListLoader {
055: private static final Logger log = Logger
056: .getLogger(LibraryLoader.class.getName());
057:
058: // Configured path.
059: private Path _path;
060:
061: private FileSetType _fileSet;
062:
063: // When the directory was last modified
064: private long _lastModified;
065:
066: private String[] _fileNames;
067:
068: // list of the matching paths
069: private ArrayList<Path> _pathList = new ArrayList<Path>();
070:
071: // list of the matching paths
072: private ArrayList<Path> _newPathList = new ArrayList<Path>();
073:
074: /**
075: * Creates a new directory loader.
076: */
077: public LibraryLoader() {
078: }
079:
080: /**
081: * Creates a new directory loader.
082: */
083: public LibraryLoader(Path path) {
084: _path = path;
085:
086: try {
087: init();
088: } catch (Exception e) {
089: throw new RuntimeException(e);
090: }
091: }
092:
093: /**
094: * The library loader's path.
095: */
096: public void setPath(Path path) {
097: _path = path;
098: }
099:
100: /**
101: * The library loader's path.
102: */
103: public Path getPath() {
104: return _path;
105: }
106:
107: /**
108: * Sets a file set.
109: */
110: public void setFileset(FileSetType fileSet) {
111: _fileSet = fileSet;
112: }
113:
114: /**
115: * Create a new class loader
116: *
117: * @param parent parent class loader
118: * @param dir directories which can handle dynamic jar addition
119: */
120: public static DynamicClassLoader create(ClassLoader parent,
121: Path path) {
122: DynamicClassLoader loader = new DynamicClassLoader(parent);
123:
124: LibraryLoader dirLoader = new LibraryLoader(path);
125:
126: loader.addLoader(dirLoader);
127:
128: loader.init();
129:
130: return loader;
131: }
132:
133: /**
134: * Initialize
135: */
136: @PostConstruct
137: @Override
138: public void init() throws ConfigException {
139: super .init();
140:
141: try {
142: if (_fileSet != null) {
143: } else if (_path.getPath().endsWith(".jar")
144: || _path.getPath().endsWith(".zip")) {
145: _fileSet = new FileSetType();
146: _fileSet.setDir(_path.getParent());
147: _fileSet
148: .addInclude(new PathPatternType(_path.getTail()));
149: } else {
150: _fileSet = new FileSetType();
151: _fileSet.setDir(_path);
152: _fileSet.addInclude(new PathPatternType("*.jar"));
153: _fileSet.addInclude(new PathPatternType("*.zip"));
154: }
155:
156: fillJars();
157: } catch (ConfigException e) {
158: throw e;
159: } catch (Exception e) {
160: throw ConfigException.create(e);
161: }
162: }
163:
164: /**
165: * True if any of the loaded classes have been modified. If true, the
166: * caller should drop the classpath and create a new one.
167: */
168: public boolean isModified() {
169: _newPathList.clear();
170:
171: _fileSet.getPaths(_newPathList);
172:
173: return !_newPathList.equals(_pathList);
174: }
175:
176: /**
177: * True if the classes in the directory have changed.
178: */
179: public boolean logModified(Logger log) {
180: if (isModified()) {
181: log.info(_path.getNativePath() + " has modified jar files");
182: return true;
183: } else
184: return false;
185: }
186:
187: /**
188: * Find all the jars in this directory and add them to jarList.
189: */
190: private void fillJars() {
191: _pathList.clear();
192: _jarList.clear();
193:
194: _fileSet.getPaths(_pathList);
195:
196: for (int i = 0; i < _pathList.size(); i++) {
197: Path jar = _pathList.get(i);
198:
199: addJar(jar);
200: }
201: }
202:
203: public Path getCodePath() {
204: return _fileSet.getDir();
205: }
206:
207: /**
208: * Destroys the loader, closing the jars.
209: */
210: protected void destroy() {
211: clearJars();
212: }
213:
214: public String toString() {
215: return getClass().getSimpleName() + "[" + _fileSet + "]";
216: }
217: }
|