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: package org.netbeans.modules.web.project;
042:
043: import java.beans.PropertyChangeEvent;
044: import java.beans.PropertyChangeListener;
045: import java.io.File;
046: import java.util.ArrayList;
047: import java.util.Collections;
048: import java.util.Map;
049: import java.util.HashMap;
050: import java.util.List;
051: import org.netbeans.api.project.SourceGroup;
052: import org.netbeans.api.project.Sources;
053: import org.netbeans.modules.gsfpath.api.classpath.ClassPath;
054: import org.netbeans.modules.gsfpath.spi.classpath.ClassPathFactory;
055: import org.netbeans.modules.gsfpath.spi.classpath.ClassPathImplementation;
056: import org.netbeans.modules.gsfpath.spi.classpath.ClassPathProvider;
057: import org.netbeans.modules.gsfpath.spi.classpath.PathResourceImplementation;
058: import org.netbeans.spi.project.support.ant.AntProjectHelper;
059: import org.netbeans.spi.project.support.ant.PropertyEvaluator;
060: import org.openide.filesystems.FileObject;
061: import org.openide.filesystems.FileUtil;
062: import org.openide.util.WeakListeners;
063:
064: /**
065: * Defines the various class paths for a J2SE project.
066: */
067: public final class GsfClassPathProviderImpl implements
068: ClassPathProvider, PropertyChangeListener {
069: private final AntProjectHelper helper;
070: private final File projectDirectory;
071: private final PropertyEvaluator evaluator;
072: private final WebSources sourceRoots;
073: private final ClassPath[] cache = new ClassPath[8];
074:
075: private final Map<String, FileObject> dirCache = new HashMap<String, FileObject>();
076:
077: public GsfClassPathProviderImpl(AntProjectHelper helper,
078: PropertyEvaluator evaluator, WebSources sources) {
079: this .helper = helper;
080: this .projectDirectory = FileUtil.toFile(helper
081: .getProjectDirectory());
082: assert this .projectDirectory != null;
083: this .evaluator = evaluator;
084: this .sourceRoots = sources;
085: evaluator.addPropertyChangeListener(WeakListeners
086: .propertyChange(this , evaluator));
087: }
088:
089: private synchronized FileObject getDir(String propname) {
090: FileObject fo = (FileObject) this .dirCache.get(propname);
091: if (fo == null || !fo.isValid()) {
092: String prop = evaluator.getProperty(propname);
093: if (prop != null) {
094: fo = helper.resolveFileObject(prop);
095: this .dirCache.put(propname, fo);
096: }
097: }
098: return fo;
099: }
100:
101: private FileObject[] getPrimarySrcPath() {
102: List<FileObject> roots = new ArrayList<FileObject>();
103: SourceGroup[] sourceGroups = sourceRoots
104: .getSourceGroups(Sources.TYPE_GENERIC);
105: for (SourceGroup sg : sourceGroups) {
106: roots.add(sg.getRootFolder());
107: }
108:
109: return roots.toArray(new FileObject[roots.size()]);
110: }
111:
112: /**
113: * Find what a given file represents.
114: * @param file a file in the project
115: * @return one of: <dl>
116: * <dt>0</dt> <dd>normal source</dd>
117: * <dt>1</dt> <dd>test source</dd>
118: * <dt>2</dt> <dd>built class (unpacked)</dd>
119: * <dt>3</dt> <dd>built test class</dd>
120: * <dt>4</dt> <dd>built class (in dist JAR)</dd>
121: * <dt>-1</dt> <dd>something else</dd>
122: * </dl>
123: */
124: private int getType(FileObject file) {
125: // ALL files in the Rails project are considered sources - we don't have
126: // separate test roots etc.
127: // TODO - check if files are even within the project?
128: return 0;
129: }
130:
131: private synchronized ClassPath getSourcepath(FileObject file) {
132: int type = getType(file);
133: return this .getSourcepath(type);
134: }
135:
136: private ClassPath getSourcepath(int type) {
137: if (type < 0 || type > 1) {
138: return null;
139: }
140: ClassPath cp = cache[type];
141: if (cp == null) {
142: switch (type) {
143: case 0:
144: cp = ClassPathFactory
145: .createClassPath(new GsfSourcePathImplementation(
146: this .sourceRoots, helper, evaluator));
147: break;
148: //case 1:
149: // cp = ClassPathFactory.createClassPath(new SourcePathImplementation (this.testSourceRoots));
150: // break;
151: }
152: }
153: cache[type] = cp;
154: return cp;
155: }
156:
157: private synchronized ClassPath getBootClassPath() {
158: ClassPath cp = cache[7];
159: if (cp == null) {
160: cp = ClassPathFactory
161: .createClassPath(new GsfBootClassPathImplementation(
162: projectDirectory, evaluator));
163: cache[7] = cp;
164: }
165: return cp;
166: }
167:
168: public ClassPath findClassPath(FileObject file, String type) {
169: /*if (type.equals(ClassPath.EXECUTE)) {
170: return getRunTimeClasspath(file);
171: } else */if (type.equals(ClassPath.SOURCE)) {
172: return getSourcepath(file);
173: } else if (type.equals(ClassPath.BOOT)) {
174: return getBootClassPath();
175: } else if (type.equals(ClassPath.COMPILE)) {
176: // Bogus
177: return getBootClassPath();
178: } else {
179: return null;
180: }
181: }
182:
183: /**
184: * Returns array of all classpaths of the given type in the project.
185: * The result is used for example for GlobalPathRegistry registrations.
186: */
187: public ClassPath[] getProjectClassPaths(String type) {
188: if (ClassPath.BOOT.equals(type)) {
189: return new ClassPath[] { getBootClassPath() };
190: }
191: //if (ClassPath.COMPILE.equals(type)) {
192: // ClassPath[] l = new ClassPath[2];
193: // l[0] = getCompileTimeClasspath(0);
194: // l[1] = getCompileTimeClasspath(1);
195: // return l;
196: //}
197: if (ClassPath.SOURCE.equals(type)) {
198: ClassPath[] l = new ClassPath[1];
199: l[0] = getSourcepath(0);
200: //l[1] = getSourcepath(1);
201: return l;
202: }
203: return null;
204: }
205:
206: /**
207: * Returns the given type of the classpath for the project sources
208: * (i.e., excluding tests roots). Valid types are BOOT, SOURCE and COMPILE.
209: */
210: public ClassPath getProjectSourcesClassPath(String type) {
211: if (ClassPath.BOOT.equals(type)) {
212: return getBootClassPath();
213: }
214: if (ClassPath.SOURCE.equals(type)) {
215: return getSourcepath(0);
216: }
217: if (ClassPath.COMPILE.equals(type)) {
218: return getBootClassPath();
219: }
220: return null;
221: }
222:
223: public synchronized void propertyChange(PropertyChangeEvent evt) {
224: dirCache.remove(evt.getPropertyName());
225: }
226: }
|