diff --git a/maven.embedder/nbproject/project.xml b/maven.embedder/nbproject/project.xml
--- a/maven.embedder/nbproject/project.xml
+++ b/maven.embedder/nbproject/project.xml
@@ -163,6 +163,7 @@
org.netbeans.modules.maven.repository
org.netbeans.modules.maven.search
org.netbeans.modules.selenium.maven
+ org.netbeans.modules.refactoring.maven
org.apache.maven
org.apache.maven.artifact
diff --git a/maven.indexer/nbproject/project.xml b/maven.indexer/nbproject/project.xml
--- a/maven.indexer/nbproject/project.xml
+++ b/maven.indexer/nbproject/project.xml
@@ -180,6 +180,7 @@
org.netbeans.modules.maven.j2ee
org.netbeans.modules.maven.repository
org.netbeans.modules.maven.search
+ org.netbeans.modules.refactoring.maven
org.netbeans.modules.maven.indexer.api
org.netbeans.modules.maven.indexer.api.ui
org.netbeans.modules.maven.indexer.spi
diff --git a/maven.indexer/src/org/netbeans/modules/maven/indexer/NexusRepositoryIndexerImpl.java b/maven.indexer/src/org/netbeans/modules/maven/indexer/NexusRepositoryIndexerImpl.java
--- a/maven.indexer/src/org/netbeans/modules/maven/indexer/NexusRepositoryIndexerImpl.java
+++ b/maven.indexer/src/org/netbeans/modules/maven/indexer/NexusRepositoryIndexerImpl.java
@@ -41,7 +41,12 @@
*/
package org.netbeans.modules.maven.indexer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
import java.io.FileNotFoundException;
+import java.util.Map.Entry;
import org.apache.maven.index.expr.StringSearchExpression;
import org.codehaus.plexus.util.FileUtils;
import java.util.Map;
@@ -53,6 +58,7 @@
import org.netbeans.modules.maven.indexer.api.NBVersionInfo;
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.util.ArrayList;
@@ -61,13 +67,18 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.TreeMap;
import java.util.TreeSet;
import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@@ -80,7 +91,9 @@
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidArtifactRTException;
@@ -106,10 +119,6 @@
import org.apache.maven.index.creator.AbstractIndexCreator;
import org.apache.maven.index.SearchEngine;
import org.apache.maven.index.context.IndexCreator;
-import org.apache.maven.index.creator.JarFileContentsIndexCreator;
-import org.apache.maven.index.creator.MavenArchetypeArtifactInfoIndexCreator;
-import org.apache.maven.index.creator.MavenPluginArtifactInfoIndexCreator;
-import org.apache.maven.index.creator.MinimalArtifactInfoIndexCreator;
import org.apache.maven.index.updater.IndexUpdateRequest;
import org.apache.maven.index.updater.IndexUpdater;
import org.apache.maven.index.updater.ResourceFetcher;
@@ -140,11 +149,14 @@
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.modules.maven.indexer.spi.ContextLoadedQuery;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
+import org.openide.util.Cancellable;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
@@ -178,6 +190,12 @@
private static final String NB_DEPENDENCY_GROUP = "nbdg"; //NOI18N
private static final String NB_DEPENDENCY_ARTIFACT = "nbda"; //NOI18N
private static final String NB_DEPENDENCY_VERSION = "nbdv"; //NOI18N
+ /** Used for indexing all classes in a local repository artifact: bar.Foo<foo.Bar (class bar.Foo is used by class for.Bar)
+ * < may be confusing to read, but will speed up the lucene prefix search: query: bar.Foo<*
+ */
+ private static final String NB_DEPENDENCY_CLASSES = "nbdc"; //NOI18N
+ /** Used for separating a class and it's dependencies as field value of {@link #NB_DEPENDENCY_CLASSES} bar.Foo<foo.Bar */
+ private static final String NB_DEPENDENCY_CLASS_SEPARATOR = "<";
private static final Logger LOGGER = Logger.getLogger(NexusRepositoryIndexerImpl.class.getName());
/*custom Index creators*/
/**
@@ -281,7 +299,7 @@
LOGGER.log(Level.FINE, "Local context changed: {0}, unload/load", info.getId());
unloadIndexingContext(info);
} else {
- LOGGER.log(Level.FINER, "Skipping Context: {0}, already loaded.", info.getId());
+ LOGGER.log(Level.FINE, "Skipping Context: {0}, already loaded.", info.getId());
break LOAD; // XXX does it suffice to just return here, or is code after block needed?
}
}
@@ -296,17 +314,15 @@
List creators = new ArrayList();
try {
- // XXX MINDEXER-34: maven-plugin must follow min, so using embedder.lookupList(IndexCreator.class) does not work
- for (String id : new String[] {MinimalArtifactInfoIndexCreator.ID, MavenPluginArtifactInfoIndexCreator.ID, MavenArchetypeArtifactInfoIndexCreator.ID, JarFileContentsIndexCreator.ID}) {
- creators.add(embedder.lookup(IndexCreator.class, id));
- }
+ creators.addAll(embedder.lookupList(IndexCreator.class));
} catch (ComponentLookupException x) {
throw new IOException(x);
}
if (info.isLocal()) { // #164593
creators.add(new NbIndexCreator());
+ creators.add(new NbClassDependenciesIndexCreator());
} else {
- creators.add(new NotifyingIndexCreator());
+ creators.add(new NotifyingIndexCreator(info));
}
try {
indexer.addIndexingContextForced(
@@ -317,7 +333,6 @@
info.isRemoteDownloadable() ? info.getRepositoryUrl() : null, // repositoryUrl
info.isRemoteDownloadable() ? indexUpdateUrl : null,
creators);
- LOGGER.log(Level.FINE, "using index creators: {0}", creators);
} catch (IOException ex) {
LOGGER.log(Level.INFO, "Found a broken index at " + loc.getAbsolutePath(), ex);
FileUtils.deleteDirectory(loc);
@@ -517,7 +532,7 @@
}
}
if (nic != null) {
- nic.start(listener);
+ nic.start();
}
try {
remoteIndexUpdater.fetchAndUpdateIndex(iur);
@@ -554,16 +569,38 @@
}
/** Just tracks what is being unpacked after a remote index has been downloaded. */
private static final class NotifyingIndexCreator implements IndexCreator {
- private RemoteIndexTransferListener listener;
- NotifyingIndexCreator() {}
- private void start(RemoteIndexTransferListener listener) {
- this.listener = listener;
+ private final RepositoryInfo beingIndexed;
+ private ProgressHandle handle;
+ private final AtomicBoolean canceled = new AtomicBoolean();
+ NotifyingIndexCreator(RepositoryInfo info) {
+ beingIndexed = info;
+ }
+ private void start() {
+ handle = null;
+ canceled.set(false);
}
private void end() {
- listener = null;
+ if (handle != null) {
+ handle.finish();
+ handle = null;
+ }
+ canceled.set(false);
}
public @Override void updateDocument(ArtifactInfo artifactInfo, Document document) {
- listener.unpackingProgress(artifactInfo.groupId + ':' + artifactInfo.artifactId);
+ if (canceled.get()) {
+ throw new Cancellation();
+ }
+ if (handle == null) {
+ handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(NexusRepositoryIndexerImpl.class, "LBL_unpacking", beingIndexed.getName()), new Cancellable() { {
+ Cancellation.register(this);
+ }
+ public @Override boolean cancel() {
+ return canceled.compareAndSet(false, true);
+ }
+ });
+ handle.start();
+ }
+ handle.progress(artifactInfo.groupId + ':' + artifactInfo.artifactId);
}
public @Override Collection getIndexerFields() {
return Collections.emptySet();
@@ -915,6 +952,61 @@
}
@Override
+ public Set findDependendClassesFromClass(final String className, final List repos) {
+ try {
+ final Set dependendClasses = new HashSet();
+ for (final RepositoryInfo repo : repos) {
+ if (repo.isLocal()) {
+ getRepoMutex(repo).writeAccess(new Mutex.ExceptionAction() {
+
+ public @Override
+ Void run() throws Exception {
+ loadIndexingContext(repo);
+ final String searchString = className.replace(".", "/");
+ // TODO Query is not really efficient, should return only hits which contain: 'className<' in field
+ final Query refClassQuery = indexer.constructQuery(NbClassDependenciesIndexCreator.FLD_NB_DEPENDENCY_CLASS.getOntology(), new StringSearchExpression(searchString));
+ final TopScoreDocCollector collector = TopScoreDocCollector.create(MAX_RESULT_COUNT, true);
+ final Collection contexts = getContexts(new RepositoryInfo[]{repo});
+ final IndexingContext context = (IndexingContext) contexts.toArray()[0];
+ context.getIndexSearcher().search(refClassQuery, collector);
+ final ScoreDoc[] hits = collector.topDocs().scoreDocs;
+ for (ScoreDoc hit : hits) {
+ int docId = hit.doc;
+ Document d = context.getIndexSearcher().doc(docId);
+// LOGGER.log(Level.INFO, className + "uses: " + d.get(NB_DEPENDENCY_CLASSES));
+ final Set refClasses = parseField(searchString, d.get(NB_DEPENDENCY_CLASSES));
+ for (String binaryClass : refClasses) {
+ dependendClasses.add(binaryClass);
+ }
+ }
+ return null;
+ }
+
+ private Set parseField(final String className, final String fldValue) {
+ final Set refClasses = new HashSet();
+ final String[] split = fldValue.split("\n");
+ for (String grp : split) {
+ // TODO this condition is only necessary because the not fully working query --> it filters false positives.
+ if (grp.contains(className + NB_DEPENDENCY_CLASS_SEPARATOR)) {
+ final String classGrp = grp.substring(grp.indexOf(NB_DEPENDENCY_CLASS_SEPARATOR) + 1, grp.length() - 1);
+ final String[] classes = classGrp.split(",");
+ refClasses.addAll(Arrays.asList(classes));
+ }
+ }
+ return refClasses;
+ }
+
+ });
+ }
+ }
+ return dependendClasses;
+ } catch (MutexException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return Collections.emptySet();
+ }
+
+ @Override
public List findDependencyUsage(final String groupId, final String artifactId, final String version, List repos) {
try {
final List infos = new ArrayList();
@@ -1213,8 +1305,9 @@
// we don't want javadoc and sources shown anywhere, we use the getJavadocExists(), getSourceExists() methods.
continue;
}
+ // fextension != packaging - e.g a pom could be packaging "bundle" but from type/extension "jar"
NBVersionInfo nbvi = new NBVersionInfo(ai.repository, ai.groupId, ai.artifactId,
- ai.version, ai.packaging, ai.packaging, ai.name, ai.description, ai.classifier);
+ ai.version, ai.fextension, ai.packaging, ai.name, ai.description, ai.classifier);
/*Javadoc & Sources*/
nbvi.setJavadocExists(ai.javadocExists == ArtifactAvailablility.PRESENT);
nbvi.setSourcesExists(ai.sourcesExists == ArtifactAvailablility.PRESENT);
@@ -1237,7 +1330,292 @@
}
return q;
}
+
+ /**
+ * Scanns every class in all artifacts located in local maven repository for it's class dependencies.
+ */
+ private static class NbClassDependenciesIndexCreator extends AbstractIndexCreator {
+ private final List remoteRepos;
+ NbClassDependenciesIndexCreator() {
+ remoteRepos = new ArrayList();
+ for (RepositoryInfo info : RepositoryPreferences.getInstance().getRepositoryInfos()) {
+ if (!info.isLocal()) {
+ remoteRepos.add(new MavenArtifactRepository(info.getId(), info.getRepositoryUrl(), new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(), new ArtifactRepositoryPolicy()));
+ }
+ }
+ }
+
+ private WeakReference embedderRef = null;
+
+ private MavenEmbedder getEmbedder() {
+ MavenEmbedder res = (null != embedderRef ? embedderRef.get() : null);
+ if (null == res) {
+ res = EmbedderFactory.getOnlineEmbedder();
+ embedderRef = new WeakReference(res);
+ }
+ return res;
+ }
+
+ private MavenProject load(ArtifactInfo ai) {
+ try {
+ Artifact projectArtifact = getEmbedder().createArtifact(
+ ai.groupId,
+ ai.artifactId,
+ ai.version,
+ ai.packaging != null ? ai.packaging : "jar");
+ DefaultProjectBuildingRequest dpbr = new DefaultProjectBuildingRequest();
+ dpbr.setLocalRepository(getEmbedder().getLocalRepository());
+ dpbr.setRemoteRepositories(remoteRepos);
+ dpbr.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
+ dpbr.setSystemProperties(getEmbedder().getSystemProperties());
+
+ ProjectBuildingResult res = getEmbedder().buildProject(projectArtifact, dpbr);
+ if (res.getProject() != null) {
+ return res.getProject();
+ } else {
+ LOGGER.log(Level.FINE, "No project model from repository for {0}: {1}", new Object[]{ai, res.getProblems()});
+ }
+ } catch (ProjectBuildingException ex) {
+ LOGGER.log(Level.FINE, "Failed to load project model from repository for {0}: {1}", new Object[]{ai, ex});
+ } catch (Exception exception) {
+ LOGGER.log(Level.FINE, "Failed to load project model from repository for " + ai, exception);
+ }
+ return null;
+ }
+
+ private Artifact artifact;
+
+ public @Override void populateArtifactInfo(ArtifactContext context) throws IOException {
+ ArtifactInfo ai = context.getArtifactInfo();
+ if (ai.classifier != null) {
+ //don't process items with classifier
+ return;
+ }
+ try {
+ MavenProject mp = load(ai);
+
+ if (mp != null) {
+ artifact = getEmbedder().getLocalRepository().find(mp.getArtifact());
+ ai.setFieldValue(NbClassDependenciesIndexCreator.FLD_NB_DEPENDENCY_CLASS.getOntology(), "empty");
+ }
+ } catch (InvalidArtifactRTException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ @Override
+ public boolean updateArtifactInfo(Document document, ArtifactInfo artifactInfo) {
+ // Add the data to the ArtifactInfo
+ artifactInfo.setFieldValue(NbClassDependenciesIndexCreator.FLD_NB_DEPENDENCY_CLASS.getOntology(), document.get(NB_DEPENDENCY_CLASSES));
+ return true;
+ }
+
+ public @Override void updateDocument(ArtifactInfo ai, Document doc) {
+ final Map> classDeps = new HashMap>();
+ Map classfiles = new TreeMap();
+ File jar = null;
+ if (artifact != null) {
+ // TODO are there any other possible archive types?
+ if (isArchiveSupported(artifact) && isArtifactFileArchive(artifact)) {
+ try {
+ read(new JarFile(artifact.getFile()), classfiles, new HashSet(Collections.singleton(jar)), "");
+ for (Map.Entry entry : classfiles.entrySet()) {
+ String clazz = entry.getKey();
+ byte[] data = entry.getValue();
+ addDependenciesToMap(clazz, data, classDeps);
+ }
+ addMapToIndex(classDeps, doc);
+ } catch (IOException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ }
+ }
+
+ private boolean isArtifactFileArchive(final Artifact arti) {
+ final File artifactFile = arti.getFile();
+ return artifactFile != null && artifactFile.exists();
+ }
+
+ private boolean isArchiveSupported(final Artifact arti) {
+ final String type = arti.getType();
+ if (type.equals("jar")) {
+ return true;
+ } else if (type.equals("war")) {
+ return true;
+ }
+ return false;
+ }
+
+ private void addDependenciesToMap(final String clazz, final byte[] data, final Map> depsMap) throws IOException{
+ //log("Verifying linkage of " + clazz.replace('/', '.'), Project.MSG_DEBUG);
+ final Set dependencies = dependencies(data);
+
+ for (String usedClass : dependencies) {
+ // filter classes out which are referring themselfs
+ if (!usedClass.equals(clazz)) {
+ Set refClasses = depsMap.get(usedClass);
+ if (refClasses == null) {
+ refClasses = new HashSet();
+ depsMap.put(usedClass, refClasses);
+ }
+ refClasses.add(clazz);
+ }
+ }
+ }
+
+ private void addMapToIndex(final Map> classDeps, final Document doc) {
+ final StringBuilder fldBuilder = new StringBuilder();
+ for (Entry> entry : classDeps.entrySet()) {
+ String usedClass = entry.getKey();
+ // add usedClass with a separator
+ fldBuilder.append(usedClass.replace(".", "/")).append(NB_DEPENDENCY_CLASS_SEPARATOR);
+ // add all classes which refer usedClass (,) seperated
+ Set value = entry.getValue();
+ for (String refClass : value) {
+ fldBuilder.append(refClass.replace(".", "/")).append(",");
+ }
+ // Mark the end of all referring classes
+ fldBuilder.append("\n");
+ }
+ LOGGER.log(Level.FINE, "Class dependencies index field: {0}", fldBuilder.toString());
+ doc.add(FLD_NB_DEPENDENCY_CLASS.toField(fldBuilder.toString()));
+ }
+
+ static void read(JarFile jf, Map classfiles, Set alreadyRead, String ignores) throws IOException {
+ Pattern p = (ignores != null)? Pattern.compile(ignores): null;
+ Enumeration e = jf.entries();
+ while (e.hasMoreElements()) {
+ JarEntry entry = e.nextElement();
+ String name = entry.getName();
+ if (!name.endsWith(".class")) {
+ continue;
+ }
+ String clazz = name.substring(0, name.length() - 6).replace('/', '.');
+ if (p != null && p.matcher(clazz).matches()) {
+ continue;
+ }
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(Math.max((int) entry.getSize(), 0));
+ InputStream is = jf.getInputStream(entry);
+ try {
+ byte[] buf = new byte[4096];
+ int read;
+ while ((read = is.read(buf)) != -1) {
+ baos.write(buf, 0, read);
+ }
+ } finally {
+ is.close();
+ }
+ classfiles.put(clazz, baos.toByteArray());
+ }
+ }
+
+
+ static Set dependencies(byte[] data) throws IOException {
+ Set result = new TreeSet();
+ DataInput input = new DataInputStream(new ByteArrayInputStream(data));
+ skip(input, 8); // magic, minor_version, major_version
+ int size = input.readUnsignedShort() - 1; // constantPoolCount
+ String[] utf8Strings = new String[size];
+ boolean[] isClassName = new boolean[size];
+ boolean[] isDescriptor = new boolean[size];
+ for (int i = 0; i < size; i++) {
+ byte tag = input.readByte();
+ switch (tag) {
+ case 1: // CONSTANT_Utf8
+ utf8Strings[i] = input.readUTF();
+ break;
+ case 7: // CONSTANT_Class
+ int index = input.readUnsignedShort() - 1;
+ if (index >= size) {
+ throw new IOException("@" + i + ": CONSTANT_Class_info.name_index " + index + " too big for size of pool " + size);
+ }
+ //log("Class reference at " + index, Project.MSG_DEBUG);
+ isClassName[index] = true;
+ break;
+ case 3: // CONSTANT_Integer
+ case 4: // CONSTANT_Float
+ case 9: // CONSTANT_Fieldref
+ case 10: // CONSTANT_Methodref
+ case 11: // CONSTANT_InterfaceMethodref
+ skip(input, 4);
+ break;
+ case 12: // CONSTANT_NameAndType
+ skip(input, 2);
+ index = input.readUnsignedShort() - 1;
+ if (index >= size || index < 0) {
+ throw new IOException("@" + i + ": CONSTANT_NameAndType_info.descriptor_index " + index + " too big for size of pool " + size);
+ }
+ isDescriptor[index] = true;
+ break;
+ case 8: // CONSTANT_String
+ skip(input, 2);
+ break;
+ case 5: // CONSTANT_Long
+ case 6: // CONSTANT_Double
+ skip(input, 8);
+ i++; // weirdness in spec
+ break;
+ default:
+ LOGGER.log(Level.WARNING, "Unrecognized constant pool tag {0} at index {1}; running UTF-8 strings: {2}", new Object[]{tag, i, Arrays.asList(utf8Strings)});
+ continue;
+ }
+ }
+ //task.log("UTF-8 strings: " + Arrays.asList(utf8Strings), Project.MSG_DEBUG);
+ for (int i = 0; i < size; i++) {
+ String s = utf8Strings[i];
+ if (s != null) {
+ if (isClassName[i]) {
+ while (s.charAt(0) == '[') {
+ // array type
+ s = s.substring(1);
+ }
+ if (s.length() == 1) {
+ // primitive
+ continue;
+ }
+ String c;
+ if (s.charAt(s.length() - 1) == ';' && s.charAt(0) == 'L') {
+ // Uncommon but seems sometimes this happens.
+ c = s.substring(1, s.length() - 1);
+ } else {
+ c = s;
+ }
+ result.add(c.replace('/', '.'));
+ } else if (isDescriptor[i]) {
+ int idx = 0;
+ while ((idx = s.indexOf('L', idx)) != -1) {
+ int semi = s.indexOf(';', idx);
+ if (semi == -1) {
+ throw new IOException("Invalid type or descriptor: " + s);
+ }
+ result.add(s.substring(idx + 1, semi).replace('/', '.'));
+ idx = semi;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ private static void skip(DataInput input, int bytes) throws IOException {
+ int skipped = input.skipBytes(bytes);
+ if (skipped != bytes) {
+ throw new IOException("Truncated class file");
+ }
+ }
+
+ private static final String NS = "urn:NbClassDependenciesIndexCreator"; // NOI18N
+ public static final IndexerField FLD_NB_DEPENDENCY_CLASS = new IndexerField(new Field(
+ null, NS, NB_DEPENDENCY_CLASSES, "From a class's inside an artifact used class-dependencies"),
+ IndexerFieldVersion.V3, NB_DEPENDENCY_CLASSES, "From a class's inside an artifact used class-dependencies", Store.YES, Index.ANALYZED);
+ @Override
+ public Collection getIndexerFields() {
+ return Arrays.asList(FLD_NB_DEPENDENCY_CLASS);
+ }
+ }
+
private static class NbIndexCreator extends AbstractIndexCreator {
private final List remoteRepos;
@@ -1273,7 +1651,7 @@
MavenProject mp = load(ai);
if (mp != null) {
List dependencies = mp.getDependencies();
- LOGGER.log(Level.FINER, "Successfully loaded project model from repository for {0} with {1} dependencies", new Object[] {ai, dependencies.size()});
+ LOGGER.log(Level.FINE, "Successfully loaded project model from repository for {0} with {1} dependencies", new Object[] {ai, dependencies.size()});
dependenciesByArtifact.put(ai, dependencies);
}
} catch (InvalidArtifactRTException ex) {
@@ -1320,12 +1698,12 @@
if (res.getProject() != null) {
return res.getProject();
} else {
- LOGGER.log(Level.FINER, "No project model from repository for {0}: {1}", new Object[] {ai, res.getProblems()});
+ LOGGER.log(Level.FINE, "No project model from repository for {0}: {1}", new Object[] {ai, res.getProblems()});
}
} catch (ProjectBuildingException ex) {
- LOGGER.log(Level.FINER, "Failed to load project model from repository for {0}: {1}", new Object[] {ai, ex});
+ LOGGER.log(Level.FINE, "Failed to load project model from repository for {0}: {1}", new Object[] {ai, ex});
} catch (Exception exception) {
- LOGGER.log(Level.FINER, "Failed to load project model from repository for " + ai, exception);
+ LOGGER.log(Level.FINE, "Failed to load project model from repository for " + ai, exception);
}
return null;
}
diff --git a/maven.indexer/src/org/netbeans/modules/maven/indexer/api/RepositoryQueries.java b/maven.indexer/src/org/netbeans/modules/maven/indexer/api/RepositoryQueries.java
--- a/maven.indexer/src/org/netbeans/modules/maven/indexer/api/RepositoryQueries.java
+++ b/maven.indexer/src/org/netbeans/modules/maven/indexer/api/RepositoryQueries.java
@@ -48,6 +48,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -61,6 +62,7 @@
import org.netbeans.modules.maven.indexer.spi.DependencyInfoQueries;
import org.netbeans.modules.maven.indexer.spi.GenericFindQuery;
import org.netbeans.modules.maven.indexer.spi.RepositoryIndexerImplementation;
+import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
/**
@@ -300,6 +302,26 @@
query.addResults(null, true);
}
+ /**
+ * Returns all referring class of {@code className} in the local repository
+ *
+ * @param className the binary class name of the class to find referers.
+ * @param repos repositories to search in
+ * @return a Set of binary class name's which are referring {@code className}
+ */
+ public static Set findDependendClassesByClass(final String className, final RepositoryInfo... repos) {
+ final Collection> all = splitReposByType(repos);
+ final Set dependendClasses = new HashSet();
+ for (List rps : all) {
+ final RepositoryIndexerImplementation impl = RepositoryIndexer.findImplementation(rps.get(0));
+ final ClassesQuery chq = impl.getCapabilityLookup().lookup(ClassesQuery.class);
+ if (chq != null) {
+ dependendClasses.addAll(chq.findDependendClassesFromClass(className, rps));
+ }
+ }
+ return dependendClasses;
+ }
+
public static List findArchetypes(RepositoryInfo... repos) {
Collection> all = splitReposByType(repos);
List toRet = new ArrayList();
diff --git a/maven.indexer/src/org/netbeans/modules/maven/indexer/spi/ClassesQuery.java b/maven.indexer/src/org/netbeans/modules/maven/indexer/spi/ClassesQuery.java
--- a/maven.indexer/src/org/netbeans/modules/maven/indexer/spi/ClassesQuery.java
+++ b/maven.indexer/src/org/netbeans/modules/maven/indexer/spi/ClassesQuery.java
@@ -43,6 +43,7 @@
package org.netbeans.modules.maven.indexer.spi;
import java.util.List;
+import java.util.Set;
import org.netbeans.modules.maven.indexer.api.NBVersionInfo;
import org.netbeans.modules.maven.indexer.api.RepositoryInfo;
@@ -61,4 +62,13 @@
* search is too general.
*/
public List findVersionsByClass(final String className, List repos);
+
+ /**
+ * Returns all referring class of {@code className} in the local repository
+ *
+ * @param className the binary class name of the class to find referers.
+ * @param repos repositories to search in
+ * @return a Set of binary class name's which are referring {@code className}
+ */
+ public Set findDependendClassesFromClass(final String className, List repos);
}
diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RetoucheCommit.java b/refactoring.maven/src/org/netbeans/modules/refactoring/maven/plugins/RetoucheCommit.java
copy from refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RetoucheCommit.java
copy to refactoring.maven/src/org/netbeans/modules/refactoring/maven/plugins/RetoucheCommit.java
--- a/refactoring.java/src/org/netbeans/modules/refactoring/java/plugins/RetoucheCommit.java
+++ b/refactoring.maven/src/org/netbeans/modules/refactoring/maven/plugins/RetoucheCommit.java
@@ -41,7 +41,7 @@
* 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.refactoring.java.plugins;
+package org.netbeans.modules.refactoring.maven.plugins;
import java.io.File;
import java.io.IOException;
diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/WhereUsedPanel.form b/refactoring.maven/src/org/netbeans/modules/refactoring/maven/ui/WhereUsedPanel.form
copy from refactoring.java/src/org/netbeans/modules/refactoring/java/ui/WhereUsedPanel.form
copy to refactoring.maven/src/org/netbeans/modules/refactoring/maven/ui/WhereUsedPanel.form
--- a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/WhereUsedPanel.form
+++ b/refactoring.maven/src/org/netbeans/modules/refactoring/maven/ui/WhereUsedPanel.form
@@ -15,7 +15,7 @@
-
+
@@ -35,7 +35,7 @@
-
+
@@ -63,12 +63,12 @@
-
+
-
+
@@ -88,7 +88,7 @@
-
+
@@ -96,7 +96,7 @@
-
+
@@ -123,27 +123,18 @@
-
-
-
-
-
-
-
-
-
-
+
-
+
@@ -162,7 +153,7 @@
-
+
@@ -170,7 +161,7 @@
-
+
@@ -188,12 +179,12 @@
-
+
-
+
@@ -205,6 +196,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -231,8 +242,8 @@
-
-
+
+
@@ -271,7 +282,7 @@
-
+
@@ -290,7 +301,7 @@
-
+
diff --git a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/WhereUsedPanel.java b/refactoring.maven/src/org/netbeans/modules/refactoring/maven/ui/WhereUsedPanel.java
copy from refactoring.java/src/org/netbeans/modules/refactoring/java/ui/WhereUsedPanel.java
copy to refactoring.maven/src/org/netbeans/modules/refactoring/maven/ui/WhereUsedPanel.java
--- a/refactoring.java/src/org/netbeans/modules/refactoring/java/ui/WhereUsedPanel.java
+++ b/refactoring.maven/src/org/netbeans/modules/refactoring/maven/ui/WhereUsedPanel.java
@@ -41,11 +41,10 @@
* 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.refactoring.java.ui;
+package org.netbeans.modules.refactoring.maven.ui;
import java.awt.BorderLayout;
import java.awt.Component;
-import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.io.IOException;
import java.text.MessageFormat;
@@ -64,12 +63,9 @@
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectUtils;
-import org.netbeans.modules.refactoring.java.RetoucheUtils;
-import org.netbeans.modules.refactoring.java.ui.WhereUsedPanel.Scope;
import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
import org.openide.awt.Mnemonics;
import org.openide.util.NbBundle;
-import org.netbeans.modules.refactoring.java.RefactoringModule;
import javax.lang.model.element.Modifier;
import javax.swing.JLabel;
import javax.swing.JPanel;
@@ -82,10 +78,13 @@
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.ui.ElementHeaders;
import org.netbeans.api.project.Project;
+import org.netbeans.modules.refactoring.maven.RefactoringModule;
+import org.netbeans.modules.refactoring.maven.RetoucheUtils;
/**
* @author Jan Becicka
+ * @author Christian Moser
*/
public class WhereUsedPanel extends JPanel implements CustomRefactoringPanel {
@@ -103,16 +102,47 @@
initComponents();
//parent.setPreviewEnabled(false);
}
+
+ /**
+ * Disable/Enables currently not supported search options.
+ *
+ * @param state selected-state of {@link #searchInLocalRepo} checkbox
+ */
+ private void searchInLocalRepoHelper(final Boolean state) {
+ RefactoringModule.setOption("searchInLocalRepo.whereUsed", state);
+ if (state) {
+ searchInComments.setEnabled(false);
+ c_subclasses.setEnabled(false);
+ c_directOnly.setEnabled(false);
+ } else {
+ searchInComments.setEnabled(true);
+ c_subclasses.setEnabled(true);
+ c_directOnly.setEnabled(true);
+ }
+ RefactoringModule.setOption("searchInComments.whereUsed", false);
+ searchInComments.setSelected(false);
+ c_subclasses.setSelected(false);
+ c_directOnly.setSelected(false);
+ c_usages.setSelected(true);
+ }
public enum Scope {
- ALL,
- CURRENT
+ OPEN_PROJECTS,
+ CURRENT_PROJECT,
+ LOCAL_REPO,
}
public Scope getScope() {
- if (scope.getSelectedIndex()==1)
- return Scope.CURRENT;
- return Scope.ALL;
+ switch (scope.getSelectedIndex()) {
+ case 0:
+ return Scope.OPEN_PROJECTS;
+ case 1:
+ return Scope.CURRENT_PROJECT;
+ case 2:
+ return Scope.LOCAL_REPO;
+ default:
+ return Scope.OPEN_PROJECTS;
+ }
}
private boolean initialized = false;
@@ -133,13 +163,16 @@
Project p = FileOwnerQuery.getOwner(element.getFileObject());
final JLabel currentProject;
final JLabel allProjects;
+ final JLabel localRepo;
if (p!=null) {
ProjectInformation pi = ProjectUtils.getInformation(FileOwnerQuery.getOwner(element.getFileObject()));
currentProject = new JLabel(pi.getDisplayName(), pi.getIcon(), SwingConstants.LEFT);
allProjects = new JLabel(NbBundle.getMessage(WhereUsedPanel.class,"LBL_AllProjects"), pi.getIcon(), SwingConstants.LEFT);
+ localRepo = new JLabel(NbBundle.getMessage(WhereUsedPanel.class,"LBL_LocalRepo"), pi.getIcon(), SwingConstants.LEFT);
} else {
currentProject = null;
allProjects = null;
+ localRepo = null;
}
CancellableTask task =new CancellableTask() {
public void cancel() {
@@ -189,6 +222,7 @@
SwingUtilities.invokeLater(new Runnable() {
public void run() {
+ boolean localRepoSupported = false;
remove(classesPanel);
remove(methodsPanel);
label.setText(labelText);
@@ -208,6 +242,7 @@
} else if ((element.getKind() == ElementKind.CLASS) || (element.getKind() == ElementKind.INTERFACE)) {
add(classesPanel, BorderLayout.CENTER);
classesPanel.setVisible(true);
+ localRepoSupported = true;
} else {
remove(classesPanel);
remove(methodsPanel);
@@ -216,11 +251,18 @@
c_usages.setVisible(false);
c_directOnly.setVisible(false);
}
+
if (currentProject!=null) {
- scope.setModel(new DefaultComboBoxModel(new Object[]{allProjects, currentProject }));
+ scope.setModel(new DefaultComboBoxModel(new Object[]{allProjects, currentProject, localRepo }));
int defaultItem = (Integer) RefactoringModule.getOption("whereUsed.scope", 0); // NOI18N
scope.setSelectedIndex(defaultItem);
scope.setRenderer(new JLabelRenderer());
+ // refersh local repo scope
+ searchInLocalRepoHelper(defaultItem == 2 ? true : false);
+ if (!localRepoSupported) {
+ // Local Repo scope is only supported in class / interface search
+ scope.removeItem(localRepo);
+ }
} else {
scopePanel.setVisible(false);
}
@@ -310,10 +352,10 @@
m_overriders = new javax.swing.JCheckBox();
m_usages = new javax.swing.JCheckBox();
classesPanel = new javax.swing.JPanel();
- jPanel2 = new javax.swing.JPanel();
c_subclasses = new javax.swing.JRadioButton();
c_usages = new javax.swing.JRadioButton();
c_directOnly = new javax.swing.JRadioButton();
+ localRepoPanel = new javax.swing.JPanel();
commentsPanel = new javax.swing.JPanel();
label = new javax.swing.JLabel();
searchInComments = new javax.swing.JCheckBox();
@@ -342,7 +384,7 @@
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 0);
methodsPanel.add(m_isBaseClass, gridBagConstraints);
- java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/netbeans/modules/refactoring/java/ui/Bundle"); // NOI18N
+ java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/netbeans/modules/refactoring/maven/ui/Bundle"); // NOI18N
m_isBaseClass.getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_isBaseClass")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
@@ -396,14 +438,6 @@
add(methodsPanel, java.awt.BorderLayout.CENTER);
classesPanel.setLayout(new java.awt.GridBagLayout());
- gridBagConstraints = new java.awt.GridBagConstraints();
- gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 4;
- gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
- gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
- gridBagConstraints.weightx = 1.0;
- gridBagConstraints.weighty = 1.0;
- classesPanel.add(jPanel2, gridBagConstraints);
buttonGroup.add(c_subclasses);
org.openide.awt.Mnemonics.setLocalizedText(c_subclasses, org.openide.util.NbBundle.getMessage(WhereUsedPanel.class, "LBL_FindAllSubtypes")); // NOI18N
@@ -437,13 +471,33 @@
classesPanel.add(c_directOnly, gridBagConstraints);
c_directOnly.getAccessibleContext().setAccessibleDescription(bundle.getString("ACSD_directOnly")); // NOI18N
+ javax.swing.GroupLayout localRepoPanelLayout = new javax.swing.GroupLayout(localRepoPanel);
+ localRepoPanel.setLayout(localRepoPanelLayout);
+ localRepoPanelLayout.setHorizontalGroup(
+ localRepoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 361, Short.MAX_VALUE)
+ );
+ localRepoPanelLayout.setVerticalGroup(
+ localRepoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGap(0, 8, Short.MAX_VALUE)
+ );
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 4;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.weightx = 1.0;
+ gridBagConstraints.weighty = 1.0;
+ classesPanel.add(localRepoPanel, gridBagConstraints);
+
add(classesPanel, java.awt.BorderLayout.CENTER);
commentsPanel.setLayout(new java.awt.BorderLayout());
commentsPanel.add(label, java.awt.BorderLayout.NORTH);
searchInComments.setSelected(((Boolean) RefactoringModule.getOption("searchInComments.whereUsed", Boolean.FALSE)).booleanValue());
- org.openide.awt.Mnemonics.setLocalizedText(searchInComments, org.openide.util.NbBundle.getBundle(WhereUsedPanel.class).getString("LBL_SearchInComents")); // NOI18N
+ searchInComments.setLabel(org.openide.util.NbBundle.getMessage(WhereUsedPanel.class, "LBL_SearchInComents")); // NOI18N
searchInComments.setMargin(new java.awt.Insets(10, 14, 2, 2));
searchInComments.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
@@ -473,7 +527,7 @@
.addContainerGap()
.addComponent(scopeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(scope, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(scope, 0, 301, Short.MAX_VALUE)
.addContainerGap())
);
scopePanelLayout.setVerticalGroup(
@@ -489,6 +543,7 @@
private void scopeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scopeActionPerformed
RefactoringModule.setOption("whereUsed.scope", scope.getSelectedIndex()); // NOI18N
+ searchInLocalRepoHelper(scope.getSelectedIndex() == 2 ? true : false);
}//GEN-LAST:event_scopeActionPerformed
private void searchInCommentsItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_searchInCommentsItemStateChanged
@@ -530,8 +585,8 @@
private javax.swing.JPanel classesPanel;
private javax.swing.JPanel commentsPanel;
private javax.swing.JPanel jPanel1;
- private javax.swing.JPanel jPanel2;
private javax.swing.JLabel label;
+ private javax.swing.JPanel localRepoPanel;
private javax.swing.JCheckBox m_isBaseClass;
private javax.swing.JCheckBox m_overriders;
private javax.swing.JCheckBox m_usages;