Make MODULE_FILE optional
[idea/community.git] / plugins / devkit / src / build / PluginBuildConfiguration.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.jetbrains.idea.devkit.build;
17
18 import com.intellij.openapi.application.AccessToken;
19 import com.intellij.openapi.application.ReadAction;
20 import com.intellij.openapi.application.Result;
21 import com.intellij.openapi.application.WriteAction;
22 import com.intellij.openapi.components.PersistentStateComponent;
23 import com.intellij.openapi.components.State;
24 import com.intellij.openapi.module.Module;
25 import com.intellij.openapi.module.ModuleServiceManager;
26 import com.intellij.openapi.module.ModuleType;
27 import com.intellij.openapi.ui.Messages;
28 import com.intellij.openapi.util.Disposer;
29 import com.intellij.openapi.util.io.FileUtil;
30 import com.intellij.openapi.util.text.StringUtil;
31 import com.intellij.openapi.vfs.LocalFileSystem;
32 import com.intellij.openapi.vfs.VfsUtilCore;
33 import com.intellij.openapi.vfs.VirtualFile;
34 import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
35 import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
36 import com.intellij.util.descriptors.ConfigFile;
37 import com.intellij.util.descriptors.ConfigFileContainer;
38 import com.intellij.util.descriptors.ConfigFileFactory;
39 import com.intellij.util.descriptors.ConfigFileInfo;
40 import com.intellij.util.xmlb.annotations.Attribute;
41 import org.jetbrains.annotations.NonNls;
42 import org.jetbrains.annotations.NotNull;
43 import org.jetbrains.annotations.Nullable;
44 import org.jetbrains.annotations.TestOnly;
45 import org.jetbrains.idea.devkit.DevKitBundle;
46 import org.jetbrains.idea.devkit.module.PluginDescriptorConstants;
47 import org.jetbrains.idea.devkit.module.PluginModuleType;
48
49 import java.io.File;
50
51 @State(name = "DevKit.ModuleBuildProperties")
52 public class PluginBuildConfiguration implements PersistentStateComponent<PluginBuildConfiguration.State> {
53   private final Module myModule;
54   private final ConfigFileContainer myPluginXmlContainer;
55   private VirtualFilePointer myManifestFilePointer;
56   private boolean myUseUserManifest = false;
57   @NonNls private static final String META_INF = "META-INF";
58   @NonNls private static final String PLUGIN_XML = "plugin.xml";
59
60   private State state = new State();
61
62   public PluginBuildConfiguration(@NotNull Module module) {
63     myModule = module;
64     myPluginXmlContainer = ConfigFileFactory.getInstance().createSingleFileContainer(myModule.getProject(), PluginDescriptorConstants.META_DATA);
65     Disposer.register(module, myPluginXmlContainer);
66   }
67
68   @Nullable
69   public static PluginBuildConfiguration getInstance(@NotNull Module module) {
70     return ModuleType.is(module, PluginModuleType.getInstance()) ? ModuleServiceManager.getService(module, PluginBuildConfiguration.class) : null;
71   }
72
73   static class State {
74     @Attribute
75     String url;
76
77     @Attribute
78     String manifest;
79
80     @Override
81     public boolean equals(Object o) {
82       if (this == o) return true;
83       if (o == null || getClass() != o.getClass()) return false;
84
85       State state = (State)o;
86
87       if (url != null ? !url.equals(state.url) : state.url != null) return false;
88       if (manifest != null ? !manifest.equals(state.manifest) : state.manifest != null) return false;
89
90       return true;
91     }
92
93     @Override
94     public int hashCode() {
95       int result = url != null ? url.hashCode() : 0;
96       result = 31 * result + (manifest != null ? manifest.hashCode() : 0);
97       return result;
98     }
99   }
100
101   @Nullable
102   @Override
103   public State getState() {
104     state.url = getPluginXmlUrl();
105     state.manifest = myManifestFilePointer == null ? null : myManifestFilePointer.getUrl();
106     return state;
107   }
108
109   @Override
110   public void loadState(State state) {
111     this.state = state;
112     if (state.url != null) {
113       myPluginXmlContainer.getConfiguration().replaceConfigFile(PluginDescriptorConstants.META_DATA, state.url);
114     }
115     if (state.manifest != null) {
116       setManifestPath(VfsUtilCore.urlToPath(state.manifest));
117     }
118   }
119
120   @Nullable
121   public ConfigFile getPluginXML() {
122     return myPluginXmlContainer.getConfigFile(PluginDescriptorConstants.META_DATA);
123   }
124
125   @TestOnly
126   public void setPluginXmlFromVirtualFile(VirtualFile virtualFile) {
127     myPluginXmlContainer.getConfiguration().replaceConfigFile(PluginDescriptorConstants.META_DATA, virtualFile.getUrl());
128   }
129
130   private void createDescriptor(final String url) {
131     final ConfigFileInfo descriptor = new ConfigFileInfo(PluginDescriptorConstants.META_DATA, url);
132     myPluginXmlContainer.getConfiguration().addConfigFile(descriptor);
133     ConfigFileFactory.getInstance().createFile(myModule.getProject(), descriptor.getUrl(), PluginDescriptorConstants.META_DATA.getDefaultVersion(),
134                                                false);
135   }
136
137   @Nullable
138   public ConfigFile getPluginXmlConfigFile() {
139     return myPluginXmlContainer.getConfigFile(PluginDescriptorConstants.META_DATA);
140   }
141
142   @Nullable
143   private String getPluginXmlUrl() {
144     ConfigFile configFile = getPluginXmlConfigFile();
145     return configFile != null ? configFile.getUrl() : null;
146   }
147
148   private String getDefaultLocation() {
149     return new File(myModule.getModuleFilePath()).getParent() + File.separator + META_INF + File.separator + PLUGIN_XML;
150   }
151
152   @NotNull
153   public String getPluginXmlPath() {
154     String url = getPluginXmlUrl();
155     if (url == null) {
156       return getDefaultLocation();
157     }
158     return FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(url));
159   }
160
161   public void setPluginXmlPathAndCreateDescriptorIfDoesntExist(final String pluginXmlPath) {
162     myPluginXmlContainer.getConfiguration().removeConfigFiles(PluginDescriptorConstants.META_DATA);
163     new WriteAction() {
164       @Override
165       protected void run(@NotNull final Result result) throws Throwable {
166         createDescriptor(VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(pluginXmlPath)));
167       }
168     }.execute();
169   }
170
171   public void setManifestPath(@Nullable String manifestPath) {
172     if (StringUtil.isEmpty(manifestPath)) {
173       myManifestFilePointer = null;
174       return;
175     }
176
177     VirtualFile manifest = LocalFileSystem.getInstance().findFileByPath(manifestPath);
178     if (manifest == null) {
179       Messages.showErrorDialog(myModule.getProject(), DevKitBundle.message("error.file.not.found.message", manifestPath), DevKitBundle.message("error.file.not.found"));
180       AccessToken token = ReadAction.start();
181       try {
182         myManifestFilePointer = VirtualFilePointerManager.getInstance().create(
183           VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(manifestPath)), myModule, null);
184       }
185       finally {
186         token.finish();
187       }
188     }
189     else {
190       AccessToken token = ReadAction.start();
191       try {
192         myManifestFilePointer = VirtualFilePointerManager.getInstance().create(manifest, myModule, null);
193       }
194       finally {
195         token.finish();
196       }
197     }
198   }
199
200   @Nullable
201   public String getManifestPath() {
202     return myManifestFilePointer != null ? FileUtil.toSystemDependentName(myManifestFilePointer.getPresentableUrl()) : null;
203   }
204
205   @Nullable
206   public VirtualFile getManifest(){
207     return myManifestFilePointer != null ? myManifestFilePointer.getFile() : null;
208   }
209
210   public boolean isUseUserManifest() {
211     return myUseUserManifest;
212   }
213
214   public void setUseUserManifest(final boolean useUserManifest) {
215     myUseUserManifest = useUserManifest;
216   }
217 }