blob: 7f48b6bbfaa3bf1415e96f5eff8504f84cbfb6c8 [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.j2ee;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.modules.j2ee.deployment.devmodules.api.Deployment;
import org.netbeans.modules.j2ee.deployment.devmodules.api.InstanceRemovedException;
import org.netbeans.modules.j2ee.deployment.devmodules.api.J2eePlatform;
import org.netbeans.modules.j2ee.deployment.devmodules.api.ServerInstance;
import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
import org.netbeans.modules.java.hints.spi.AbstractHint;
import org.netbeans.modules.javaee.project.api.JavaEEProjectSettings;
import org.netbeans.modules.maven.api.ModelUtils;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.model.ModelOperation;
import org.netbeans.modules.maven.model.pom.Dependency;
import org.netbeans.modules.maven.model.pom.POMModel;
import org.netbeans.modules.maven.model.pom.Properties;
import org.netbeans.spi.editor.hints.ChangeInfo;
import org.netbeans.spi.editor.hints.ErrorDescription;
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
import org.netbeans.spi.editor.hints.Fix;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
/**
* Warn user when implementation of EJBContainer is missing and offers him Embeddable EJB Container to use .
*/
public class EmbeddableEJBContainerHint extends AbstractHint {
private static final Set<Tree.Kind> TREE_KINDS =
EnumSet.<Tree.Kind>of(Tree.Kind.METHOD_INVOCATION);
private static final String PROP_GF_EMBEDDED_JAR = "glassfish.embedded-static-shell.jar";
public EmbeddableEJBContainerHint() {
super(true, true, AbstractHint.HintSeverity.ERROR);
}
@Override
public String getDescription() {
return NbBundle.getMessage(EmbeddableEJBContainerHint.class, "EmbeddableEJBContainer_Description"); // NOI18N
}
@Override
public Set<Kind> getTreeKinds() {
return TREE_KINDS;
}
@Override
public List<ErrorDescription> run(CompilationInfo info, TreePath treePath) {
Tree t = treePath.getLeaf();
Element el = info.getTrees().getElement(treePath);
if (!(el != null && el.getEnclosingElement().getSimpleName().toString().equals("EJBContainer") && // NOI18N
el.getSimpleName().toString().equals("createEJBContainer"))) { // NOI18N
return null;
}
FileObject testFile = info.getFileObject();
Project prj = FileOwnerQuery.getOwner(testFile);
if (prj == null) {
return null;
}
if (prj.getLookup().lookup(NbMavenProject.class) == null) {
// handles only Maven projects; Ant projects solves this issue differently
return null;
}
ClassPath cp = ClassPath.getClassPath(testFile, ClassPath.EXECUTE);
if (cp == null) {
return null;
}
for (FileObject cpRoot : cp.getRoots()) {
FileObject fo = FileUtil.getArchiveFile(cpRoot);
if (fo != null && fo.getNameExt().toLowerCase().contains("glassfish-embedded-static-shell")) {
return null;
}
}
try {
cp.getClassLoader(true).loadClass("javax.ejb.embeddable.EJBContainer"); // NOI18N
return null;
} catch (ClassFormatError tt) {
// OK, show hint to add GF
} catch (ClassNotFoundException tt) {
// OK, show hint to add GF
}
List<Fix> fixes = new ArrayList<Fix>();
J2eeModuleProvider provider = prj.getLookup().lookup(J2eeModuleProvider.class);
if (provider != null) {
fixes = FixEjbContainerAction.createGF3SystemScope(prj);
}
return Collections.<ErrorDescription>singletonList(
ErrorDescriptionFactory.createErrorDescription(
getSeverity().toEditorSeverity(),
getDisplayName(),
fixes,
info.getFileObject(),
(int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), t),
(int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), t)));
}
@Override
public String getId() {
return "EmbeddableEJBContainer"; // NOI18N
}
@Override
public String getDisplayName() {
return NbBundle.getMessage(EmbeddableEJBContainerHint.class, "EmbeddableEJBContainer_DisplayName"); // NOI18N
}
@Override
public void cancel() {
}
private static final class FixEjbContainerAction implements Fix {
private static final String GF_EMBEDDED_STATIC_SHELL_POM_LATEST = "https://maven.java.net/content/repositories/releases/org/glassfish/main/extras/glassfish-embedded-static-shell/3.1.2.2/glassfish-embedded-static-shell-3.1.2.2.pom";
private static final String GF_EMBEDDED_STATIC_SHELL_POM_OLD = "http://repo2.maven.org/maven2/org/glassfish/extras/glassfish-embedded-static-shell/3.0.1/glassfish-embedded-static-shell-3.0.1.pom";
private final String fixDesc;
private final URL pomUrl;
private final Project project;
private final File file;
private FixEjbContainerAction(String fixDesc, URL pomUrl, File f, Project prj) {
this.fixDesc = fixDesc;
this.pomUrl = pomUrl;
this.project = prj;
this.file = FileUtil.normalizeFile(f);
}
public static List<Fix> createGF3SystemScope(Project prj) {
List<Fix> fixes = new ArrayList<Fix>();
String usedServer = JavaEEProjectSettings.getServerInstanceID(prj);
for (String serId : Deployment.getDefault().getServerInstanceIDs()) {
ServerInstance server = Deployment.getDefault().getServerInstance(serId);
try {
if (!"gfv3ee6".equals(server.getServerID())) {
continue;
}
} catch (InstanceRemovedException ex) {
continue;
}
try {
File[] files = server.getJ2eePlatform().getToolClasspathEntries(J2eePlatform.TOOL_EMBEDDABLE_EJB);
assert files.length == 1 : "expecting one item: " + Arrays.asList(files);
try {
URL pomUrl;
if (serId.indexOf("gfv3ee6wc") != -1) {
pomUrl = new URL(GF_EMBEDDED_STATIC_SHELL_POM_LATEST);
} else {
pomUrl = new URL(GF_EMBEDDED_STATIC_SHELL_POM_OLD);
}
if (serId.equals(usedServer)) {
fixes.clear();
}
fixes.add(new FixEjbContainerAction(
NbBundle.getMessage(EmbeddableEJBContainerHint.class, "EmbeddableEJBContainer_FixGFStatic", server.getDisplayName()),
pomUrl, files[0], prj));
if (serId.equals(usedServer)) {
return fixes;
}
} catch (MalformedURLException ex) {
Exceptions.printStackTrace(ex);
}
} catch (InstanceRemovedException ex) {
Exceptions.printStackTrace(ex);
}
}
return fixes;
}
@Override
public ChangeInfo implement() throws Exception {
final Boolean[] added = new Boolean[1];
ModelOperation<POMModel> operation = new ModelOperation<POMModel>() {
@Override
public void performOperation(POMModel model) {
added[0] = checkAndAddPom(pomUrl, model, file);
}
};
FileObject pom = project.getProjectDirectory().getFileObject("pom.xml");//NOI18N
org.netbeans.modules.maven.model.Utilities.performPOMModelOperations(pom, Collections.singletonList(operation));
//TODO is the manual reload necessary if pom.xml file is being saved?
// NbMavenProject.fireMavenProjectReload(project);
if (added[0]) {
project.getLookup().lookup(NbMavenProject.class).triggerDependencyDownload();
}
return null;
}
private boolean checkAndAddPom(URL pom, POMModel model, File systemDep) {
ModelUtils.LibraryDescriptor result = ModelUtils.checkLibrary(pom);
if (result != null) {
//set dependency
Dependency dep = ModelUtils.checkModelDependency(model, result.getGroupId(), result.getArtifactId(), true);
dep.setVersion(result.getVersion());
dep.setScope("system"); //NOI18N
if (result.getClassifier() != null) {
dep.setClassifier(result.getClassifier());
}
if (systemDep != null) {
Properties props = model.getProject().getProperties();
if (props != null && props.getProperty(PROP_GF_EMBEDDED_JAR) == null) {
props.setProperty(PROP_GF_EMBEDDED_JAR, systemDep.getAbsolutePath());
}
dep.setSystemPath("${"+PROP_GF_EMBEDDED_JAR+ "}");
}
return true;
}
return false;
}
@Override
public String getText() {
return fixDesc;
}
}
}