| /* |
| * 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; |
| } |
| } |
| } |