2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.netbeans.modules.j2ee.clientproject.queries;
44
import org.netbeans.spi.java.queries.SourceForBinaryQueryImplementation;
45
import org.netbeans.spi.project.support.ant.AntProjectHelper;
46
import org.openide.filesystems.FileObject;
47
import org.openide.filesystems.FileUtil;
50
import java.net.MalformedURLException;
51
import java.beans.PropertyChangeListener;
52
import java.beans.PropertyChangeEvent;
53
import java.util.ArrayList;
54
import java.util.Iterator;
56
import java.util.HashMap;
57
import javax.swing.event.ChangeListener;
58
import javax.swing.event.ChangeEvent;
60
import org.netbeans.api.java.queries.SourceForBinaryQuery;
61
import org.netbeans.spi.project.support.ant.PropertyEvaluator;
62
import org.netbeans.modules.j2ee.clientproject.SourceRoots;
63
import org.netbeans.modules.j2ee.clientproject.ui.customizer.AppClientProjectProperties;
64
import org.openide.util.Exceptions;
67
* Finds sources corresponding to binaries in a J2SE project.
68
* @author Jesse Glick, Tomas Zezula
70
public class CompiledSourceForBinaryQuery implements SourceForBinaryQueryImplementation {
72
private final AntProjectHelper helper;
73
private final PropertyEvaluator evaluator;
74
private final SourceRoots sourceRoots;
75
private final SourceRoots testRoots;
76
private Map<URL,SourceForBinaryQuery.Result> cache = new HashMap<URL,SourceForBinaryQuery.Result>();
78
public CompiledSourceForBinaryQuery(AntProjectHelper helper, PropertyEvaluator evaluator, SourceRoots srcRoots, SourceRoots testRoots) {
80
this.evaluator = evaluator;
81
this.sourceRoots = srcRoots;
82
this.testRoots = testRoots;
85
public SourceForBinaryQuery.Result findSourceRoots(URL binaryRoot) {
86
if (FileUtil.getArchiveFile(binaryRoot) != null) {
87
binaryRoot = FileUtil.getArchiveFile(binaryRoot);
88
// XXX check whether this is really the root
90
SourceForBinaryQuery.Result res = cache.get(binaryRoot);
94
SourceRoots src = null;
95
if (hasSources(binaryRoot, AppClientProjectProperties.BUILD_CLASSES_DIR)) {
96
src = this.sourceRoots;
97
} else if (hasSources(binaryRoot, AppClientProjectProperties.DIST_JAR)) {
98
src = this.sourceRoots;
99
} else if (hasSources(binaryRoot, AppClientProjectProperties.BUILD_TEST_CLASSES_DIR)) {
100
src = this.testRoots;
105
res = new Result(src);
106
cache.put(binaryRoot, res);
112
private boolean hasSources(URL binaryRoot, String binaryProperty) {
114
String outDir = evaluator.getProperty(binaryProperty);
115
if (outDir != null) {
116
File f = helper.resolveFile(outDir);
117
URL url = f.toURI().toURL();
118
if (!f.exists() && !f.getPath().toLowerCase().endsWith(".jar")) { // NOI18N
120
assert !url.toExternalForm().endsWith("/") : f; // NOI18N
121
url = new URL(url.toExternalForm() + "/"); // NOI18N
123
if (url.equals(binaryRoot)) {
127
} catch (MalformedURLException malformedURL) {
128
Exceptions.printStackTrace(malformedURL);
133
private static class Result implements SourceForBinaryQuery.Result, PropertyChangeListener {
135
private ArrayList<ChangeListener> listeners;
136
private SourceRoots sourceRoots;
138
public Result(SourceRoots sourceRoots) {
139
this.sourceRoots = sourceRoots;
140
this.sourceRoots.addPropertyChangeListener(this);
143
public FileObject[] getRoots() {
144
return this.sourceRoots.getRoots(); //No need to cache it, SourceRoots does
147
public synchronized void addChangeListener(ChangeListener l) {
148
if (this.listeners == null) {
149
this.listeners = new ArrayList<ChangeListener>();
151
this.listeners.add(l);
154
public synchronized void removeChangeListener(ChangeListener l) {
155
if (this.listeners == null) {
158
this.listeners.remove(l);
161
public void propertyChange(PropertyChangeEvent evt) {
162
if (SourceRoots.PROP_ROOTS.equals(evt.getPropertyName())) {
167
private void fireChange() {
168
Iterator<ChangeListener> it;
169
synchronized (this) {
170
if (this.listeners == null) {
173
@SuppressWarnings("unchecked")
174
ArrayList<ChangeListener> cloned = (ArrayList) this.listeners.clone();
175
it = cloned.iterator();
177
ChangeEvent event = new ChangeEvent(this);
178
while (it.hasNext()) {
179
(it.next()).stateChanged(event);