blob: a1948a6df3918e68a0252004d6a7234924d2fb9f [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.maven.refactoring;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.AbstractArtifactResolutionException;
import org.netbeans.api.actions.Openable;
import org.netbeans.api.java.queries.SourceForBinaryQuery;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.modules.maven.indexer.api.RepositoryPreferences;
import org.netbeans.modules.maven.indexer.api.RepositoryUtil;
import static org.netbeans.modules.maven.indexer.api.RepositoryUtil.createArtifact;
import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
import org.netbeans.modules.refactoring.spi.ui.TreeElementFactory;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.text.PositionBounds;
import org.openide.util.Lookup;
import org.openide.util.RequestProcessor;
import org.openide.util.lookup.Lookups;
class MavenRefactoringElementImplementation implements RefactoringElementImplementation {
private static final Logger LOG = Logger.getLogger(MavenRefactoringElementImplementation.class.getName());
private static final RequestProcessor RP = new RequestProcessor(MavenRefactoringElementImplementation.class);
private final ReferringClass ref;
private FileObject file;
private static final FileObject NO_FILE = FileUtil.getConfigRoot();
MavenRefactoringElementImplementation(ReferringClass ref) {
this.ref = ref;
}
@Override public String getText() {
return ref.clazz;
}
@Override public String getDisplayText() {
return TreeElementFactory.getTreeElement(ref.artifact).getText(true);
}
@Override public boolean isEnabled() {
return true;
}
@Override public void setEnabled(boolean enabled) {}
@Override public void performChange() {}
@Override public void undoChange() {}
@Override public Lookup getLookup() {
return Lookups.singleton(ref);
}
@Override public synchronized FileObject getParentFile() {
if (file == null) {
try {
Artifact a = createArtifact(ref.artifact);
File jar = a.getFile();
if (!jar.exists()) { //#236842 try to minimize the cases when we need to let maven resolve and download artifacts
jar = RepositoryUtil.downloadArtifact(ref.artifact); // probably a no-op, since local hits must have been indexed
}
URL jarURL = FileUtil.urlForArchiveOrDir(jar);
if (jarURL != null) {
SourceForBinaryQuery.Result2 result = SourceForBinaryQuery.findSourceRoots2(jarURL);
if (result.preferSources()) {
FileObject[] roots = result.getRoots();
for (FileObject root : roots) {
file = root.getFileObject(ref.clazz.replace('.', '/') + ".java");
if (file != null) {
LOG.log(Level.FINE, "found source file {0}", file);
break;
}
}
if (file == null) {
if (roots.length > 0) {
LOG.log(Level.WARNING, "did not find {0} among {1}", new Object[] {ref.clazz, Arrays.asList(roots)});
} else {
LOG.log(Level.FINE, "no source roots for {0}", jar);
}
}
} else {
LOG.log(Level.FINE, "ignoring non-preferred sources for {0}", jar);
}
} else {
LOG.log(Level.WARNING, "no URL for {0}", jar);
}
if (file == null) {
if (jar.isFile()) {
file = URLMapper.findFileObject(new URL("jar:" + jar.toURI() + "!/" + ref.clazz.replace('.', '/') + ".class"));
if (file == null) {
LOG.log(Level.WARNING, "did not find {0} in {1}", new Object[] {ref.clazz, jar});
}
} else {
LOG.log(Level.WARNING, "{0} does not exist", jar);
}
}
} catch (Exception x) {
LOG.log(Level.WARNING, null, x);
}
if (file == null) {
file = NO_FILE;
}
}
return file;
}
@Override public PositionBounds getPosition() {
return null;
}
@Override public int getStatus() {
return NORMAL;
}
@Override public void setStatus(int status) {}
@Override public void openInEditor() {
RP.post(new Runnable() { // resolve(...) may connect to the network
@Override public void run() {
FileObject f = getParentFile();
if (f == NO_FILE) {
return;
}
if (f.hasExt("class")) {
try {
MavenEmbedder online = EmbedderFactory.getOnlineEmbedder();
Artifact sources = online.createArtifactWithClassifier(ref.artifact.getGroupId(), ref.artifact.getArtifactId(), ref.artifact.getVersion(), ref.artifact.getType(), "sources");
// XXX how do we get the exact remote repo from this?
// (Local artifact may well have come from a repository which is no longer registered in the IDE, or was never registered.
// Unfortunately it seems M3 does not preserve enough information in the local repo's metadata to find artifacts
// associated with one which was previously downloaded: _maven.repositories will remember the repositoryId but not its location.)
List<ArtifactRepository> remotes = RepositoryPreferences.getInstance().remoteRepositories(online);
online.resolve(sources, remotes, online.getLocalRepository());
// XXX this does not make ClassDataObject.OpenSourceCookie work immediately; clicking repeatedly seems to fix it
} catch (AbstractArtifactResolutionException x) {
LOG.log(Level.FINE, null, x);
}
}
try {
Openable o = DataObject.find(f).getLookup().lookup(Openable.class);
if (o != null) {
o.open();
} else {
LOG.log(Level.WARNING, "no Openable on {0}", getParentFile());
}
} catch (DataObjectNotFoundException x) {
LOG.log(Level.WARNING, null, x);
}
}
});
}
@Override public void showPreview() {}
}