/platform/projectModel-impl/src/com/intellij/application/options/PathMacrosImpl.java

https://bitbucket.org/nbargnesi/idea · Java · 366 lines · 302 code · 44 blank · 20 comment · 32 complexity · 7962efdc0df611042b575dc8fbc01147 MD5 · raw file

  1. /*
  2. * Copyright 2000-2012 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 com.intellij.application.options;
  17. import com.intellij.openapi.application.ApplicationManager;
  18. import com.intellij.openapi.application.PathMacros;
  19. import com.intellij.openapi.application.PathManager;
  20. import com.intellij.openapi.components.ApplicationComponent;
  21. import com.intellij.openapi.components.ExpandMacroToPathMap;
  22. import com.intellij.openapi.diagnostic.Logger;
  23. import com.intellij.openapi.util.InvalidDataException;
  24. import com.intellij.openapi.util.NamedJDOMExternalizable;
  25. import com.intellij.openapi.util.RoamingTypeDisabled;
  26. import com.intellij.openapi.util.WriteExternalException;
  27. import com.intellij.openapi.util.io.FileUtil;
  28. import com.intellij.openapi.util.text.StringUtil;
  29. import com.intellij.util.SystemProperties;
  30. import com.intellij.util.containers.ContainerUtil;
  31. import com.intellij.util.containers.HashMap;
  32. import gnu.trove.THashSet;
  33. import org.jdom.Element;
  34. import org.jetbrains.annotations.NonNls;
  35. import org.jetbrains.annotations.NotNull;
  36. import java.util.*;
  37. import java.util.concurrent.locks.ReentrantReadWriteLock;
  38. /**
  39. * @author dsl
  40. */
  41. public class PathMacrosImpl extends PathMacros implements ApplicationComponent, NamedJDOMExternalizable, RoamingTypeDisabled {
  42. private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.PathMacrosImpl");
  43. private final Map<String, String> myLegacyMacros = new HashMap<String, String>();
  44. private final Map<String, String> myMacros = new HashMap<String, String>();
  45. private final ReentrantReadWriteLock myLock = new ReentrantReadWriteLock();
  46. private final List<String> myIgnoredMacros = ContainerUtil.createEmptyCOWList();
  47. @NonNls
  48. public static final String MACRO_ELEMENT = "macro";
  49. @NonNls
  50. public static final String NAME_ATTR = "name";
  51. @NonNls
  52. public static final String VALUE_ATTR = "value";
  53. @NonNls
  54. public static final String IGNORED_MACRO_ELEMENT = "ignoredMacro";
  55. // predefined macros
  56. @NonNls
  57. public static final String APPLICATION_HOME_MACRO_NAME = "APPLICATION_HOME_DIR";
  58. @NonNls
  59. public static final String PROJECT_DIR_MACRO_NAME = "PROJECT_DIR";
  60. @NonNls
  61. public static final String MODULE_DIR_MACRO_NAME = "MODULE_DIR";
  62. @NonNls
  63. public static final String USER_HOME_MACRO_NAME = "USER_HOME";
  64. private static final Set<String> SYSTEM_MACROS = new HashSet<String>();
  65. @NonNls public static final String EXT_FILE_NAME = "path.macros";
  66. static {
  67. SYSTEM_MACROS.add(APPLICATION_HOME_MACRO_NAME);
  68. SYSTEM_MACROS.add(PROJECT_DIR_MACRO_NAME);
  69. SYSTEM_MACROS.add(MODULE_DIR_MACRO_NAME);
  70. SYSTEM_MACROS.add(USER_HOME_MACRO_NAME);
  71. }
  72. private static final Set<String> ourToolsMacros = ContainerUtil.immutableSet(
  73. "ClasspathEntry",
  74. "Classpath",
  75. "ColumnNumber",
  76. "FileClass",
  77. "FileDir",
  78. "FileDirRelativeToProjectRoot",
  79. "/FileDirRelativeToProjectRoot",
  80. "FileDirRelativeToSourcepath",
  81. "/FileDirRelativeToSourcepath",
  82. "FileExt",
  83. "FileFQPackage",
  84. "FileName",
  85. "FileNameWithoutExtension",
  86. "FilePackage",
  87. "FilePath",
  88. "FilePathRelativeToProjectRoot",
  89. "/FilePathRelativeToProjectRoot",
  90. "FilePathRelativeToSourcepath",
  91. "/FilePathRelativeToSourcepath",
  92. "FilePrompt",
  93. "FileRelativeDir",
  94. "/FileRelativeDir",
  95. "FileRelativePath",
  96. "/FileRelativePath",
  97. "FileEncoding",
  98. "JavaDocPath",
  99. "JDKPath",
  100. "LineNumber",
  101. "ModuleFileDir",
  102. "ModuleFilePath",
  103. "ModuleName",
  104. "ModuleSourcePath",
  105. "ModuleSdkPath",
  106. "OutputPath",
  107. "PhpExecutable",
  108. "ProjectFileDir",
  109. "ProjectFilePath",
  110. "ProjectName",
  111. "Projectpath",
  112. "Prompt",
  113. "SourcepathEntry",
  114. "Sourcepath",
  115. "SHOW_CHANGES",
  116. "SelectedText",
  117. "SelectionStartLine",
  118. "SelectionEndLine",
  119. "SelectionStartColumn",
  120. "SelectionEndColumn"
  121. );
  122. public PathMacrosImpl() {
  123. //setMacro(USER_HOME_MACRO_NAME, FileUtil.toSystemIndependentName(SystemProperties.getUserHome()));
  124. }
  125. public static PathMacrosImpl getInstanceEx() {
  126. return (PathMacrosImpl)ApplicationManager.getApplication().getComponent(PathMacros.class);
  127. }
  128. @NotNull
  129. public String getComponentName() {
  130. return "PathMacrosImpl";
  131. }
  132. public void initComponent() {
  133. }
  134. public void disposeComponent() {
  135. }
  136. public String getExternalFileName() {
  137. return EXT_FILE_NAME;
  138. }
  139. public Set<String> getUserMacroNames() {
  140. myLock.readLock().lock();
  141. try {
  142. return new THashSet<String>(myMacros.keySet()); // keyset should not escape the lock
  143. }
  144. finally {
  145. myLock.readLock().unlock();
  146. }
  147. }
  148. public static Set<String> getToolMacroNames() {
  149. return ourToolsMacros;
  150. }
  151. public Set<String> getSystemMacroNames() {
  152. return SYSTEM_MACROS;
  153. }
  154. @Override
  155. public Collection<String> getIgnoredMacroNames() {
  156. return myIgnoredMacros;
  157. }
  158. public void setIgnoredMacroNames(@NotNull final Collection<String> names) {
  159. myIgnoredMacros.clear();
  160. myIgnoredMacros.addAll(names);
  161. }
  162. @Override
  163. public void addIgnoredMacro(@NotNull String name) {
  164. if (!myIgnoredMacros.contains(name)) myIgnoredMacros.add(name);
  165. }
  166. public static Map<String, String> getGlobalSystemMacros() {
  167. final Map<String, String> map = new HashMap<String, String>();
  168. map.put(APPLICATION_HOME_MACRO_NAME, PathManager.getHomePath());
  169. map.put(USER_HOME_MACRO_NAME, getUserHome());
  170. return map;
  171. }
  172. @Override
  173. public boolean isIgnoredMacroName(@NotNull String macro) {
  174. return myIgnoredMacros.contains(macro);
  175. }
  176. public Set<String> getAllMacroNames() {
  177. final Set<String> userMacroNames = getUserMacroNames();
  178. final Set<String> systemMacroNames = getSystemMacroNames();
  179. final Set<String> allNames = new HashSet<String>(userMacroNames.size() + systemMacroNames.size());
  180. allNames.addAll(systemMacroNames);
  181. allNames.addAll(userMacroNames);
  182. return allNames;
  183. }
  184. public String getValue(String name) {
  185. try {
  186. myLock.readLock().lock();
  187. return myMacros.get(name);
  188. }
  189. finally {
  190. myLock.readLock().unlock();
  191. }
  192. }
  193. public void removeAllMacros() {
  194. try {
  195. myLock.writeLock().lock();
  196. myMacros.clear();
  197. }
  198. finally {
  199. myLock.writeLock().unlock();
  200. }
  201. }
  202. @Override
  203. public Collection<String> getLegacyMacroNames() {
  204. try {
  205. myLock.readLock().lock();
  206. return new THashSet<String>(myLegacyMacros.keySet()); // keyset should not escape the lock
  207. }
  208. finally {
  209. myLock.readLock().unlock();
  210. }
  211. }
  212. public void setMacro(@NotNull String name, @NotNull String value) {
  213. if (value.trim().length() == 0) return;
  214. try {
  215. myLock.writeLock().lock();
  216. myMacros.put(name, value);
  217. }
  218. finally {
  219. myLock.writeLock().unlock();
  220. }
  221. }
  222. @Override
  223. public void addLegacyMacro(@NotNull String name, @NotNull String value) {
  224. try {
  225. myLock.writeLock().lock();
  226. myLegacyMacros.put(name, value);
  227. myMacros.remove(name);
  228. }
  229. finally {
  230. myLock.writeLock().unlock();
  231. }
  232. }
  233. public void removeMacro(String name) {
  234. try {
  235. myLock.writeLock().lock();
  236. final String value = myMacros.remove(name);
  237. LOG.assertTrue(value != null);
  238. }
  239. finally {
  240. myLock.writeLock().unlock();
  241. }
  242. }
  243. public void readExternal(Element element) throws InvalidDataException {
  244. try {
  245. myLock.writeLock().lock();
  246. final List children = element.getChildren(MACRO_ELEMENT);
  247. for (Object aChildren : children) {
  248. Element macro = (Element)aChildren;
  249. final String name = macro.getAttributeValue(NAME_ATTR);
  250. String value = macro.getAttributeValue(VALUE_ATTR);
  251. if (name == null || value == null) {
  252. throw new InvalidDataException();
  253. }
  254. if (SYSTEM_MACROS.contains(name)) {
  255. continue;
  256. }
  257. if (value.length() > 1 && value.charAt(value.length() - 1) == '/') {
  258. value = value.substring(0, value.length() - 1);
  259. }
  260. myMacros.put(name, value);
  261. }
  262. final List ignoredChildren = element.getChildren(IGNORED_MACRO_ELEMENT);
  263. for (final Object child : ignoredChildren) {
  264. final Element macroElement = (Element)child;
  265. final String ignoredName = macroElement.getAttributeValue(NAME_ATTR);
  266. if (ignoredName != null && ignoredName.length() > 0 && !myIgnoredMacros.contains(ignoredName)) {
  267. myIgnoredMacros.add(ignoredName);
  268. }
  269. }
  270. }
  271. finally {
  272. myLock.writeLock().unlock();
  273. }
  274. }
  275. public void writeExternal(Element element) throws WriteExternalException {
  276. try {
  277. myLock.writeLock().lock();
  278. final Set<Map.Entry<String, String>> entries = myMacros.entrySet();
  279. for (Map.Entry<String, String> entry : entries) {
  280. final String value = entry.getValue();
  281. if (value != null && value.trim().length() > 0) {
  282. final Element macro = new Element(MACRO_ELEMENT);
  283. macro.setAttribute(NAME_ATTR, entry.getKey());
  284. macro.setAttribute(VALUE_ATTR, value);
  285. element.addContent(macro);
  286. }
  287. }
  288. for (final String macro : myIgnoredMacros) {
  289. final Element macroElement = new Element(IGNORED_MACRO_ELEMENT);
  290. macroElement.setAttribute(NAME_ATTR, macro);
  291. element.addContent(macroElement);
  292. }
  293. }
  294. finally {
  295. myLock.writeLock().unlock();
  296. }
  297. }
  298. public void addMacroReplacements(ReplacePathToMacroMap result) {
  299. for (final String name : getUserMacroNames()) {
  300. final String value = getValue(name);
  301. if (value != null && value.trim().length() > 0) result.addMacroReplacement(value, name);
  302. }
  303. }
  304. public void addMacroExpands(ExpandMacroToPathMap result) {
  305. for (final String name : getUserMacroNames()) {
  306. final String value = getValue(name);
  307. if (value != null && value.trim().length() > 0) result.addMacroExpand(name, value);
  308. }
  309. myLock.readLock().lock();
  310. try {
  311. for (Map.Entry<String, String> entry : myLegacyMacros.entrySet()) {
  312. result.addMacroExpand(entry.getKey(), entry.getValue());
  313. }
  314. }
  315. finally {
  316. myLock.readLock().unlock();
  317. }
  318. }
  319. public static String getUserHome() {
  320. return StringUtil.trimEnd(FileUtil.toSystemIndependentName(SystemProperties.getUserHome()), "/");
  321. }
  322. }