update copyright
[fedora-idea.git] / plugins / devkit / src / build / PluginBuildParticipant.java
blobdf2f042f0be113b2e25fbaecdf5c97207ef40bd8
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.BuildConfiguration;
21 import com.intellij.openapi.compiler.make.BuildParticipantBase;
22 import com.intellij.openapi.compiler.make.BuildRecipe;
23 import com.intellij.openapi.deployment.DeploymentUtil;
24 import com.intellij.openapi.deployment.LibraryLink;
25 import com.intellij.openapi.deployment.ModuleLink;
26 import com.intellij.openapi.deployment.PackagingMethod;
27 import com.intellij.openapi.module.Module;
28 import com.intellij.openapi.module.ModuleUtil;
29 import com.intellij.openapi.projectRoots.Sdk;
30 import com.intellij.openapi.roots.ModuleRootManager;
31 import com.intellij.openapi.roots.OrderRootType;
32 import com.intellij.openapi.roots.libraries.Library;
33 import com.intellij.openapi.vfs.JarFileSystem;
34 import com.intellij.openapi.vfs.VfsUtil;
35 import com.intellij.openapi.vfs.VirtualFile;
36 import com.intellij.psi.xml.XmlDocument;
37 import com.intellij.psi.xml.XmlFile;
38 import com.intellij.psi.xml.XmlTag;
39 import com.intellij.util.descriptors.ConfigFile;
40 import com.intellij.util.descriptors.CustomConfigFile;
41 import com.intellij.util.xml.DomElement;
42 import com.intellij.util.xml.DomManager;
43 import org.jetbrains.annotations.NonNls;
44 import org.jetbrains.idea.devkit.DevKitBundle;
45 import org.jetbrains.idea.devkit.dom.Dependency;
46 import org.jetbrains.idea.devkit.dom.IdeaPlugin;
47 import org.jetbrains.idea.devkit.module.PluginModuleType;
48 import org.jetbrains.idea.devkit.projectRoots.IdeaJdk;
49 import org.jetbrains.idea.devkit.util.DescriptorUtil;
51 import java.util.ArrayList;
52 import java.util.HashSet;
54 /**
55 * @author peter
57 public class PluginBuildParticipant extends BuildParticipantBase {
58 @NonNls private static final String CLASSES = "/classes";
59 @NonNls private static final String LIB = "/lib/";
60 @NonNls private static final String LIB_DIRECTORY = "lib";
61 private final PluginBuildConfiguration myPluginBuildConfiguration;
63 public PluginBuildParticipant(final Module module, final PluginBuildConfiguration pluginBuildConfiguration) {
64 super(module);
65 myPluginBuildConfiguration = pluginBuildConfiguration;
68 public BuildRecipe getBuildInstructions(final CompileContext context) {
69 //todo[nik] cache?
70 final BuildRecipe buildRecipe = DeploymentUtil.getInstance().createBuildRecipe();
71 registerBuildInstructions(buildRecipe, context);
72 return buildRecipe;
75 protected void registerBuildInstructions(final BuildRecipe instructions, final CompileContext context) {
76 Sdk jdk = IdeaJdk.findIdeaJdk(ModuleRootManager.getInstance(getModule()).getSdk());
77 if (jdk != null && IdeaJdk.isFromIDEAProject(jdk.getHomePath())) {
78 return;
81 registerDescriptorCopyingInstructions(instructions, context);
83 if (jdk == null) {
84 context.addMessage(CompilerMessageCategory.ERROR, DevKitBundle.message("jdk.type.incorrect", getModule().getName()), null, -1, -1);
85 return;
88 final Module[] wrongSetDependencies = PluginBuildUtil.getWrongSetDependencies(getModule());
89 if (wrongSetDependencies.length != 0) {
90 boolean realProblems = false;
91 final String pluginId = DescriptorUtil.getPluginId(getModule());
93 for (Module dependency : wrongSetDependencies) {
94 if (!PluginModuleType.isOfType(dependency)) {
95 realProblems = true;
96 context.addMessage(CompilerMessageCategory.ERROR,
97 DevKitBundle.message("incorrect.dependency.non-plugin-module", dependency.getName(), getModule().getName()), null,
98 -1, -1);
100 else {
101 final XmlFile pluginXml = PluginModuleType.getPluginXml(dependency);
102 boolean isDeclared = false;
103 if (pluginXml != null) {
104 final XmlTag rootTag = pluginXml.getDocument().getRootTag();
105 final XmlTag[] dependencies = rootTag != null ? rootTag.findSubTags("depends") : XmlTag.EMPTY;
106 for (XmlTag dep : dependencies) {
107 if (dep.getValue().getTrimmedText().equals(pluginId)) {
108 isDeclared = true;
109 break;
113 if (!isDeclared) {
114 // make this a warning instead?
115 realProblems = true;
116 context.addMessage(CompilerMessageCategory.ERROR,
117 DevKitBundle.message("incorrect.dependency.not-declared", dependency.getName(), getModule().getName()), null, -1,
118 -1);
122 if (realProblems) return;
125 final String explodedPath = myPluginBuildConfiguration.getExplodedPath();
126 if (explodedPath == null) return; //where to put everything?
127 HashSet<Module> modules = new HashSet<Module>();
128 PluginBuildUtil.getDependencies(getModule(), modules);
130 ModuleLink[] containingModules = new ModuleLink[modules.size()];
131 int i = 0;
132 final DeploymentUtil makeUtil = DeploymentUtil.getInstance();
133 for (Module dep : modules) {
134 ModuleLink link = makeUtil.createModuleLink(dep, getModule());
135 containingModules[i++] = link;
136 link.setPackagingMethod(PackagingMethod.COPY_FILES);
137 link.setURI(CLASSES);
140 // output may be excluded, copy it nevertheless
141 makeUtil.addModuleOutputContents(context, instructions, getModule(), getModule(), CLASSES, explodedPath, null);
143 // child Java utility modules
144 makeUtil.addJavaModuleOutputs(getModule(), containingModules, instructions, context, explodedPath, DevKitBundle.message("presentable.plugin.module.name",
145 ModuleUtil.getModuleNameInReadAction(getModule())));
147 HashSet<Library> libs = new HashSet<Library>();
148 PluginBuildUtil.getLibraries(getModule(), libs);
149 for (Module dependentModule : modules) {
150 PluginBuildUtil.getLibraries(dependentModule, libs);
153 final LibraryLink[] libraryLinks = new LibraryLink[libs.size()];
154 i = 0;
155 for (Library library : libs) {
156 LibraryLink link = makeUtil.createLibraryLink(library, getModule());
157 libraryLinks[i++] = link;
158 link.setPackagingMethod(PackagingMethod.COPY_FILES);
159 final boolean onlyDirs = link.hasDirectoriesOnly();
160 if (onlyDirs) {//todo split one lib into 2 separate libs if there are jars and dirs
161 link.setURI(CLASSES);
163 else {
164 link.setURI(LIB);
168 // libraries
169 final VirtualFile libDir = jdk.getHomeDirectory().findFileByRelativePath(LIB_DIRECTORY);
170 for (i = 0; i < libraryLinks.length; i++) {
171 LibraryLink libraryLink = libraryLinks[i];
172 final Library library = libraryLink.getLibrary();
173 if (library != null) {
174 VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
175 for (VirtualFile file : files) {
176 if (file.getFileSystem() instanceof JarFileSystem) {
177 file = ((JarFileSystem)file.getFileSystem()).getVirtualFileForJar(file);
179 if (libDir != null && file != null && VfsUtil.isAncestor(libDir, file, false)) {
180 context.addMessage(CompilerMessageCategory.ERROR, DevKitBundle.message("dont.add.idea.libs.to.classpath", file.getName()), null,
181 -1, -1);
184 makeUtil.addLibraryLink(context, instructions, libraryLink, getModule(), explodedPath);
189 protected CustomConfigFile[] getCustomDescriptors() {
190 final ConfigFile[] configFiles = getDeploymentDescriptors();
191 if (configFiles.length == 1) {
192 final ConfigFile configFile = configFiles[0];
193 final XmlFile xmlFile = configFile.getXmlFile();
194 if (xmlFile != null) {
195 final XmlDocument document = xmlFile.getDocument();
196 if (document != null) {
197 final DomElement domElement = DomManager.getDomManager(xmlFile.getProject()).getDomElement(document.getRootTag());
198 if (domElement instanceof IdeaPlugin) {
199 final ArrayList<CustomConfigFile> list = new ArrayList<CustomConfigFile>();
200 for(Dependency dependency: ((IdeaPlugin)domElement).getDependencies()) {
201 final String file = dependency.getConfigFile().getValue();
202 final VirtualFile virtualFile = configFile.getVirtualFile();
203 assert virtualFile != null;
204 final VirtualFile parent = virtualFile.getParent();
205 assert parent != null;
206 final String url = parent.getUrl();
207 list.add(new CustomConfigFile(url + "/" + file, configFile.getMetaData().getDirectoryPath()));
209 return list.toArray(new CustomConfigFile[list.size()]);
214 return super.getCustomDescriptors();
217 protected ConfigFile[] getDeploymentDescriptors() {
218 ConfigFile configFile = myPluginBuildConfiguration.getPluginXML();
219 if (configFile != null) {
220 return new ConfigFile[]{configFile};
222 return ConfigFile.EMPTY_ARRAY;
225 public BuildConfiguration getBuildConfiguration() {
226 return myPluginBuildConfiguration;