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: * If you wish your version of this file to be governed by only the CDDL
025: * or only the GPL Version 2, indicate your decision by adding
026: * "[Contributor] elects to include this software in this distribution
027: * under the [CDDL or GPL Version 2] license." If you do not indicate a
028: * single choice of license, a recipient has the option to distribute
029: * your version of this file under either the CDDL, the GPL Version 2 or
030: * to extend the choice of license to its licensees as provided above.
031: * However, if you add GPL Version 2 code and therefore, elected the GPL
032: * Version 2 license, then the option applies only if the new code is
033: * made subject to such option by the copyright holder.
034: *
035: * Contributor(s):
036: *
037: * Portions Copyrighted 2007 Sun Microsystems, Inc.
038: */
039:
040: package org.netbeans.modules.java.api.common.classpath.j2ee;
041:
042: import org.netbeans.modules.java.api.common.classpath.*;
043: import java.beans.PropertyChangeEvent;
044: import java.beans.PropertyChangeListener;
045: import java.io.File;
046: import java.util.ArrayList;
047: import java.util.Arrays;
048: import java.util.Map;
049: import java.util.HashMap;
050:
051: import java.util.List;
052: import org.netbeans.api.java.classpath.ClassPath;
053: import org.netbeans.modules.java.api.common.SourceRoots;
054: import org.netbeans.spi.java.classpath.ClassPathFactory;
055: import org.netbeans.spi.java.classpath.ClassPathProvider;
056: import org.netbeans.spi.java.project.classpath.support.ProjectClassPathSupport;
057: import org.netbeans.spi.project.support.ant.AntProjectHelper;
058: import org.netbeans.spi.project.support.ant.PropertyEvaluator;
059: import org.openide.filesystems.FileObject;
060: import org.openide.filesystems.FileUtil;
061: import org.openide.util.Parameters;
062: import org.openide.util.WeakListeners;
063:
064: // will be moved to j2ee.common
065: // XXX improve javadoc
066: /**
067: * Defines the various class paths for a web project.
068: * @since 1.21
069: */
070: public final class ClassPathProviderImpl implements ClassPathProvider,
071: PropertyChangeListener {
072:
073: private final DefaultClassPathProviderImpl delegate;
074: private final AntProjectHelper helper;
075: private final File projectDirectory;
076: private final PropertyEvaluator evaluator;
077: private final SourceRoots sourceRoots;
078: private final SourceRoots testSourceRoots;
079:
080: private final Properties properties;
081:
082: private final Map<ClassPathCache, ClassPath> cache = new HashMap<ClassPathCache, ClassPath>();
083: private final Map<String, FileObject> dirCache = new HashMap<String, FileObject>();
084:
085: /**
086: * Type of file classpath is required for.
087: */
088: private static enum FileType {
089: UNKNOWN, WEB_SOURCE
090: // web source
091: }
092:
093: /**
094: * Constants for different cached classpaths.
095: */
096: private static enum ClassPathCache {
097: SOURCE_COMPILATION, SOURCE_RUNTIME, WEB_SOURCE, PLATFORM
098: }
099:
100: public ClassPathProviderImpl(AntProjectHelper helper,
101: PropertyEvaluator evaluator, SourceRoots sourceRoots,
102: SourceRoots testSourceRoots, Properties properties) {
103:
104: delegate = new DefaultClassPathProviderImpl(helper, evaluator,
105: sourceRoots, testSourceRoots, properties.delegate);
106: this .helper = helper;
107: this .projectDirectory = FileUtil.toFile(helper
108: .getProjectDirectory());
109: this .evaluator = evaluator;
110: this .sourceRoots = sourceRoots;
111: this .testSourceRoots = testSourceRoots;
112: evaluator.addPropertyChangeListener(WeakListeners
113: .propertyChange(this , evaluator));
114: this .properties = properties;
115: }
116:
117: private synchronized FileObject getDir(String propname) {
118: FileObject fo = dirCache.get(propname);
119: if (fo == null || !fo.isValid()) {
120: String prop = evaluator.getProperty(propname);
121: if (prop != null) {
122: fo = helper.resolveFileObject(prop);
123: dirCache.put(propname, fo);
124: }
125: }
126: return fo;
127: }
128:
129: private FileObject getDocumentBaseDir() {
130: if (properties.webDocBaseDir == null) {
131: return null;
132: }
133: return getDir(properties.webDocBaseDir);
134: }
135:
136: /**
137: * Find what a given file represents.
138: * @param file a file in the project
139: * @return one of FileType.* constants
140: */
141: private FileType getType(FileObject file) {
142: FileObject dir = getDocumentBaseDir();
143: if (dir != null
144: && (dir.equals(file) || FileUtil.isParentOf(dir, file))) {
145: return FileType.WEB_SOURCE;
146: }
147: return FileType.UNKNOWN;
148: }
149:
150: private synchronized ClassPath getCompileTimeClasspath(FileType type) {
151: ClassPath cp = null;
152: switch (type) {
153: case WEB_SOURCE:
154: // XXX should be same like for (java) SOURCE
155: // treat this type as source
156: cp = cache.get(ClassPathCache.SOURCE_COMPILATION);
157: if (cp == null) {
158: cp = ClassPathFactory
159: .createClassPath(ProjectClassPathSupport
160: .createPropertyBasedClassPathImplementation(
161: projectDirectory,
162: evaluator,
163: properties.sourceCompileTimeClassPath));
164: cache.put(ClassPathCache.SOURCE_COMPILATION, cp);
165: }
166: break;
167:
168: default:
169: // XXX any exception?
170: break;
171: }
172: return cp;
173: }
174:
175: private synchronized ClassPath getRunTimeClasspath(FileType type) {
176: ClassPath cp = null;
177: switch (type) {
178: case WEB_SOURCE:
179: // XXX should be same like for (java) SOURCE
180: // treat this type as source
181: cp = cache.get(ClassPathCache.SOURCE_RUNTIME);
182: if (cp == null) {
183: cp = ClassPathFactory
184: .createClassPath(ProjectClassPathSupport
185: .createPropertyBasedClassPathImplementation(
186: projectDirectory,
187: evaluator,
188: properties.sourceRunTimeClassPath));
189: cache.put(ClassPathCache.SOURCE_RUNTIME, cp);
190: }
191: break;
192:
193: default:
194: // XXX any exception?
195: break;
196: }
197: return cp;
198: }
199:
200: private synchronized ClassPath getSourcePath(FileType type) {
201: ClassPath cp = null;
202: switch (type) {
203: case WEB_SOURCE:
204: cp = cache.get(ClassPathCache.WEB_SOURCE);
205: if (cp == null) {
206: List<ClassPath> classPaths;
207: if (properties.additionalSourcePaths != null) {
208: classPaths = Arrays
209: .asList(properties.additionalSourcePaths);
210: } else {
211: classPaths = new ArrayList<ClassPath>(1);
212: }
213: classPaths.add(ClassPathFactory
214: .createClassPath(new SourcePathImplementation(
215: sourceRoots, helper, evaluator)));
216: cp = org.netbeans.spi.java.classpath.support.ClassPathSupport
217: .createProxyClassPath(classPaths
218: .toArray(new ClassPath[classPaths
219: .size()]));
220: cache.put(ClassPathCache.WEB_SOURCE, cp);
221: }
222: break;
223:
224: default:
225: // XXX any exception?
226: break;
227: }
228: return cp;
229: }
230:
231: public synchronized ClassPath getJ2eePlatformClassPath() {
232: ClassPath cp = cache.get(ClassPathCache.PLATFORM);
233: if (cp == null) {
234: cp = ClassPathFactory
235: .createClassPath(ProjectClassPathSupport
236: .createPropertyBasedClassPathImplementation(
237: projectDirectory, evaluator,
238: properties.javaEEPlatformClasspath));
239: cache.put(ClassPathCache.PLATFORM, cp);
240: }
241: return cp;
242: }
243:
244: public ClassPath findClassPath(FileObject file, String type) {
245: ClassPath cp = null;
246: FileType fileType = getType(file);
247: switch (fileType) {
248: case WEB_SOURCE:
249: // XXX should be solved somehow better
250: if (type.equals(ClassPath.COMPILE)) {
251: cp = getCompileTimeClasspath(fileType);
252: } else if (type.equals(ClassPath.EXECUTE)) {
253: cp = getRunTimeClasspath(fileType);
254: } else if (type.equals(ClassPath.SOURCE)) {
255: cp = getSourcePath(fileType);
256: }
257: break;
258: default:
259: cp = delegate.findClassPath(file, type);
260: break;
261: }
262: return cp;
263: }
264:
265: /**
266: * Return array of all classpaths of the given type in the project.
267: * The result is used for example for GlobalPathRegistry registrations.
268: * @param type classpath type - boot, compile or source, see {@link ClassPath} for more information.
269: * @return array of all classpaths of the given type in the project.
270: */
271: public ClassPath[] getProjectClassPaths(String type) {
272: if (ClassPath.SOURCE.equals(type)) {
273: // XXX
274: List<ClassPath> sourcePaths = Arrays.asList(delegate
275: .getProjectClassPaths(type));
276: sourcePaths.add(1, getSourcePath(FileType.WEB_SOURCE));
277: return sourcePaths
278: .toArray(new ClassPath[sourcePaths.size()]);
279: }
280: return delegate.getProjectClassPaths(type);
281: }
282:
283: /**
284: * Return the given type of the classpath for the project sources
285: * (i.e., excluding tests roots).
286: * @param type classpath type - boot, compile or source, see {@link ClassPath} for more information.
287: * @return the given type of the classpath for the project sources.
288: */
289: public ClassPath getProjectSourcesClassPath(String type) {
290: return delegate.getProjectSourcesClassPath(type);
291: }
292:
293: public void propertyChange(PropertyChangeEvent evt) {
294: if (properties.webDocBaseDir.equals(evt.getPropertyName())) {
295: dirCache.remove(evt.getPropertyName());
296: } else {
297: delegate.propertyChange(evt);
298: }
299: }
300:
301: /**
302: * Clear directory cache. This method can be suitable while listening to some properties,
303: * e.g. {@link org.netbeans.spi.project.support.ant.AntProjectListener#configurationXmlChanged(AntProjectEvent)}.
304: */
305: public synchronized void clearDirectoryCache() {
306: delegate.clearDirectoryCache();
307: dirCache.clear();
308: }
309:
310: /**
311: * Class holding different properties like "javac.classpath" etc.
312: */
313: public static final class Properties {
314:
315: final DefaultClassPathProviderImpl.Properties delegate;
316:
317: final String webDocBaseDir;
318:
319: final String[] sourceCompileTimeClassPath;
320: final String[] sourceRunTimeClassPath;
321: final String[] javaEEPlatformClasspath;
322:
323: final ClassPath[] additionalSourcePaths;
324:
325: // XXX add javadoc
326: public Properties(String buildClassesDir,
327: String buildTestClassesDir, String distJar,
328: String webDocBaseDir,
329: String[] sourceCompileTimeClassPath,
330: String[] testSourceCompileTimeClassPath,
331: String[] sourceRunTimeClassPath,
332: String[] testSourceRunTimeClassPath,
333: String[] javaEEPlatformClasspath,
334: ClassPath[] additionalSourcePaths) {
335: Parameters.notNull("javaEEPlatformClasspath",
336: javaEEPlatformClasspath); // NOI18N
337:
338: delegate = new DefaultClassPathProviderImpl.Properties(
339: buildClassesDir, buildTestClassesDir, distJar,
340: sourceCompileTimeClassPath,
341: testSourceCompileTimeClassPath,
342: sourceRunTimeClassPath, testSourceRunTimeClassPath);
343: this.webDocBaseDir = webDocBaseDir;
344: this.sourceCompileTimeClassPath = sourceCompileTimeClassPath;
345: this.sourceRunTimeClassPath = sourceRunTimeClassPath;
346: this.javaEEPlatformClasspath = javaEEPlatformClasspath;
347: this.additionalSourcePaths = additionalSourcePaths;
348: }
349: }
350: }
|