# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: H:\work\nbsrc\apisupport.project # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: src/org/netbeans/modules/apisupport/project/resources/defaultLookup.png --- src/org/netbeans/modules/apisupport/project/resources/defaultLookup.png Base (BASE) +++ src/org/netbeans/modules/apisupport/project/resources/defaultLookup.png Locally New Index: src/org/netbeans/modules/apisupport/project/ui/ImportantFilesNodeFactory.java --- src/org/netbeans/modules/apisupport/project/ui/ImportantFilesNodeFactory.java Base (BASE) +++ src/org/netbeans/modules/apisupport/project/ui/ImportantFilesNodeFactory.java Locally Modified (Based On LOCAL) @@ -55,6 +55,7 @@ import org.netbeans.modules.apisupport.project.layers.LayerNode; import org.netbeans.modules.apisupport.project.layers.LayerUtils; import org.netbeans.modules.apisupport.project.suite.SuiteProject; +import org.netbeans.modules.apisupport.project.ui.services.ServicesChildFactory; import org.netbeans.spi.project.ui.support.NodeFactory; import org.netbeans.spi.project.ui.support.NodeList; import org.openide.ErrorManager; @@ -246,6 +247,8 @@ } } else if (key instanceof LayerUtils.LayerHandle) { return new Node[] {/* #68240 */ new SpecialFileNode(new LayerNode((LayerUtils.LayerHandle) key), null)}; + } else if (key instanceof ImportantFilesChildren) { + return new Node[] { ServicesChildFactory.createRoot(project) }; } else { throw new AssertionError(key); } @@ -254,6 +257,7 @@ private void refreshKeys() { Set files = new HashSet(); List newVisibleFiles = new ArrayList(); + newVisibleFiles.add (this); LayerUtils.LayerHandle handle = LayerUtils.layerForProject(project); FileObject layerFile = handle.getLayerFile(); if (layerFile != null) { Index: src/org/netbeans/modules/apisupport/project/ui/services/Bundle.properties --- src/org/netbeans/modules/apisupport/project/ui/services/Bundle.properties Base (BASE) +++ src/org/netbeans/modules/apisupport/project/ui/services/Bundle.properties Locally New @@ -0,0 +1,38 @@ +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# +# The contents of this file are subject to the terms of either the GNU +# General Public License Version 2 only ("GPL") or the Common +# Development and Distribution License("CDDL") (collectively, the +# "License"). You may not use this file except in compliance with the +# License. You can obtain a copy of the License at +# http://www.netbeans.org/cddl-gplv2.html +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the +# specific language governing permissions and limitations under the +# License. When distributing the software, include this License Header +# Notice in each file and include the License file at +# nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the GPL Version 2 section of the License file that +# accompanied this code. If applicable, add the following below the +# License Header, with the fields enclosed by brackets [] replaced by +# your own identifying information: +# "Portions Copyrighted [year] [name of copyright owner]" +# +# If you wish your version of this file to be governed by only the CDDL +# or only the GPL Version 2, indicate your decision by adding +# "[Contributor] elects to include this software in this distribution +# under the [CDDL or GPL Version 2] license." If you do not indicate a +# single choice of license, a recipient has the option to distribute +# your version of this file under either the CDDL, the GPL Version 2 or +# to extend the choice of license to its licensees as provided above. +# However, if you add GPL Version 2 code and therefore, elected the GPL +# Version 2 license, then the option applies only if the new code is +# made subject to such option by the copyright holder. +# +# Contributor(s): +# +# Portions Copyrighted 2009 Sun Microsystems, Inc. + +SERVICES=Default Lookup Index: src/org/netbeans/modules/apisupport/project/ui/services/ServiceNode.java --- src/org/netbeans/modules/apisupport/project/ui/services/ServiceNode.java Base (BASE) +++ src/org/netbeans/modules/apisupport/project/ui/services/ServiceNode.java Locally New @@ -0,0 +1,80 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ + +package org.netbeans.modules.apisupport.project.ui.services; + +import java.awt.Image; +import javax.swing.Action; +import org.openide.actions.EditAction; +import org.openide.actions.OpenAction; +import org.openide.cookies.EditCookie; +import org.openide.cookies.OpenCookie; +import org.openide.nodes.FilterNode; +import org.openide.nodes.Node; +import org.openide.util.ImageUtilities; +import org.openide.util.actions.SystemAction; + +/** + * + * @author Tim Boudreau + */ +final class ServiceNode extends FilterNode { + public ServiceNode(Node nodeDelegate, String fqn) { + super (nodeDelegate); + disableDelegation(DELEGATE_SET_DISPLAY_NAME); + disableDelegation(DELEGATE_GET_DISPLAY_NAME); + //PENDING: Could listen for name changes instead of + //relying on parent node refresh + setDisplayName(fqn); + } + + @Override + public Action[] getActions (boolean ignored) { + EditCookie ec = getLookup().lookup(EditCookie.class); + if (ec != null) { + return new Action[] { SystemAction.get(EditAction.class) }; + } else { + OpenCookie oc = getLookup().lookup(OpenCookie.class); + if (oc != null) { + return new Action[] { SystemAction.get(OpenAction.class) }; + } + } + return new Action[0]; + } +} Index: src/org/netbeans/modules/apisupport/project/ui/services/ServicesChildFactory.java --- src/org/netbeans/modules/apisupport/project/ui/services/ServicesChildFactory.java Base (BASE) +++ src/org/netbeans/modules/apisupport/project/ui/services/ServicesChildFactory.java Locally New @@ -0,0 +1,188 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.apisupport.project.ui.services; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.project.Project; +import org.netbeans.modules.apisupport.project.NbModuleProject; +import org.netbeans.modules.apisupport.project.queries.ClassPathProviderImpl; +import org.netbeans.spi.java.classpath.ClassPathProvider; +import org.openide.filesystems.FileChangeAdapter; +import org.openide.filesystems.FileEvent; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileRenameEvent; +import org.openide.loaders.DataObject; +import org.openide.loaders.DataObjectNotFoundException; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.util.Exceptions; +import org.openide.util.NbBundle; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author Tim Boudreau + */ +public final class ServicesChildFactory extends ChildFactory.Detachable implements PropertyChangeListener { + private static final String ICON_BASE = + "org/netbeans/modules/apisupport/project/resources/defaultLookup.png"; //NOI18N + private final Project project; + private final Set paths = Collections.synchronizedSet(new HashSet()); + private final FL fl = new FL(); + + public ServicesChildFactory(Project p) { + this.project = p; + } + + public static Node createRoot(Project project) { + AbstractNode result = new AbstractNode(Children.create( + new ServicesChildFactory(project), true), Lookups.singleton(project)); + result.setDisplayName(NbBundle.getMessage(ServicesChildFactory.class, + "SERVICES")); //NOI18N + result.setIconBaseWithExtension(ICON_BASE); + return result; + } + + @Override + protected boolean createKeys(final List toPopulate) { + ClassPathProviderImpl prov = project.getLookup().lookup(ClassPathProviderImpl.class); + TypeFinder.Callback cb = new TypeFinder.Callback() { + public void foundFileObject(FileObject fo, String className) { + toPopulate.add(new ServicesEntry(fo, className)); + paths.add(fo.getPath()); + } + }; + if (prov != null) { + for (ClassPath srcPath : prov.getProjectClassPaths(ClassPath.SOURCE)) { + TypeFinder finder = new TypeFinder(ServiceProvider.class.getName(), srcPath); + finder.findTypes(cb); + } + } + return true; + } + + @Override + protected Node createNodeForKey(ServicesEntry key) { + if (key.fo.isValid()) { + try { + return new ServiceNode(DataObject.find(key.fo).getNodeDelegate(), key.fqn); + } catch (DataObjectNotFoundException ex) { + Exceptions.printStackTrace(ex); + } + } + return null; + } + + public void propertyChange(PropertyChangeEvent evt) { + if (ClassPath.PROP_ROOTS.equals(evt.getPropertyName())) { + refresh(true); + } + } + + @Override + protected void addNotify() { + super.addNotify(); + ClassPathProvider prov = project.getLookup().lookup(ClassPathProvider.class); + NbModuleProject m = (NbModuleProject) project; + if (prov != null) { + ClassPath srcPath = prov.findClassPath(m.getSourceDirectory(), ClassPath.SOURCE); + init(srcPath); + } + } + + @Override + protected void removeNotify() { + ClassPathProvider prov = project.getLookup().lookup(ClassPathProvider.class); + NbModuleProject m = (NbModuleProject) project; + if (prov != null) { + ClassPath srcPath = prov.findClassPath(m.getSourceDirectory(), ClassPath.SOURCE); + uninit(srcPath); + } + super.removeNotify(); + } + + private void init(ClassPath srcPath) { + srcPath.addPropertyChangeListener(this); + for (FileObject root : srcPath.getRoots()) { + root.addFileChangeListener(fl); + } + } + + private void uninit(ClassPath srcPath) { + srcPath.removePropertyChangeListener(this); + for (FileObject root : srcPath.getRoots()) { + root.removeFileChangeListener(fl); + } + } + + private class FL extends FileChangeAdapter { + + @Override + public void fileChanged(FileEvent fe) { + FileObject fo = (FileObject) fe.getSource(); + if ("text/x-java".equals(fo.getMIMEType())) { //NOI18N + String path = fo.getPath(); + if (!paths.contains(path)) { + //XXX scan just this file, not everything + refresh(false); + } + } + } + + @Override + public void fileRenamed(FileRenameEvent fe) { + FileObject fo = (FileObject) fe.getSource(); + if ("text/x-java".equals(fo.getMIMEType())) { //NOI18N + String path = fo.getParent().getPath() + "/" + fe.getName() + "." + fe.getExt(); + if (paths.contains(path)) { + refresh(false); + } + } + } + } +} Index: src/org/netbeans/modules/apisupport/project/ui/services/ServicesEntry.java --- src/org/netbeans/modules/apisupport/project/ui/services/ServicesEntry.java Base (BASE) +++ src/org/netbeans/modules/apisupport/project/ui/services/ServicesEntry.java Locally New @@ -0,0 +1,15 @@ +package org.netbeans.modules.apisupport.project.ui.services; + +import org.openide.filesystems.FileObject; + +public final class ServicesEntry { + + FileObject fo; + String fqn; + + public ServicesEntry(FileObject fo, String fqn) { + super(); + this.fo = fo; + this.fqn = fqn; + } +} Index: src/org/netbeans/modules/apisupport/project/ui/services/TypeFinder.java --- src/org/netbeans/modules/apisupport/project/ui/services/TypeFinder.java Base (BASE) +++ src/org/netbeans/modules/apisupport/project/ui/services/TypeFinder.java Locally New @@ -0,0 +1,203 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + */ +package org.netbeans.modules.apisupport.project.ui.services; + +import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.TreeVisitor; +import com.sun.source.util.SimpleTreeVisitor; +import com.sun.source.util.TreePath; +import com.sun.source.util.Trees; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.source.CancellableTask; +import org.netbeans.api.java.source.CompilationController; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.JavaSource.Phase; +import org.openide.filesystems.FileObject; + +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.awt.*; +import java.io.IOException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.openide.util.Parameters; + +/** + * Scans a classpath and finds all subtypes of a given type. + * + * @author Tim Boudreau + */ +public class TypeFinder implements CancellableTask { + private volatile boolean cancelled; + private final ClassPath classpath; + private final String fqn; + private Callback callback; + + public TypeFinder(String fqn, ClassPath path) { + this.classpath = path; + this.fqn = fqn; + Parameters.notNull ("Classpath", path); //NOI18N + Parameters.notNull ("AnnotationName", fqn); //NOI18N + } + + public interface Callback { + public void foundFileObject(FileObject fo, String className); + } + + public void findTypes(Callback callback) { + //Don't ever do this kind of IO-heavy work on the event thread + assert !EventQueue.isDispatchThread(); + this.callback = callback; + //recursively iterate all children + for (FileObject fo : classpath.getRoots()) { + analyze(fo); + } + } + + + private void analyze(FileObject fo) { + if (fo.isFolder()) { + for (FileObject child : fo.getChildren()) { + analyze(child); + } + } else if ("java".equals(fo.getExt())) { //NOI18N + JavaSource src = JavaSource.forFileObject(fo); + try { + src.runUserActionTask(this, true); + } catch (IOException ex) { + Logger.getLogger(TypeFinder.class.getName()).log(Level.INFO, + "Problem scanning " + fo.getPath(), ex); //NOI18N + } + } + } + + public void reset() { + cancelled = false; + } + + public void cancel() { + cancelled = true; + } + + public void run(CompilationController compiler) throws Exception { + if (cancelled) { + return; + } + compiler.toPhase(Phase.RESOLVED); + if (cancelled) { + return; + } + List types = + compiler.getCompilationUnit().getTypeDecls(); + for (Tree tree: types) { + if (cancelled) { + return; + } + TypeMirror mirror = compiler.getTrees().getTypeMirror( + TreePath.getPath(compiler.getCompilationUnit(), + tree)); + if (tree instanceof ClassTree && match(compiler, (ClassTree) tree)) { + callback.foundFileObject(compiler.getFileObject(), + mirror.toString()); + } + } + } + + boolean match(CompilationController compiler, ClassTree t) { +// compiler.getTrees(), compiler.getTypes(), compiler.getCompilationUnit()/ +// TypeMirror mirror = trees.getTypeMirror(TreePath.getPath(unit, t)); + V v = new V(compiler); + return t.accept(v, callback); +// return match(mirror, types); + } + + /* + boolean match(TypeMirror mirror, Types types) { + boolean result = false; + if (mirror != null && + !"java.lang.Object".equals(mirror.toString())) { //NOI18N + + result = fqn.equals(mirror.toString()); + if (!result) { + List l = + types.directSupertypes(mirror); + + for (TypeMirror tm : l) { + result = match(tm, types); + if (cancelled) return result; + if (result) break; + } + } + } + return result; + } + */ + + private class V extends SimpleTreeVisitor { + private final CompilationController compiler; + V (CompilationController compiler) { + this.compiler = compiler; + } + + @Override + public Boolean visitAnnotation(AnnotationTree node, Callback p) { + TypeMirror mirror = compiler.getTrees().getTypeMirror(TreePath.getPath(compiler.getCompilationUnit(), node)); + return fqn.equals (mirror.toString()); + } + + @Override + public Boolean visitClass(ClassTree node, Callback p) { + boolean result = false; + for (AnnotationTree t : node.getModifiers().getAnnotations()) { + result = visitAnnotation(t, p); + if (result) { + break; + } + } + return result; + } + + } +}