Inspections - pass onTheFly into ProblemDescriptors & use it to create LAZY refs...
[fedora-idea.git] / plugins / devkit / src / build / PluginBuildParticipant.java
blob025d22aa08f0e4d27e2e89c02112a15bf17e060f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.idea.devkit.build;
18 import com.intellij.openapi.compiler.CompileContext;
19 import com.intellij.openapi.compiler.CompilerMessageCategory;
20 import com.intellij.openapi.compiler.make.BuildParticipant;
21 import com.intellij.openapi.deployment.DeploymentUtil;
22 import com.intellij.openapi.module.Module;
23 import com.intellij.openapi.projectRoots.Sdk;
24 import com.intellij.openapi.roots.ModuleRootManager;
25 import com.intellij.openapi.roots.OrderRootType;
26 import com.intellij.openapi.roots.libraries.Library;
27 import com.intellij.openapi.util.io.FileUtil;
28 import com.intellij.openapi.vfs.JarFileSystem;
29 import com.intellij.openapi.vfs.VfsUtil;
30 import com.intellij.openapi.vfs.VirtualFile;
31 import com.intellij.packaging.artifacts.Artifact;
32 import com.intellij.packaging.elements.ArtifactRootElement;
33 import com.intellij.packaging.elements.CompositePackagingElement;
34 import com.intellij.packaging.elements.PackagingElement;
35 import com.intellij.packaging.elements.PackagingElementFactory;
36 import com.intellij.packaging.impl.artifacts.ArtifactImpl;
37 import com.intellij.packaging.impl.artifacts.PlainArtifactType;
38 import com.intellij.psi.xml.XmlDocument;
39 import com.intellij.psi.xml.XmlFile;
40 import com.intellij.psi.xml.XmlTag;
41 import com.intellij.util.descriptors.ConfigFile;
42 import com.intellij.util.xml.DomElement;
43 import com.intellij.util.xml.DomManager;
44 import org.jetbrains.annotations.NonNls;
45 import org.jetbrains.idea.devkit.DevKitBundle;
46 import org.jetbrains.idea.devkit.dom.Dependency;
47 import org.jetbrains.idea.devkit.dom.IdeaPlugin;
48 import org.jetbrains.idea.devkit.module.PluginModuleType;
49 import org.jetbrains.idea.devkit.projectRoots.IdeaJdk;
50 import org.jetbrains.idea.devkit.util.DescriptorUtil;
52 import java.util.HashSet;
53 import java.util.List;
55 /**
56 * @author peter
58 public class PluginBuildParticipant extends BuildParticipant {
59 @NonNls private static final String CLASSES = "/classes";
60 @NonNls private static final String LIB = "/lib/";
61 @NonNls private static final String LIB_DIRECTORY = "lib";
62 private final Module myModule;
63 private final PluginBuildConfiguration myPluginBuildConfiguration;
65 public PluginBuildParticipant(final Module module, final PluginBuildConfiguration pluginBuildConfiguration) {
66 super();
67 myModule = module;
68 myPluginBuildConfiguration = pluginBuildConfiguration;
71 @Override
72 public Artifact createArtifact(CompileContext context) {
73 Sdk jdk = IdeaJdk.findIdeaJdk(ModuleRootManager.getInstance(myModule).getSdk());
74 if (jdk != null && IdeaJdk.isFromIDEAProject(jdk.getHomePath())) {
75 return null;
78 if (jdk == null) {
79 context.addMessage(CompilerMessageCategory.ERROR, DevKitBundle.message("jdk.type.incorrect", myModule.getName()), null, -1, -1);
80 return null;
83 final String outputPath = PluginBuildUtil.getPluginExPath(myModule);
84 if (outputPath == null) {
85 return null;
88 if (!checkDependencies(context)) {
89 return null;
93 final PackagingElementFactory factory = PackagingElementFactory.getInstance();
94 final ArtifactRootElement<?> root = factory.createArtifactRootElement();
96 ConfigFile configFile = myPluginBuildConfiguration.getPluginXML();
97 if (configFile != null) {
98 DeploymentUtil.getInstance().checkConfigFile(configFile, context, myModule);
99 factory.addFileCopy(root, "META-INF/", VfsUtil.urlToPath(configFile.getUrl()));
101 final XmlFile xmlFile = configFile.getXmlFile();
102 if (xmlFile != null) {
103 final XmlDocument document = xmlFile.getDocument();
104 if (document != null) {
105 final DomElement domElement = DomManager.getDomManager(xmlFile.getProject()).getDomElement(document.getRootTag());
106 if (domElement instanceof IdeaPlugin) {
107 for(Dependency dependency: ((IdeaPlugin)domElement).getDependencies()) {
108 final String file = dependency.getConfigFile().getValue();
109 final VirtualFile virtualFile = configFile.getVirtualFile();
110 assert virtualFile != null;
111 final VirtualFile parent = virtualFile.getParent();
112 assert parent != null;
113 final String url = parent.getUrl();
114 factory.addFileCopy(root, "META-INF/", VfsUtil.urlToPath(url) + "/" + file);
121 HashSet<Module> modules = new HashSet<Module>();
122 PluginBuildUtil.getDependencies(myModule, modules);
124 final CompositePackagingElement<?> classesDir = factory.getOrCreateDirectory(root, CLASSES);
125 for (Module dep : modules) {
126 classesDir.addOrFindChild(factory.createModuleOutput(dep));
128 classesDir.addOrFindChild(factory.createModuleOutput(myModule));
130 HashSet<Library> libs = new HashSet<Library>();
131 PluginBuildUtil.getLibraries(myModule, libs);
132 for (Module dependentModule : modules) {
133 PluginBuildUtil.getLibraries(dependentModule, libs);
137 // libraries
138 final VirtualFile libDir = jdk.getHomeDirectory().findFileByRelativePath(LIB_DIRECTORY);
139 for (Library library : libs) {
140 boolean hasDirsOnly = true;
141 VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
142 for (VirtualFile file : files) {
143 if (file.getFileSystem() instanceof JarFileSystem) {
144 hasDirsOnly = false;
145 file = ((JarFileSystem)file.getFileSystem()).getVirtualFileForJar(file);
147 if (libDir != null && file != null && VfsUtil.isAncestor(libDir, file, false)) {
148 context.addMessage(CompilerMessageCategory.ERROR, DevKitBundle.message("dont.add.idea.libs.to.classpath", file.getName()), null,
149 -1, -1);
153 final List<? extends PackagingElement<?>> elements = factory.createLibraryElements(library);
154 if (hasDirsOnly) {
155 //todo split one lib into 2 separate libs if there are jars and dirs
156 classesDir.addOrFindChildren(elements);
158 else {
159 factory.getOrCreateDirectory(root, LIB).addOrFindChildren(elements);
163 return new ArtifactImpl(getArtifactName(), PlainArtifactType.getInstance(), false, root, FileUtil.toSystemIndependentName(outputPath));
166 private String getArtifactName() {
167 return myModule.getName() + ":plugin";
170 private boolean checkDependencies(CompileContext context) {
171 final Module[] wrongSetDependencies = PluginBuildUtil.getWrongSetDependencies(myModule);
172 if (wrongSetDependencies.length != 0) {
173 boolean realProblems = false;
174 final String pluginId = DescriptorUtil.getPluginId(myModule);
176 for (Module dependency : wrongSetDependencies) {
177 if (!PluginModuleType.isOfType(dependency)) {
178 realProblems = true;
179 context.addMessage(CompilerMessageCategory.ERROR,
180 DevKitBundle.message("incorrect.dependency.non-plugin-module", dependency.getName(), myModule.getName()), null,
181 -1, -1);
183 else {
184 final XmlFile pluginXml = PluginModuleType.getPluginXml(dependency);
185 boolean isDeclared = false;
186 if (pluginXml != null) {
187 final XmlTag rootTag = pluginXml.getDocument().getRootTag();
188 final XmlTag[] dependencies = rootTag != null ? rootTag.findSubTags("depends") : XmlTag.EMPTY;
189 for (XmlTag dep : dependencies) {
190 if (dep.getValue().getTrimmedText().equals(pluginId)) {
191 isDeclared = true;
192 break;
196 if (!isDeclared) {
197 // make this a warning instead?
198 realProblems = true;
199 context.addMessage(CompilerMessageCategory.ERROR,
200 DevKitBundle.message("incorrect.dependency.not-declared", dependency.getName(), myModule.getName()), null, -1,
201 -1);
205 if (realProblems) return false;
207 return true;