/*
* Copyright (c) 2007-2009, Osmorc Development Team
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.osmorc.inspection.maven;
import com.intellij.codeInspection.*;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomManager;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.dom.model.MavenDomDependency;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.dom.model.MavenDomRepository;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenArtifactUtil;
import org.osmorc.facet.OsmorcFacet;
import org.osmorc.frameworkintegration.CachingBundleInfoProvider;
import org.osmorc.obrimport.MavenRepository;
import org.osmorc.obrimport.ObrSearchDialog;
import org.osmorc.obrimport.springsource.ObrMavenResult;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Inspection which detects non-OSGi dependencies.
*
* @author <a href="mailto:janthomae@janthomae.de">Jan Thomä</a>
* @version $Id:$
*/
public class NonOsgiMavenDependencyInspection extends XmlSuppressableInspectionTool {
@Nls
@NotNull
public String getGroupDisplayName() {
return "OSGi";
}
@Nls
@NotNull
public String getDisplayName() {
return "Non-OSGi dependency";
}
@NotNull
public String getShortName() {
return "osmorcNonOsgiMavenDependency";
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder problemsHolder, boolean b) {
return new XmlElementVisitor() {
public void visitXmlTag(XmlTag xmltag) {
// suppress inspection for projects not having an OSGi context.
if (!OsmorcFacet.hasOsmorcFacet(xmltag)) {
return;
}
// get the dependency
MavenDomDependency dependency = getDependency(xmltag);
if (dependency != null) {
String scope = dependency.getScope().getStringValue();
if ("test".equals(scope)) {
// don't test this for "test" dependencies...
return;
}
// get the projects manager for this dependency
MavenProjectsManager manager = MavenProjectsManager.getInstance(xmltag.getProject());
// try to resolve the jar file
File artifactFile = MavenArtifactUtil
.getArtifactFile(manager.getLocalRepository(), dependency.getGroupId().getStringValue(),
dependency.getArtifactId().getStringValue(),
dependency.getVersion().getStringValue(), "jar");
if (artifactFile.exists()) {
try {
String url = artifactFile.toURL().toString();
// it is no bundle
if (!CachingBundleInfoProvider.isBundle(url)) {
problemsHolder.registerProblem(xmltag, "Dependency is not OSGi-ready",
new FindOsgiCapableMavenDependencyQuickFix());
}
}
catch (MalformedURLException e) {
// ok
}
}
}
}
};
}
@Override
public ProblemDescriptor[] checkFile(@NotNull PsiFile psiFile, @NotNull InspectionManager inspectionManager,
boolean b) {
// only run this for POM files in osmorc-controlled projects, its a waste of resources on other XML file types
if (!MavenDomUtil.isMavenFile(psiFile) || !OsmorcFacet.hasOsmorcFacet(psiFile)) {
return new ProblemDescriptor[0];
}
else {
return super.checkFile(psiFile, inspectionManager, b);
}
}
public static MavenDomDependency getDependency(XmlTag xmltag) {
// avoid going through the dom for each and every tag.
if (!"dependency".equals(xmltag.getName())) {
return null;
}
DomElement dom = DomManager.getDomManager(xmltag.getProject()).getDomElement(xmltag);
if (dom != null) {
return dom.getParentOfType(MavenDomDependency.class, false);
}
return null;
}
/**
* Intention action which tries to find a compatible OSGi-ready version of a maven dependency in the Springsource
* repository.
*
* @author <a href="mailto:janthomae@janthomae.de">Jan Thomä</a>
* @version $Id:$
*/
private static class FindOsgiCapableMavenDependencyQuickFix implements LocalQuickFix {
@NotNull
public String getFamilyName() {
return "Osmorc";
}
@NotNull
public String getName() {
return "Find OSGi-ready version";
}
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor problemDescriptor) {
final MavenDomDependency dependency = getDependency((XmlTag) problemDescriptor.getPsiElement());
final ObrMavenResult mavenResult =
ObrSearchDialog.queryForMavenArtifact(project, dependency.getArtifactId().toString());
if (mavenResult != null) {
final PsiFile psiFile = problemDescriptor.getPsiElement().getContainingFile();
new WriteCommandAction(project, psiFile) {
protected void run(Result result) throws Throwable
{
MavenDomProjectModel model =
MavenDomUtil.getMavenDomProjectModel(getProject(), psiFile.getVirtualFile());
// adds a new dependency to the end of the list
MavenDomDependency dummy = model.getDependencies().addDependency();
dummy.getArtifactId().setStringValue(mavenResult.getArtifactId());
dummy.getVersion().setStringValue(mavenResult.getVersion());
dummy.getGroupId().setStringValue(mavenResult.getGroupId());
// copy over scope from old item
if (!"".equals(dependency.getScope().getStringValue())) {
dummy.getScope().setStringValue(dependency.getScope().getStringValue());
}
PsiElement newDep = dummy.getXmlElement();
PsiElement oldDep = dependency.getXmlElement();
// add after the old element a copy of our dummy element (which is at the end of the list so far)
oldDep.getParent().addAfter(newDep.copy(), oldDep);
// kill old dependency and the dummy
oldDep.delete();
newDep.delete();
// finally check the repo urls, if we need to add a new one.
MavenRepository[] repos = mavenResult.getBundleRepository().getMavenRepositories();
List<MavenDomRepository> repositories = model.getRepositories().getRepositories();
List<MavenRepository> knownRepositories = new ArrayList<MavenRepository>();
for (MavenDomRepository repository : repositories) {
String knownRepoUrl = repository.getUrl().getStringValue();
for (MavenRepository repo : repos) {
if (repo.getRepositoryUrl().equals(knownRepoUrl)) {
knownRepositories.add(repo);
break;
}
}
}
List<MavenRepository> unknownRepositories =
new ArrayList<MavenRepository>(Arrays.asList(repos));
unknownRepositories.removeAll(knownRepositories);
// now we have a list of Repos we still don't know.
// add these to the repo list
for (MavenRepository unknownRepository : unknownRepositories) {
// fix up IDEA-24324, we use the ID provided by MavenRepository instead of using its URL
// which breaks maven on windows systems.
MavenDomRepository repo = model.getRepositories().addRepository();
repo.getId().setStringValue(unknownRepository.getRepositoryId());
repo.getUrl().setStringValue(unknownRepository.getRepositoryUrl());
repo.getName().setStringValue(unknownRepository.getRepositoryDescription());
}
}
}.execute();
FileDocumentManager docManager = FileDocumentManager.getInstance();
com.intellij.openapi.editor.Document doc = docManager.getDocument(psiFile.getVirtualFile());
docManager.saveDocument(doc);
PsiDocumentManager.getInstance(project).commitDocument(doc);
/*
MavenId mavenid = new MavenId(result.getGroupId(), result.getArtifactId(), result.getVersion());
Module module = getModuleForFile(problemDescriptor.getPsiElement().getContainingFile());
MavenModel model = MavenUtil.getMavenModel(project, problemDescriptor.getPsiElement().getContainingFile().getVirtualFile());
model.getDependencies().addDependency();
org.jetbrains.idea.maven.project.MavenProjectModel mavenProject =
MavenProjectsManager.getInstance(project).findProject(module);
mavenProject.getRemoteRepositories()
MavenProjectsManager.getInstance(project).addDependency(mavenProject, mavenid);
*/
// MavenProjectsManager.getInstance(project).reimport();
}
}
}
}