blob: e2a0b0ba75cacf97884c19870c8cfff3f40fb5eb [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.nodes;
import org.netbeans.modules.maven.ModuleInfoSupport;
import java.awt.Component;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenuItem;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Profile;
import org.apache.maven.model.Relocation;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.project.ProjectBuildingResult;
import org.codehaus.plexus.util.FileUtils;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.netbeans.api.java.queries.JavadocForBinaryQuery;
import org.netbeans.api.progress.aggregate.AggregateProgressHandle;
import org.netbeans.api.progress.aggregate.BasicAggregateProgressFactory;
import org.netbeans.api.progress.aggregate.ProgressContributor;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.maven.NbArtifactFixer;
import org.netbeans.modules.maven.NbMavenProjectImpl;
import org.netbeans.modules.maven.api.CommonArtifactActions;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.dependencies.DependencyExcludeNodeVisitor;
import org.netbeans.modules.maven.dependencies.ExcludeDependencyPanel;
import org.netbeans.modules.maven.embedder.DependencyTreeFactory;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.maven.embedder.MavenEmbedder;
import org.netbeans.modules.maven.embedder.exec.ProgressTransferListener;
import org.netbeans.modules.maven.model.ModelOperation;
import org.netbeans.modules.maven.model.Utilities;
import org.netbeans.modules.maven.model.pom.Exclusion;
import org.netbeans.modules.maven.model.pom.POMModel;
import org.netbeans.spi.project.ui.PathFinder;
import static org.netbeans.modules.maven.nodes.Bundle.*;
import org.netbeans.modules.maven.queries.MavenFileOwnerQueryImpl;
import org.netbeans.modules.maven.queries.RepositoryForBinaryQueryImpl;
import org.netbeans.modules.maven.queries.RepositoryForBinaryQueryImpl.Coordinates;
import org.netbeans.modules.maven.spi.IconResources;
import org.netbeans.modules.maven.spi.nodes.DependencyTypeIconBadge;
import org.netbeans.modules.maven.spi.queries.ForeignClassBundler;
import org.netbeans.spi.java.project.support.ui.PackageView;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.actions.PropertiesAction;
import org.openide.awt.HtmlBrowser;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.loaders.DataObject;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.openide.nodes.PropertySupport;
import org.openide.nodes.Sheet;
import org.openide.util.ContextAwareAction;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.RequestProcessor;
import org.openide.util.WeakListeners;
import org.openide.util.actions.Presenter;
import org.openide.util.lookup.Lookups;
/**
* node representing a dependency
* @author Milos Kleint
*/
public class DependencyNode extends AbstractNode implements PreferenceChangeListener {
private boolean longLiving;
private PropertyChangeListener listener;
private ChangeListener listener2;
final Data data;
private volatile String iconBase = IconResources.DEPENDENCY_ICON;
private static final String toolTipJavadoc = "<img src=\"" + DependencyNode.class.getClassLoader().getResource(IconResources.JAVADOC_BADGE_ICON) + "\">&nbsp;" //NOI18N
+ NbBundle.getMessage(DependencyNode.class, "ICON_JavadocBadge");//NOI18N
private static final String toolTipSource = "<img src=\"" + DependencyNode.class.getClassLoader().getResource(IconResources.SOURCE_BADGE_ICON) + "\">&nbsp;" //NOI18N
+ NbBundle.getMessage(DependencyNode.class, "ICON_SourceBadge");//NOI18N
private static final String toolTipMissing = "<img src=\"" + DependencyNode.class.getClassLoader().getResource(IconResources.BROKEN_PROJECT_BADGE_ICON) + "\">&nbsp;" //NOI18N
+ NbBundle.getMessage(DependencyNode.class, "ICON_MissingBadge");//NOI18N
private static final String toolTipManaged = "<img src=\"" + DependencyNode.class.getClassLoader().getResource(IconResources.MANAGED_BADGE_ICON) + "\">&nbsp;" //NOI18N
+ NbBundle.getMessage(DependencyNode.class, "ICON_ManagedBadge");//NOI18N
private static final String toolTipForeignBundler = "<img src=\"" + DependencyNode.class.getClassLoader().getResource(IconResources.BROKEN_PROJECT_BADGE_ICON) + "\">&nbsp;" //NOI18N
+ NbBundle.getMessage(DependencyNode.class, "ICON_PreferSourcesBadge");//NOI18N
private static final RequestProcessor RP = new RequestProcessor(DependencyNode.class);
private static Children createChildren(@NullAllowed Node nodeDelegate) {
return nodeDelegate == null ? Children.LEAF : new JarContentFilterChildren(nodeDelegate);
}
@NonNull
private static Lookup createLookup(@NonNull final Project project, @NonNull final Artifact art, @NullAllowed final Node nodeDelegate, Supplier<Boolean> canAddToModuleInfo) {
final PathFinder pathFinderDelegate = nodeDelegate == null ? null : nodeDelegate.getLookup().lookup(PathFinder.class);
final FileObject fo = nodeDelegate == null ? null : nodeDelegate.getLookup().lookup(FileObject.class);
if (fo != null) {
return Lookups.fixed(new Data(art, project, fo, canAddToModuleInfo), project, art, PathFinders.createDelegatingPathFinder(pathFinderDelegate), fo);
} else {
return Lookups.fixed(new Data(art, project, null, canAddToModuleInfo), project, art, PathFinders.createDelegatingPathFinder(pathFinderDelegate));
}
}
@CheckForNull
static Node createNodeDelegate(@NonNull final Artifact art, FileObject fo, final boolean longLiving) {
if (!longLiving) {
return null;
}
//artifact.getFile() should be eagerly normalized
if (fo != null && FileUtil.isArchiveFile(fo)) {
return PackageView.createPackageView(new ArtifactSourceGroup(art));
}
return null;
}
public DependencyNode(
NbMavenProjectImpl project,
final Artifact art,
final FileObject fo,
boolean isLongLiving,
Node nodeDelegate,
Supplier<Boolean> canAddToModuleInfo) {
super(createChildren(nodeDelegate), createLookup(project, art, nodeDelegate, canAddToModuleInfo));
this.data = getLookup().lookup(Data.class);
data.fileObject.set(fo);
longLiving = isLongLiving;
if (longLiving) {
listener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (NbMavenProject.PROP_PROJECT.equals(evt.getPropertyName())) {
refreshNode();
}
}
};
NbMavenProject.addPropertyChangeListener(project, WeakListeners.propertyChange(listener, project.getProjectWatcher()));
listener2 = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent event) {
if (event instanceof MavenFileOwnerQueryImpl.GAVCHangeEvent) {
MavenFileOwnerQueryImpl.GAVCHangeEvent ev = (MavenFileOwnerQueryImpl.GAVCHangeEvent) event;
if (ev.matches(art)) {
refreshNode();
}
} else {
refreshNode();
}
}
};
//TODO check if this one is a performance bottleneck.
MavenFileOwnerQueryImpl.getInstance().addChangeListener(
WeakListeners.change(listener2,
MavenFileOwnerQueryImpl.getInstance()));
DependenciesNode.prefs().addPreferenceChangeListener(WeakListeners.create(PreferenceChangeListener.class, this, DependenciesNode.prefs()));
}
setDisplayName(createName(false));
setIconBase(false);
if (longLiving) {
RP.post(new Runnable() {
@Override
public void run() {
refreshNode();
}
});
}
data.setNode(this);
}
private void setIconBase(boolean longLiving) {
String base;
if (longLiving && data.isDependencyProjectAvailable()) {
if (data.isTransitive()) {
base = IconResources.TRANSITIVE_MAVEN_ICON;
} else {
base = IconResources.MAVEN_ICON;
}
} else if (data.isTransitive()) {
if (data.isAddedToCP()) {
base = IconResources.TRANSITIVE_DEPENDENCY_ICON;
} else {
base = IconResources.TRANSITIVE_ARTIFACT_ICON;
}
} else if (data.isAddedToCP()) {
base = IconResources.DEPENDENCY_ICON;
} else {
base = IconResources.ARTIFACT_ICON;
}
this.iconBase = base;
setIconBaseWithExtension(base);
}
@Messages({
"DESC_Dep1=GroupId:",
"DESC_Dep2=ArtifactId:",
"DESC_Dep3=Version:",
"DESC_Dep4=Type:",
"DESC_Dep5=Classifier:",
"DESC_scope=Scope:",
"DESC_via=Via:"
})
@Override public String getShortDescription() {
StringBuilder buf = new StringBuilder();
buf.append("<html><i>").append(DESC_Dep1()).append("</i><b> ").append(data.art.getGroupId()).append("</b><br><i>"); //NOI18N
buf.append(DESC_Dep2()).append("</i><b> ").append(data.art.getArtifactId()).append("</b><br><i>");//NOI18N
buf.append(DESC_Dep3()).append("</i><b> ").append(data.art.getVersion()).append("</b><br><i>");//NOI18N
buf.append(DESC_Dep4()).append("</i><b> ").append(data.art.getType()).append("</b><br>");//NOI18N
if (data.art.getClassifier() != null) {
buf.append("<i>").append(DESC_Dep5()).append("</i><b> ").append(data.art.getClassifier()).append("</b><br>");//NOI18N
}
buf.append("<i>").append(DESC_scope()).append("</i><b> ").append(data.art.getScope()).append("</b><br>");
List<String> trail = data.art.getDependencyTrail();
for (int i = trail.size() - 2; i > 0 && /* just to be safe */ i < trail.size(); i--) {
String[] id = trail.get(i).split(":"); // g:a:t[:c]:v
buf.append("<i>").append(DESC_via()).append("</i> ").append(id[1]).append("<br>");
}
// it seems that with ending </html> tag the icon descriptions are not added.
// buf.append("</html>");//NOI18N
return buf.toString();
}
private void refreshNode() {
assert !SwingUtilities.isEventDispatchThread();
FileObject fo = FileUtil.toFileObject(data.art.getFile());
data.sourceExists.set(data.getSourceFile().exists());
data.javadocExists.set(data.getJavadocFile().exists());
data.fileObject.set(fo);
setDisplayName(createName(longLiving));
setIconBase(longLiving);
fireIconChange();
fireDisplayNameChange(null, getDisplayName());
// if (longLiving) {
// ((DependencyChildren)getChildren()).doRefresh();
// }
//#142784
if (longLiving) {
if (Children.LEAF == getChildren()) {
final Node nodeDelegate = createNodeDelegate(data.art, fo, true);
Children childs = createChildren(nodeDelegate);
if (childs != Children.LEAF) {
setChildren(childs);
PathFinders.updateDelegate(getLookup().lookup(PathFinder.class), nodeDelegate.getLookup().lookup(PathFinder.class));
}
}
}
}
@Override
public String getHtmlDisplayName() {
StringBuilder n = new StringBuilder("<html>");
n.append(getDisplayName());
if (ArtifactUtils.isSnapshot(data.art.getVersion()) && data.art.getVersion().indexOf("SNAPSHOT") < 0) { //NOI18N
n.append(" <b>[").append(data.art.getVersion()).append("]</b>");
}
if (!data.art.getArtifactHandler().isAddedToClasspath() && !Artifact.SCOPE_COMPILE.equals(data.art.getScope())) {
n.append(" <i>[").append(data.art.getScope()).append("]</i>");
}
n.append("</html>");
return n.toString();
}
private String createName(boolean longLiving) {
if (longLiving) {
//TODO when the name changes on the other end (dep project) we have no way of knowing..
Project prj = data.getDependencyProject();
if (prj != null) {
return ProjectUtils.getInformation(prj).getDisplayName();
}
}
if (NbArtifactFixer.isFallbackFile(data.art.getFile())) {
return data.art.getArtifactId() + "-" + data.art.getBaseVersion() + (data.art.getClassifier() != null ? "-" + data.art.getClassifier() : "") + "." + data.art.getArtifactHandler().getExtension();
}
return data.art.getFile().getName();
}
@Override
public Action[] getActions(boolean context) {
Collection<Action> acts = new ArrayList<Action>();
if (longLiving && data.isDependencyProjectAvailable()) {
acts.add(OpenProjectAction.SINGLETON);
}
boolean local = data.isLocal();
if (data.isAddedToCP()) {
InstallLocalArtifactAction act = new InstallLocalArtifactAction();
acts.add(act);
if (!local) {
act.setEnabled(true);
}
}
if (local) {
acts.add(new CopyLocationAction());
}
// acts.add(new EditAction());
// acts.add(RemoveDepAction.get(RemoveDepAction.class));
if (!data.hasJavadocInRepository()) {
acts.add(DOWNLOAD_JAVADOC_ACTION);
if (data.isAddedToCP()) {
acts.add(new InstallLocalJavadocAction());
}
}
if (!data.hasSourceInRepository()) {
acts.add(DOWNLOAD_SOURCE_ACTION);
if (data.isAddedToCP()) {
acts.add(new InstallLocalSourcesAction());
}
}
if (data.isTransitive()) {
acts.add(new ExcludeTransitiveAction());
acts.add(SETINCURRENTINSTANCE);
} else {
acts.add(REMOVEDEPINSTANCE);
}
if (data.canAddToModuleInfo()) {
acts.add(ADDTOMODULEINFO);
}
acts.add(null);
acts.add(CommonArtifactActions.createViewArtifactDetails(data.art, data.getMavenProject().getRemoteArtifactRepositories()));
acts.add(CommonArtifactActions.createFindUsages(data.art));
acts.add(null);
acts.add(CommonArtifactActions.createViewJavadocAction(data.art));
/* #164992: disabled
acts.add(CommonArtifactActions.createViewProjectHomeAction(art, project.getOriginalMavenProject().getRemoteArtifactRepositories()));
acts.add(CommonArtifactActions.createViewBugTrackerAction(art, project.getOriginalMavenProject().getRemoteArtifactRepositories()));
acts.add(CommonArtifactActions.createSCMActions(art, project.getOriginalMavenProject().getRemoteArtifactRepositories()));
*/
acts.add(null);
acts.add(PropertiesAction.get(PropertiesAction.class));
return acts.toArray(new Action[acts.size()]);
}
@Override
public boolean canDestroy() {
return !data.isTransitive();
}
@Override
public void destroy() throws IOException {
REMOVEDEPINSTANCE.createContextAwareInstance(getLookup()).actionPerformed(null);
}
@Override
public boolean canRename() {
return false;
}
@Override
public boolean canCut() {
return false;
}
@Override
public boolean canCopy() {
return false;
}
@Override
public boolean hasCustomizer() {
return false;
}
void downloadJavadocSources(ProgressContributor progress, boolean isjavadoc) {
downloadJavadocSources(progress, isjavadoc, data.art, data.project);
refreshNode();
}
/**
*
* @param progress
* @param isjavadoc
* @param artifact
* @param prj
* @return the sources/javadoc artifact
*/
public static Artifact downloadJavadocSources(ProgressContributor progress, boolean isjavadoc, Artifact artifact, Project prj) {
MavenEmbedder online = EmbedderFactory.getOnlineEmbedder();
progress.start(2);
if ( Artifact.SCOPE_SYSTEM.equals(artifact.getScope())) {
progress.finish();
return null;
}
NbMavenProjectImpl prjimpl = prj.getLookup().lookup(NbMavenProjectImpl.class);
Artifact sources = null;
try {
String classifier;
String baseClassifier;
String bundleName;
if (isjavadoc) {
if (artifact.getClassifier() != null) {
if ("tests".equals(artifact.getClassifier())) {
classifier = "test-javadoc";
} else {
classifier = artifact.getClassifier() + "-javadoc";
}
} else {
classifier = "javadoc";
}
baseClassifier = "javadoc";
bundleName = "MSG_Checking_Javadoc";
} else {
baseClassifier = "sources";
if (artifact.getClassifier() != null) {
if ("tests".equals(artifact.getClassifier())) {
classifier = "test-sources";
} else {
classifier = artifact.getClassifier() + "-sources";
}
} else {
classifier = "sources";
}
bundleName = "MSG_Checking_Sources";
}
sources = prjimpl.getEmbedder().createArtifactWithClassifier(
artifact.getGroupId(),
artifact.getArtifactId(),
artifact.getVersion(),
artifact.getType(),
classifier);
progress.progress(org.openide.util.NbBundle.getMessage(DependencyNode.class, bundleName,artifact.getId()), 1);
online.resolve(sources, prjimpl.getOriginalMavenProject().getRemoteArtifactRepositories(), prjimpl.getEmbedder().getLocalRepository());
if (artifact.getFile() != null && artifact.getFile().exists()) {
List<Coordinates> coordinates = RepositoryForBinaryQueryImpl.getJarMetadataCoordinates(artifact.getFile());
if (coordinates != null) {
for (Coordinates coordinate : coordinates) {
sources = prjimpl.getEmbedder().createArtifactWithClassifier(
coordinate.groupId,
coordinate.artifactId,
coordinate.version,
"jar",
baseClassifier);
progress.progress(org.openide.util.NbBundle.getMessage(DependencyNode.class, bundleName, artifact.getId()), 1);
online.resolve(sources, prjimpl.getOriginalMavenProject().getRemoteArtifactRepositories(), prjimpl.getEmbedder().getLocalRepository());
}
}
}
} catch (ArtifactNotFoundException ex) {
// just ignore..ex.printStackTrace();
} catch (ArtifactResolutionException ex) {
// just ignore..ex.printStackTrace();
} finally {
progress.finish();
}
return sources;
}
@Override
public Image getIcon(int param) {
return badge(super.getIcon(param));
}
private boolean isIconProjectBased() {
String base = iconBase;
return IconResources.TRANSITIVE_MAVEN_ICON.equals(base) || IconResources.MAVEN_ICON.equals(base);
}
private Image badge(Image retValue) {
if (data.isLocal()) {
if (!isIconProjectBased()) {
if (data.hasJavadocInRepository()) {
Image ann = ImageUtilities.loadImage(IconResources.JAVADOC_BADGE_ICON); //NOI18N
ann = ImageUtilities.addToolTipToImage(ann, toolTipJavadoc);
retValue = ImageUtilities.mergeImages(retValue, ann, 12, 0);//NOI18N
}
if (data.hasSourceInRepository()) {
Image ann = ImageUtilities.loadImage(IconResources.SOURCE_BADGE_ICON); //NOI18N
ann = ImageUtilities.addToolTipToImage(ann, toolTipSource);
retValue = ImageUtilities.mergeImages(retValue, ann, 12, 8);//NOI18N
}
} else {
Project p = data.getDependencyProject();
if (p != null) {
ForeignClassBundler fcb = p.getLookup().lookup(ForeignClassBundler.class);
if (fcb != null && !fcb.preferSources()) {
Image ann = ImageUtilities.loadImage(IconResources.BROKEN_PROJECT_BADGE_ICON); //NOI18N
ann = ImageUtilities.addToolTipToImage(ann, toolTipForeignBundler);
retValue = ImageUtilities.mergeImages(retValue, ann, 0, 0);//NOI18N
}
}
}
if (showManagedState() && data.isManaged()) {
Image ann = ImageUtilities.loadImage(IconResources.MANAGED_BADGE_ICON); //NOI18N
ann = ImageUtilities.addToolTipToImage(ann, toolTipManaged);
retValue = ImageUtilities.mergeImages(retValue, ann, 0, 8);//NOI18N
}
FileObject fo = data.fileObject.get();
if (fo != null && fo.isValid()) {
for (DependencyTypeIconBadge badge : Lookup.getDefault().lookupAll(DependencyTypeIconBadge.class)) {
Image ann = badge.getBadgeIcon(fo, data.art);
if (ann != null) {
retValue = ImageUtilities.mergeImages(retValue, ann, 0, 0);//NOI18N
break;
}
}
}
return retValue;
} else if (!isIconProjectBased()) {
Image ann = ImageUtilities.loadImage(IconResources.BROKEN_PROJECT_BADGE_ICON); //NOI18N
ann = ImageUtilities.addToolTipToImage(ann, toolTipMissing);
return ImageUtilities.mergeImages(retValue, ann, 0, 0);//NOI18N
} else {
Project p = data.getDependencyProject();
if (p != null) {
ForeignClassBundler fcb = p.getLookup().lookup(ForeignClassBundler.class);
if (fcb != null && !fcb.preferSources()) {
Image ann = ImageUtilities.loadImage(IconResources.BROKEN_PROJECT_BADGE_ICON); //NOI18N
ann = ImageUtilities.addToolTipToImage(ann, toolTipForeignBundler);
retValue = ImageUtilities.mergeImages(retValue, ann, 0, 0);//NOI18N
}
}
return retValue;
}
}
@Override
public Image getOpenedIcon(int type) {
return badge(super.getOpenedIcon(type));
}
@Override
public Component getCustomizer() {
return null;
}
@Override
protected Sheet createSheet() {
Sheet sheet = Sheet.createDefault();
Sheet.Set basicProps = sheet.get(Sheet.PROPERTIES);
try {
PropertySupport.Reflection artifactId = new PropertySupport.Reflection<String>(data.art, String.class, "getArtifactId", null); //NOI18N
artifactId.setName("artifactId"); //NOI18N
artifactId.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Artifact"));
artifactId.setShortDescription(""); //NOI18N
PropertySupport.Reflection groupId = new PropertySupport.Reflection<String>(data.art, String.class, "getGroupId", null); //NOI18N
groupId.setName("groupId"); //NOI18N
groupId.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Group"));
groupId.setShortDescription(""); //NOI18N
PropertySupport.Reflection version = new PropertySupport.Reflection<String>(data.art, String.class, "getVersion", null); //NOI18N
version.setName("version"); //NOI18N
version.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Version"));
version.setShortDescription(org.openide.util.NbBundle.getMessage(DependencyNode.class, "HINT_Version"));
PropertySupport.Reflection type = new PropertySupport.Reflection<String>(data.art, String.class, "getType", null); //NOI18N
type.setName("type"); //NOI18N
type.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Type"));
PropertySupport.Reflection scope = new PropertySupport.Reflection<String>(data.art, String.class, "getScope", null); //NOI18N
scope.setName("scope"); //NOI18N
scope.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Scope"));
PropertySupport.Reflection classifier = new PropertySupport.Reflection<String>(data.art, String.class, "getClassifier", null); //NOI18N
classifier.setName("classifier"); //NOI18N
classifier.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Classifier"));
PropertySupport.Reflection hasJavadoc = new PropertySupport.Reflection<Boolean>(data, Boolean.TYPE, "hasJavadocInRepository", null); //NOI18N
hasJavadoc.setName("javadoc"); //NOI18N
hasJavadoc.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Javadoc_Locally"));
PropertySupport.Reflection hasSources = new PropertySupport.Reflection<Boolean>(data, Boolean.TYPE, "hasSourceInRepository", null); //NOI18N
hasSources.setName("sources"); //NOI18N
hasSources.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Sources_Locally"));
PropertySupport.Reflection transitive = new PropertySupport.Reflection<Boolean>(data, Boolean.TYPE, "isTransitive", null); //NOI18N
transitive.setName("transitive"); //NOI18N
transitive.setDisplayName(org.openide.util.NbBundle.getMessage(DependencyNode.class, "PROP_Transitive"));
PropertySupport.Reflection path = new PropertySupport.Reflection<File>(data.art, File.class, "getFile", null); //NOI18N
path.setName("path"); //NOI18N
path.setDisplayName("Path");
path.setShortDescription("Absolute path to the artifact in the local filesystem.");
PropertySupport.Reflection repositorypath = new PropertySupport.Reflection<String>(data, String.class, "getArtifactRepositoryPath", null); //NOI18N
repositorypath.setName("repositorypath"); //NOI18N
repositorypath.setDisplayName("Repository Path");
repositorypath.setShortDescription("Relative path within the local maven repository.");
basicProps.put(new Node.Property[] {
artifactId, groupId, version, type, scope, classifier, transitive, hasJavadoc, hasSources, path, repositorypath
});
} catch (NoSuchMethodException exc) {
exc.printStackTrace();
}
return sheet;
}
// private class DownloadJavadocAndSourcesAction extends AbstractAction implements Runnable {
// public DownloadJavadocAndSourcesAction() {
// putValue(Action.NAME, "Download Javadoc & Source");
// }
//
// public void actionPerformed(ActionEvent event) {
// RP.post(this);
// }
//
// public void run() {
// ProgressContributor contrib = AggregateProgressFactory.createProgressContributor("single"); //NOI18N
// AggregateProgressHandle handle = AggregateProgressFactory.createHandle("Download Javadoc and Sources", new ProgressContributor[] {contrib}, null, null);
// handle.start();
// downloadJavadocSources(EmbedderFactory.getOnlineEmbedder(), contrib);
// handle.finish();
// }
// }
//extract the model out of the node class
public static class Data {
private final Artifact art;
private final Project project;
private final Supplier<Boolean> canAddToModuleInfo;
private java.util.concurrent.atomic.AtomicReference<FileObject> fileObject;
private final java.util.concurrent.atomic.AtomicBoolean sourceExists = new AtomicBoolean(false);
private final java.util.concurrent.atomic.AtomicBoolean javadocExists = new AtomicBoolean(false);
private DependencyNode node;
public Data(Artifact art, Project project, FileObject fileObject, Supplier<Boolean> canAddToModuleInfo) {
this.art = art;
this.project = project;
this.fileObject = new AtomicReference<>(fileObject);
this.canAddToModuleInfo = canAddToModuleInfo;
}
public String getArtifactRepositoryPath() {
return EmbedderFactory.getProjectEmbedder().getLocalRepository().pathOf(art);
}
public boolean isLocal() {
FileObject fo = fileObject.get();
return fo != null && fo.isValid() && !NbArtifactFixer.isFallbackFile(art.getFile());
}
public boolean hasJavadocInRepository() {
return javadocExists.get() && (!Artifact.SCOPE_SYSTEM.equals(art.getScope()));
}
//normalized
public File getJavadocFile() {
File artifact = art.getFile();
String version = artifact.getParentFile().getName();
String artifactId = artifact.getParentFile().getParentFile().getName();
return new File(artifact.getParentFile(), artifactId + "-" + version + (art.getClassifier() != null ? ("tests".equals(art.getClassifier()) ? "-test" : "-" + art.getClassifier()) : "") + "-javadoc.jar"); //NOI18N
}
//normalized
public File getSourceFile() {
File artifact = art.getFile();
String version = artifact.getParentFile().getName();
String artifactId = artifact.getParentFile().getParentFile().getName();
return new File(artifact.getParentFile(), artifactId + "-" + version + (art.getClassifier() != null ? ("tests".equals(art.getClassifier()) ? "-test" : "-" + art.getClassifier()) : "") + "-sources.jar"); //NOI18N
}
public boolean hasSourceInRepository() {
return sourceExists.get() && (!Artifact.SCOPE_SYSTEM.equals(art.getScope()));
}
MavenProject getMavenProject() {
return project.getLookup().lookup(NbMavenProject.class).getMavenProject();
}
/**
* public because of the property sheet
*/
public boolean isTransitive() {
List trail = art.getDependencyTrail();
return trail != null && trail.size() > 2;
}
boolean canAddToModuleInfo() {
return canAddToModuleInfo.get();
}
public boolean isManaged() {
DependencyManagement dm = project.getLookup().lookup(NbMavenProject.class).getMavenProject().getDependencyManagement();
if (dm != null) {
List<Dependency> dmList = dm.getDependencies();
for (Dependency d : dmList) {
if (art.getGroupId().equals(d.getGroupId())
&& art.getArtifactId().equals(d.getArtifactId())) {
return true;
}
}
}
return false;
}
private boolean isAddedToCP() {
return art.getArtifactHandler().isAddedToClasspath();
}
/**
* this call is slow
*
* @return
*/
private boolean isDependencyProjectAvailable() {
return getDependencyProject() != null;
}
/**
* this call is slow
*
* @return
*/
private Project getDependencyProject() {
if (Artifact.SCOPE_SYSTEM.equals(art.getScope())) {
return null;
}
URI uri = org.openide.util.Utilities.toURI(art.getFile());
// TODO should be patched, along with other uses of Artifact.getFile among nodes
return FileOwnerQuery.getOwner(uri);
}
private void setNode(DependencyNode aThis) {
node = aThis;
}
public DependencyNode getNode() {
return node;
}
}
//why oh why do we have to suffer through this??
private static final RemoveDependencyAction REMOVEDEPINSTANCE = new RemoveDependencyAction(Lookup.EMPTY);
@Messages("BTN_Remove_Dependency=Remove Dependency")
private static class RemoveDependencyAction extends AbstractAction implements ContextAwareAction {
private final Lookup lkp;
RemoveDependencyAction(Lookup look) {
putValue(Action.NAME, BTN_Remove_Dependency());
lkp = look;
Collection<? extends NbMavenProjectImpl> res = lkp.lookupAll(NbMavenProjectImpl.class);
Set<NbMavenProjectImpl> prjs = new HashSet<NbMavenProjectImpl>(res);
if (prjs.size() != 1) {
setEnabled(false);
}
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new RemoveDependencyAction(actionContext);
}
@Override
public void actionPerformed(ActionEvent event) {
final Collection<? extends Artifact> artifacts = lkp.lookupAll(Artifact.class);
if (artifacts.isEmpty()) {
return;
}
Collection<? extends NbMavenProjectImpl> res = lkp.lookupAll(NbMavenProjectImpl.class);
Set<NbMavenProjectImpl> prjs = new HashSet<NbMavenProjectImpl>(res);
if (prjs.size() != 1) {
return;
}
final NbMavenProjectImpl project = prjs.iterator().next();
final List<Artifact> unremoved = new ArrayList<Artifact>();
final ModelOperation<POMModel> operation = new ModelOperation<POMModel>() {
@Override
public void performOperation(POMModel model) {
for (Artifact art : artifacts) {
org.netbeans.modules.maven.model.pom.Dependency dep =
model.getProject().findDependencyById(art.getGroupId(), art.getArtifactId(), null);
if (dep != null) {
model.getProject().removeDependency(dep);
} else {
unremoved.add(art);
}
}
}
};
RP.post(new Runnable() {
@Override
public void run() {
FileObject fo = FileUtil.toFileObject(project.getPOMFile());
Utilities.performPOMModelOperations(fo, Collections.singletonList(operation));
if (unremoved.size() > 0) {
StatusDisplayer.getDefault().setStatusText(NbBundle.getMessage(DependencyNode.class, "MSG_Located_In_Parent", unremoved.size()), Integer.MAX_VALUE);
}
}
});
}
}
private static final String SHOW_MANAGED_DEPENDENCIES = "show.managed.dependencies";
private static boolean showManagedState() {
return DependenciesNode.prefs().getBoolean(SHOW_MANAGED_DEPENDENCIES, false);
}
@Override public void preferenceChange(PreferenceChangeEvent evt) {
if (evt.getKey().equals(SHOW_MANAGED_DEPENDENCIES)) {
refreshNode();
}
}
static class ShowManagedStateAction extends AbstractAction implements Presenter.Popup {
@NbBundle.Messages("LBL_ShowManagedState=Show Managed State for dependencies")
ShowManagedStateAction() {
String s = LBL_ShowManagedState();
putValue(Action.NAME, s);
}
@Override public void actionPerformed(ActionEvent e) {
DependenciesNode.prefs().putBoolean(SHOW_MANAGED_DEPENDENCIES, !showManagedState());
}
@Override public JMenuItem getPopupPresenter() {
JCheckBoxMenuItem mi = new JCheckBoxMenuItem(this);
mi.setSelected(showManagedState());
return mi;
}
}
@Messages({"BTN_Exclude_Dependency=Exclude Dependency",
"TIT_Exclude=Exclude Transitive Dependency"})
private class ExcludeTransitiveAction extends AbstractAction {
public ExcludeTransitiveAction() {
putValue(Action.NAME, BTN_Exclude_Dependency());
}
@Override
public void actionPerformed(ActionEvent event) {
RP.post(new Runnable() {
@Override
public void run() {
org.apache.maven.shared.dependency.tree.DependencyNode rootnode = DependencyTreeFactory.createDependencyTree(data.getMavenProject(), EmbedderFactory.getOnlineEmbedder(), Artifact.SCOPE_TEST);
DependencyExcludeNodeVisitor nv = new DependencyExcludeNodeVisitor(data.art.getGroupId(), data.art.getArtifactId(), data.art.getType());
rootnode.accept(nv);
final Set<org.apache.maven.shared.dependency.tree.DependencyNode> nds = nv.getDirectDependencies();
Collection<org.apache.maven.shared.dependency.tree.DependencyNode> directs;
if (nds.size() > 1) {
final ExcludeDependencyPanel pnl = new ExcludeDependencyPanel(data.getMavenProject(), data.art, nds, rootnode);
DialogDescriptor dd = new DialogDescriptor(pnl, TIT_Exclude());
Object ret = DialogDisplayer.getDefault().notify(dd);
if (ret == DialogDescriptor.OK_OPTION) {
directs = pnl.getDependencyExcludes().get(data.art);
} else {
return;
}
} else {
directs = nds;
}
runModifyExclusions(data.art, directs);
}
});
}
private void runModifyExclusions(final Artifact art, final Collection<org.apache.maven.shared.dependency.tree.DependencyNode> nds) {
ModelOperation<POMModel> operation = new ModelOperation<POMModel>() {
@Override
public void performOperation(POMModel model) {
for (org.apache.maven.shared.dependency.tree.DependencyNode nd : nds) {
Artifact directArt = nd.getArtifact();
org.netbeans.modules.maven.model.pom.Dependency dep = model.getProject().findDependencyById(directArt.getGroupId(), directArt.getArtifactId(), null);
if (dep == null) {
// now check the active profiles for the dependency..
List<String> profileNames = new ArrayList<String>();
Iterator it = data.getMavenProject().getActiveProfiles().iterator();
while (it.hasNext()) {
Profile prof = (Profile) it.next();
profileNames.add(prof.getId());
}
for (String profileId : profileNames) {
org.netbeans.modules.maven.model.pom.Profile modProf = model.getProject().findProfileById(profileId);
if (modProf != null) {
dep = modProf.findDependencyById(directArt.getGroupId(), directArt.getArtifactId(), null);
if (dep != null) {
break;
}
}
}
}
if (dep == null) {
// relocation maybe?
List<org.netbeans.modules.maven.model.pom.Dependency> deps = model.getProject().getDependencies();
for (org.netbeans.modules.maven.model.pom.Dependency d : deps) {
Relocation rel = getRelocation(d);
if(rel != null &&
rel.getArtifactId().equals(directArt.getArtifactId()) &&
rel.getGroupId().equals(directArt.getGroupId()) &&
rel.getVersion().equals(directArt.getVersion()))
{
dep = d;
break;
}
}
}
if (dep == null) {
dep = model.getFactory().createDependency();
dep.setGroupId(directArt.getGroupId());
dep.setArtifactId(directArt.getArtifactId());
dep.setVersion(directArt.getVersion());
if (!"jar".equals(directArt.getType())) {
dep.setType(directArt.getType());
}
model.getProject().addDependency(dep);
//mkleint: TODO why is the dependency being added? i forgot already..
}
Exclusion ex = dep.findExclusionById(art.getGroupId(), art.getArtifactId());
if (ex == null) {
Exclusion exclude = model.getFactory().createExclusion();
exclude.setGroupId(art.getGroupId());
exclude.setArtifactId(art.getArtifactId());
dep.addExclusion(exclude);
}
}
}
};
FileObject fo = FileUtil.toFileObject(data.project.getLookup().lookup(NbMavenProjectImpl.class).getPOMFile());
org.netbeans.modules.maven.model.Utilities.performPOMModelOperations(fo, Collections.singletonList(operation));
}
}
private Relocation getRelocation(org.netbeans.modules.maven.model.pom.Dependency d) {
ProjectBuildingRequest dpbr = EmbedderFactory.getProjectEmbedder().createMavenExecutionRequest().getProjectBuildingRequest();
dpbr.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
dpbr.setProcessPlugins(false);
dpbr.setResolveDependencies(false);
ArrayList<ArtifactRepository> remoteRepos = new ArrayList<>();
dpbr.setRemoteRepositories(remoteRepos);
String groupId = d.getGroupId();
String artifactId = d.getArtifactId();
String version = d.getVersion();
if(groupId != null && !"".equals(groupId.trim()) &&
artifactId != null && !"".equals(artifactId.trim()) &&
version != null && !"".equals(version.trim()))
{
MavenEmbedder embedder = EmbedderFactory.getProjectEmbedder();
Artifact a = embedder.createProjectArtifact(groupId, artifactId, version);
try {
ProjectBuildingResult r = embedder.buildProject(a, dpbr);
DistributionManagement dm = r.getProject().getDistributionManagement();
return dm != null ? dm.getRelocation() : null;
} catch (ProjectBuildingException ex) {
// just log and hope for the best ...
Logger.getLogger(DependencyNode.class.getName()).log(Level.INFO, version, ex);
}
}
return null;
}
private static Action DOWNLOAD_JAVADOC_ACTION = new DownloadJavadocSrcAction(true);
private static Action DOWNLOAD_SOURCE_ACTION = new DownloadJavadocSrcAction(false);
@SuppressWarnings("serial")
private static class DownloadJavadocSrcAction extends AbstractAction implements ContextAwareAction {
private final boolean javadoc;
private final Lookup actionContext;
public DownloadJavadocSrcAction(boolean javadoc) {
this(javadoc, Lookup.EMPTY);
}
private DownloadJavadocSrcAction(boolean javadoc, Lookup actionContext) {
putValue(Action.NAME, javadoc ? LBL_Download_Javadoc() : LBL_Download__Sources());
this.javadoc = javadoc;
this.actionContext = actionContext;
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new DownloadJavadocSrcAction(javadoc, actionContext);
}
@Override
public void actionPerformed(ActionEvent evnt) {
if (actionContext == null) {
return;
}
RP.post(new Runnable() {
public @Override void run() {
ProgressContributor contributor = BasicAggregateProgressFactory.createProgressContributor("multi-1");
String label = javadoc ? Progress_Javadoc() : Progress_Source();
AggregateProgressHandle handle = BasicAggregateProgressFactory.createHandle(label,
new ProgressContributor [] {contributor}, ProgressTransferListener.cancellable(), null);
handle.start();
try {
ProgressTransferListener.setAggregateHandle(handle);
for (Data data : actionContext.lookupAll(Data.class)) {
ProgressContributor contributor2 = BasicAggregateProgressFactory.createProgressContributor("multi-1");
handle.addContributor(contributor2);
if (javadoc && !data.hasJavadocInRepository()) {
data.getNode().downloadJavadocSources(contributor2, javadoc);
} else if (!javadoc && !data.hasSourceInRepository()) {
data.getNode().downloadJavadocSources(contributor2, javadoc);
} else {
contributor2.finish();
}
}
} catch (ThreadDeath d) { // download interrupted
} catch (IllegalStateException ise) { //download interrupted in dependent thread. #213812
if (!(ise.getCause() instanceof ThreadDeath)) {
throw ise;
}
} finally {
handle.finish();
ProgressTransferListener.clearAggregateHandle();
}
}
});
}
}
//why oh why do we have to suffer through this??
private static final SetInCurrentAction SETINCURRENTINSTANCE = new SetInCurrentAction(Lookup.EMPTY);
@Messages("BTN_Set_Dependency=Declare as Direct Dependency")
private static class SetInCurrentAction extends AbstractAction implements ContextAwareAction {
private final Lookup lkp;
SetInCurrentAction(Lookup lookup) {
putValue(Action.NAME, BTN_Set_Dependency());
lkp = lookup;
Collection<? extends NbMavenProjectImpl> res = lkp.lookupAll(NbMavenProjectImpl.class);
Set<NbMavenProjectImpl> prjs = new HashSet<NbMavenProjectImpl>(res);
if (prjs.size() != 1) {
setEnabled(false);
}
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new SetInCurrentAction(actionContext);
}
@Override
public void actionPerformed(ActionEvent event) {
final Collection<? extends Artifact> artifacts = lkp.lookupAll(Artifact.class);
if (artifacts.isEmpty()) {
return;
}
Collection<? extends NbMavenProjectImpl> res = lkp.lookupAll(NbMavenProjectImpl.class);
Set<NbMavenProjectImpl> prjs = new HashSet<NbMavenProjectImpl>(res);
if (prjs.size() != 1) {
return;
}
final NbMavenProjectImpl project = prjs.iterator().next();
final ModelOperation<POMModel> operation = new ModelOperation<POMModel>() {
@Override
public void performOperation(POMModel model) {
for (Artifact art : artifacts) {
org.netbeans.modules.maven.model.pom.Dependency dep = model.getProject().findDependencyById(art.getGroupId(), art.getArtifactId(), null);
if (dep == null) {
// now check the active profiles for the dependency..
List<String> profileNames = new ArrayList<String>();
Iterator it = project.getOriginalMavenProject().getActiveProfiles().iterator();
while (it.hasNext()) {
Profile prof = (Profile) it.next();
profileNames.add(prof.getId());
}
for (String profileId : profileNames) {
org.netbeans.modules.maven.model.pom.Profile modProf = model.getProject().findProfileById(profileId);
if (modProf != null) {
dep = modProf.findDependencyById(art.getGroupId(), art.getArtifactId(), null);
if (dep != null) {
break;
}
}
}
}
if (dep == null) {
dep = model.getFactory().createDependency();
dep.setGroupId(art.getGroupId());
dep.setArtifactId(art.getArtifactId());
dep.setVersion(art.getVersion());
if (!"jar".equals(art.getType())) {
dep.setType(art.getType());
}
if (!Artifact.SCOPE_COMPILE.equals(art.getScope())) {
dep.setScope(art.getScope());
}
if (art.getClassifier() != null) {
dep.setClassifier(art.getClassifier());
}
model.getProject().addDependency(dep);
}
}
}
};
RP.post(new Runnable() {
@Override
public void run() {
FileObject fo = FileUtil.toFileObject(project.getPOMFile());
org.netbeans.modules.maven.model.Utilities.performPOMModelOperations(fo, Collections.singletonList(operation));
}
});
}
}
private static final AddToModuleInfoAction ADDTOMODULEINFO = new AddToModuleInfoAction(Lookup.EMPTY);
@Messages("BTN_AddToModuleInfo=Add to ModuleInfo")
private static class AddToModuleInfoAction extends AbstractAction implements ContextAwareAction {
private final Lookup lkp;
AddToModuleInfoAction(Lookup lookup) {
putValue(Action.NAME, BTN_AddToModuleInfo());
lkp = lookup;
Collection<? extends NbMavenProjectImpl> res = lkp.lookupAll(NbMavenProjectImpl.class);
Set<NbMavenProjectImpl> prjs = new HashSet<>(res);
if (prjs.size() != 1) {
setEnabled(false);
}
}
@Override
public Action createContextAwareInstance(Lookup actionContext) {
return new AddToModuleInfoAction(actionContext);
}
@Override
public void actionPerformed(ActionEvent event) {
final Collection<? extends Artifact> artifacts = lkp.lookupAll(Artifact.class);
if (artifacts.isEmpty()) {
return;
}
Collection<? extends NbMavenProjectImpl> res = lkp.lookupAll(NbMavenProjectImpl.class);
Set<NbMavenProjectImpl> prjs = new HashSet<>(res);
if (prjs.size() != 1) {
return;
}
ModuleInfoSupport.addRequires(prjs.iterator().next().getOriginalMavenProject(), artifacts);
}
}
@Messages("BTN_Manually_install=Manually install artifact")
private class InstallLocalArtifactAction extends AbstractAction {
public InstallLocalArtifactAction() {
putValue(Action.NAME, BTN_Manually_install());
}
@Override
public void actionPerformed(ActionEvent event) {
File fil = InstallPanel.showInstallDialog(data.art);
if (fil != null) {
InstallPanel.runInstallGoal(data.project.getLookup().lookup(NbMavenProjectImpl.class), fil, data.art);
}
}
}
private class CopyLocationAction extends AbstractAction {
@Messages("CopyLocationAction.name=Copy Location")
CopyLocationAction() {
super(CopyLocationAction_name());
}
@Override public void actionPerformed(ActionEvent e) {
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(data.art.getFile().getAbsolutePath()), null);
}
}
@Messages("BTN_Add_javadoc=Add local Javadoc")
private class InstallLocalJavadocAction extends AbstractAction implements Runnable {
private File source;
public InstallLocalJavadocAction() {
putValue(Action.NAME, BTN_Add_javadoc());
}
@Override
public void actionPerformed(ActionEvent event) {
source = InstallDocSourcePanel.showInstallDialog(true);
if (source != null) {
RP.post(this);
}
}
@Override
public void run() {
File target = data.getJavadocFile();
try {
FileUtils.copyFile(source, target);
} catch (IOException ex) {
ex.printStackTrace();
target.delete();
}
refreshNode();
}
}
@Messages("BTN_Add_sources=Add local sources")
private class InstallLocalSourcesAction extends AbstractAction implements Runnable {
private File source;
public InstallLocalSourcesAction() {
putValue(Action.NAME, BTN_Add_sources());
}
@Override
public void actionPerformed(ActionEvent event) {
source = InstallDocSourcePanel.showInstallDialog(false);
if (source != null) {
RP.post(this);
}
}
@Override
public void run() {
File target = data.getSourceFile();
try {
FileUtils.copyFile(source, target);
} catch (IOException ex) {
ex.printStackTrace();
target.delete();
}
refreshNode();
}
}
// private class EditAction extends AbstractAction {
// public EditAction() {
// putValue(Action.NAME, "Edit...");
// }
//
// public void actionPerformed(ActionEvent event) {
//
// DependencyEditor ed = new DependencyEditor(project, change);
// DialogDescriptor dd = new DialogDescriptor(ed, "Edit Dependency");
// Object ret = DialogDisplayer.getDefault().notify(dd);
// if (ret == NotifyDescriptor.OK_OPTION) {
// HashMap props = ed.getProperties();
// MavenSettings.getDefault().checkDependencyProperties(props.keySet());
// change.setNewValues(ed.getValues(), props);
// try {
// NbProjectWriter writer = new NbProjectWriter(project);
// List changes = (List)getLookup().lookup(List.class);
// writer.applyChanges(changes);
// } catch (Exception exc) {
// ErrorManager.getDefault().notify(ErrorManager.USER, exc);
// }
// }
// }
// }
//
private static class ArtifactSourceGroup implements SourceGroup {
private final Artifact art;
public ArtifactSourceGroup(Artifact art) {
this.art = art;
}
//art.getFile() should be normalized
@Override
public FileObject getRootFolder() {
FileObject fo = FileUtil.toFileObject(art.getFile());
if (fo != null) {
return FileUtil.getArchiveRoot(fo);
}
return null;
}
@Override
public String getName() {
return art.getId();
}
@Override
public String getDisplayName() {
return art.getId();
}
@Override
public Icon getIcon(boolean opened) {
return null;
}
@Override public boolean contains(FileObject file) {
return true;
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
}
private static class JarContentFilterChildren extends FilterNode.Children {
JarContentFilterChildren(Node orig) {
super(orig);
}
@Override
protected Node copyNode(Node node) {
return new JarFilterNode(node);
}
}
private static class JarFilterNode extends FilterNode {
JarFilterNode(Node original) {
super(original, Children.LEAF == original.getChildren() ?
Children.LEAF : new JarContentFilterChildren(original));
}
@Override
public Action[] getActions(boolean context) {
List<Action> result = new ArrayList<Action>();
result.addAll(Arrays.asList(super.getActions(false)));
result.add(new OpenJavadocAction());
return result.toArray(new Action[result.size()]);
}
@Messages("BTN_View_Javadoc=Show Javadoc")
private class OpenJavadocAction extends AbstractAction {
private OpenJavadocAction() {
putValue(Action.NAME, BTN_View_Javadoc());
}
@Override
@Messages({
"# {0} - artifact path",
"ERR_No_Javadoc_Found=Javadoc for {0} not found."})
public void actionPerformed(ActionEvent e) {
DataObject dobj = getOriginal().getLookup().lookup(DataObject.class);
if (dobj == null) {
return;
}
FileObject fil = dobj.getPrimaryFile();
FileObject jar = FileUtil.getArchiveFile(fil);
FileObject root = FileUtil.getArchiveRoot(jar);
String rel = FileUtil.getRelativePath(root, fil);
rel = rel.replaceAll("[.]class$", ".html"); //NOI18N
JavadocForBinaryQuery.Result res = JavadocForBinaryQuery.findJavadoc(root.toURL());
if (fil.isFolder()) {
rel = rel + "/package-summary.html"; //NOI18N
}
URL javadocUrl = findJavadoc(rel, res.getRoots());
if (javadocUrl != null) {
HtmlBrowser.URLDisplayer.getDefault().showURL(javadocUrl);
} else {
StatusDisplayer.getDefault().setStatusText(ERR_No_Javadoc_Found(fil.getPath()));
}
}
/**
* Locates a javadoc page by a relative name and an array of javadoc roots
* @param resource the relative name of javadoc page
* @param urls the array of javadoc roots
* @return the URL of found javadoc page or null if there is no such a page.
*/
URL findJavadoc(String resource, URL[] urls) {
for (int i = 0; i < urls.length; i++) {
String base = urls[i].toExternalForm();
if (!base.endsWith("/")) { // NOI18N
base = base + "/"; // NOI18N
}
try {
URL u = new URL(base + resource);
FileObject fo = URLMapper.findFileObject(u);
if (fo != null) {
return u;
}
} catch (MalformedURLException ex) {
// ErrorManager.getDefault().log(ErrorManager.ERROR, "Cannot create URL for "+base+resource+". "+ex.toString()); //NOI18N
continue;
}
}
return null;
}
}
}
private static class OpenProjectAction extends AbstractAction implements ContextAwareAction {
static final OpenProjectAction SINGLETON = new OpenProjectAction();
private OpenProjectAction() {}
public @Override void actionPerformed(ActionEvent e) {
assert false;
}
public @Override Action createContextAwareInstance(final Lookup context) {
return new AbstractAction(BTN_Open_Project()) {
public @Override void actionPerformed(ActionEvent e) {
Set<Project> projects = new HashSet<Project>();
for (Artifact art : context.lookupAll(Artifact.class)) {
File f = art.getFile();
if (f != null) {
Project p = FileOwnerQuery.getOwner(org.openide.util.Utilities.toURI(f));
if (p != null) {
projects.add(p);
}
}
}
OpenProjects.getDefault().open(projects.toArray(new NbMavenProjectImpl[projects.size()]), false, true);
}
};
}
}
}