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
;
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
) {
68 myPluginBuildConfiguration
= pluginBuildConfiguration
;
72 public Artifact
createArtifact(CompileContext context
) {
73 Sdk jdk
= IdeaJdk
.findIdeaJdk(ModuleRootManager
.getInstance(myModule
).getSdk());
74 if (jdk
!= null && IdeaJdk
.isFromIDEAProject(jdk
.getHomePath())) {
79 context
.addMessage(CompilerMessageCategory
.ERROR
, DevKitBundle
.message("jdk.type.incorrect", myModule
.getName()), null, -1, -1);
83 final String outputPath
= PluginBuildUtil
.getPluginExPath(myModule
);
84 if (outputPath
== null) {
88 if (!checkDependencies(context
)) {
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
);
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
) {
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,
153 final List
<?
extends PackagingElement
<?
>> elements
= factory
.createLibraryElements(library
);
155 //todo split one lib into 2 separate libs if there are jars and dirs
156 classesDir
.addOrFindChildren(elements
);
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
)) {
179 context
.addMessage(CompilerMessageCategory
.ERROR
,
180 DevKitBundle
.message("incorrect.dependency.non-plugin-module", dependency
.getName(), myModule
.getName()), null,
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
)) {
197 // make this a warning instead?
199 context
.addMessage(CompilerMessageCategory
.ERROR
,
200 DevKitBundle
.message("incorrect.dependency.not-declared", dependency
.getName(), myModule
.getName()), null, -1,
205 if (realProblems
) return false;