001: /*
002: * Copyright 2006 Luca Garulli (luca.garulli@assetdata.it)
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:
017: package org.romaframework.core.resource;
018:
019: import java.io.BufferedInputStream;
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.IOException;
023: import java.util.ArrayList;
024: import java.util.List;
025: import java.util.StringTokenizer;
026: import java.util.jar.JarEntry;
027: import java.util.jar.JarInputStream;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.romaframework.core.Utility;
032: import org.romaframework.core.config.RomaApplicationContext;
033: import org.romaframework.core.flow.Controller;
034: import org.romaframework.core.util.VariableParser;
035:
036: /**
037: * Resolve entity class and descriptors using the paths configured.
038: *
039: * @author Luca Garulli (luca.garulli@assetdata.it)
040: */
041: public class ResourceResolver {
042:
043: protected List<String> classPaths = new ArrayList<String>();
044: protected List<String> systemPropertiesPaths = new ArrayList<String>();
045:
046: public static final String ANY_FILES = "*";
047: public static final String RELATIVE_PATH = "./";
048: public static final String RELATIVE_PARENT_PATH = "../";
049:
050: protected static String[] ARCHIVE_SUFFIXES = { ".jar", "*.zip" };
051:
052: private static Log log = LogFactory.getLog(ResourceResolver.class);
053:
054: public ResourceResolver() {
055: resolveDefaultClasspaths();
056: }
057:
058: /**
059: * Delegates to the listeners the adding of resource.
060: *
061: * @param iFile
062: * @param iName
063: * @param iPackagePrefix
064: * @param iStartingPackage
065: */
066: protected void addResource(File iFile, String iName,
067: String iPackagePrefix, String iStartingPackage) {
068: List<ResourceResolverListener> listeners = Controller
069: .getInstance().getListeners(
070: ResourceResolverListener.class);
071: if (listeners != null)
072: for (ResourceResolverListener l : listeners) {
073: l.addResource(iFile, iName, iPackagePrefix,
074: iStartingPackage);
075: }
076: }
077:
078: /**
079: * Default accept any resources. Override this to filer interested resources only.
080: *
081: * @param iResource
082: * Resource name
083: * @return true if it's accepted, otherwise false
084: */
085: protected boolean acceptResorce(String iResource) {
086: return true;
087: }
088:
089: protected boolean acceptArchives(String iResource) {
090: for (String res : ARCHIVE_SUFFIXES)
091: if (iResource.endsWith(res))
092: return true;
093: return false;
094:
095: }
096:
097: protected void resolveDefaultClasspaths() {
098: // RESOLVE PATHS
099: String pathLocation;
100: for (String p : systemPropertiesPaths) {
101: pathLocation = System.getProperty(p);
102: if (pathLocation != null)
103: addClassPath(pathLocation);
104: }
105: }
106:
107: public String[] getClassPaths() {
108: return classPaths.toArray(new String[classPaths.size()]);
109: }
110:
111: private void addResolvedClassPath(String iClassPath) {
112: log.debug("[ResourceResolver.addClasspath] " + iClassPath);
113:
114: if (iClassPath.indexOf(File.pathSeparator) > -1) {
115: StringTokenizer tokenizer = new StringTokenizer(iClassPath,
116: File.pathSeparator);
117: while (tokenizer.hasMoreTokens()) {
118: classPaths.add(tokenizer.nextToken());
119: }
120: } else
121: classPaths.add(iClassPath);
122: }
123:
124: public void setClasspaths(List<String> iClassPaths) {
125: log.debug("[ResourceResolver.setClasspaths] " + iClassPaths);
126:
127: for (String path : iClassPaths) {
128: addClassPath(path);
129: }
130: }
131:
132: public void addClassPath(String iPath) {
133: log.debug("[ResourceResolver.addClassPath] Discovering path: "
134: + iPath);
135: String path = iPath.trim();
136:
137: path = VariableParser.resolveSystemVariables(path);
138:
139: if (path.startsWith(RELATIVE_PARENT_PATH)) {
140: // RELATIVE PARENT PATH: PREFIX WITH ./ TO BEING RESOLVED FORWARD
141: path = RELATIVE_PATH + path;
142: }
143:
144: if (path.startsWith(RELATIVE_PATH)) {
145: String appPath = RomaApplicationContext
146: .getApplicationPath();
147:
148: // RELATIVE PATH: PREFIX WITH APPLICATION PATH
149: path = appPath + path.substring(RELATIVE_PATH.length() - 1);
150: }
151:
152: path = Utility.getUniversalResourcePath(path);
153:
154: if (path.contains(ANY_FILES)) {
155: // FOUND WILDCARD: LOAD ALL FILES UNDER THAT DIRECTORY AND INSERT ITS
156: // NAMES AS CLASSPATH
157: String[] pathFolder = Utility
158: .getResourceNamesLastSeparator(path,
159: Utility.PATH_SEPARATOR_STRING, "");
160: File f = new File(pathFolder[0]);
161: if (!f.exists())
162: return;
163:
164: File[] files = f.listFiles();
165: for (File file : files) {
166: if (file.getName().matches(
167: Utility.filePatternToRegExp(pathFolder[1])))
168: addResolvedClassPath(file.getAbsolutePath());
169: }
170: } else
171: // INSERT THE CLASSPATH
172: addResolvedClassPath(path);
173: }
174:
175: public void loadResources(String iStartingPackage) {
176: File f;
177:
178: for (String pathList : classPaths) {
179: if (pathList != null) {
180: if (log.isDebugEnabled())
181: log
182: .debug("[ResourceResolver.loadEntities] Inspecting path: "
183: + pathList);
184:
185: f = new File(pathList);
186: if (log.isDebugEnabled())
187: log
188: .debug("[ResourceResolver.loadEntities] > Inspecting path: "
189: + f.getAbsolutePath());
190:
191: if (f.exists()) {
192: if (f.isDirectory()) {
193: addFiles(f.listFiles(), "", iStartingPackage);
194: } else if (acceptArchives(f.getName())) {
195: examineJarFile(f, iStartingPackage);
196: }
197: }
198: }
199: }
200: }
201:
202: /**
203: * Examine a jar file searching for entities.
204: *
205: * @param f
206: * @throws IOException
207: */
208: protected void examineJarFile(File f, String iStartingPackage) {
209: FileInputStream fis = null;
210: try {
211: fis = new FileInputStream(f);
212:
213: final JarInputStream jis = new JarInputStream(
214: new BufferedInputStream(fis));
215: JarEntry entry;
216: String fullName, packagePrefix, name;
217: int i;
218:
219: while ((entry = jis.getNextJarEntry()) != null) {
220: fullName = entry.getName();
221: if (acceptResorce(fullName)) {
222: i = fullName.lastIndexOf('/') + 1;
223: packagePrefix = fullName.substring(0, i).replace(
224: '/', '.');
225: name = fullName.substring(i, fullName.length());
226: addResource(f, name, packagePrefix,
227: iStartingPackage);
228: }
229: }
230: } catch (Exception e) {
231: } finally {
232: try {
233: fis.close();
234: } catch (IOException e) {
235: }
236: }
237: }
238:
239: protected void addFiles(File[] files, String packagePrefix,
240: String iStartingPackage) {
241: String name;
242:
243: for (int i = 0; i < files.length; i++) {
244: name = files[i].getName();
245: if (files[i].isDirectory()) {
246: addFiles(files[i].listFiles(), packagePrefix + name
247: + ".", iStartingPackage);
248: } else {
249: addResource(files[i], name, packagePrefix,
250: iStartingPackage);
251: }
252: }
253: }
254: }
|