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 com.intellij.openapi.components.impl;
18 import com.intellij.application.options.PathMacrosImpl;
19 import com.intellij.application.options.ReplacePathToMacroMap;
20 import com.intellij.openapi.application.PathManager;
21 import com.intellij.openapi.components.ExpandMacroToPathMap;
22 import com.intellij.openapi.components.PathMacroManager;
23 import com.intellij.openapi.components.PathMacroMap;
24 import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
25 import com.intellij.openapi.util.SystemInfo;
26 import com.intellij.openapi.util.text.StringUtil;
27 import com.intellij.util.SystemProperties;
28 import com.intellij.util.containers.FactoryMap;
29 import org.jdom.Element;
30 import org.jetbrains.annotations.NonNls;
31 import org.jetbrains.annotations.Nullable;
36 public class BasePathMacroManager extends PathMacroManager {
37 private PathMacrosImpl myPathMacros;
39 protected static void addFileHierarchyReplacements(ReplacePathToMacroMap result,
41 @Nullable String _path, @Nullable String stopAt) {
46 String macro = "$" + variableName + "$";
47 File dir = new File(_path.replace('/', File.separatorChar));
48 boolean check = false;
49 while (dir != null && dir.getParentFile() != null) {
50 @NonNls String path = PathMacroMap.quotePath(dir.getAbsolutePath());
53 if (StringUtil.endsWithChar(path, '/')) s += "/";
55 putIfAbsent(result, "file:" + path, "file:" + s, check);
56 putIfAbsent(result, "file:/" + path, "file:/" + s, check);
57 putIfAbsent(result, "file://" + path, "file://" + s, check);
58 putIfAbsent(result, "jar:" + path, "jar:" + s, check);
59 putIfAbsent(result, "jar:/" + path, "jar:/" + s, check);
60 putIfAbsent(result, "jar://" + path, "jar://" + s, check);
61 if (!path.equalsIgnoreCase("e:/") && !path.equalsIgnoreCase("r:/") && !path.equalsIgnoreCase("p:/")) {
62 putIfAbsent(result, path, s, check);
65 if (dir.getPath().equals(stopAt)) {
71 dir = dir.getParentFile();
75 public ExpandMacroToPathMap getExpandMacroMap() {
76 ExpandMacroToPathMap result = new ExpandMacroToPathMap();
77 result.addMacroExpand(PathMacrosImpl.APPLICATION_HOME_MACRO_NAME, PathManager.getHomePath());
78 result.addMacroExpand(PathMacrosImpl.USER_HOME_MACRO_NAME, getUserHome());
79 getPathMacros().addMacroExpands(result);
83 protected static String getUserHome() {
84 return SystemProperties.getUserHome();
88 public ReplacePathToMacroMap getReplacePathMap() {
89 ReplacePathToMacroMap result = new ReplacePathToMacroMap();
91 result.addMacroReplacement(PathManager.getHomePath(), PathMacrosImpl.APPLICATION_HOME_MACRO_NAME);
92 result.addMacroReplacement(getUserHome(), PathMacrosImpl.USER_HOME_MACRO_NAME);
93 getPathMacros().addMacroReplacements(result);
97 public TrackingPathMacroSubstitutor createTrackingSubstitutor() {
98 return new MyTrackingPathMacroSubstitutor();
101 public String expandPath(final String path) {
102 return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
105 public String collapsePath(final String path) {
106 return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
109 public void collapsePathsRecursively(final Element element) {
110 getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, true);
113 public void expandPaths(final Element element) {
114 getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
118 public void collapsePaths(final Element element) {
119 getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
122 public PathMacrosImpl getPathMacros() {
123 if (myPathMacros == null) {
124 myPathMacros = PathMacrosImpl.getInstanceEx();
131 protected static void putIfAbsent(final ReplacePathToMacroMap result, @NonNls final String pathWithPrefix, @NonNls final String substWithPrefix, final boolean check) {
132 if (check && result.get(pathWithPrefix) != null) return;
133 result.put(pathWithPrefix, substWithPrefix);
136 private class MyTrackingPathMacroSubstitutor implements TrackingPathMacroSubstitutor {
137 private final Map<String, Set<String>> myMacroToComponentNames = new FactoryMap<String, Set<String>>() {
139 protected Set<String> create(String key) {
140 return new HashSet<String>();
144 private final Map<String, Set<String>> myComponentNameToMacros = new FactoryMap<String, Set<String>>() {
146 protected Set<String> create(String key) {
147 return new HashSet<String>();
151 public MyTrackingPathMacroSubstitutor() {
154 public void reset() {
155 myMacroToComponentNames.clear();
156 myComponentNameToMacros.clear();
159 public String expandPath(final String path) {
160 return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
163 public String collapsePath(final String path) {
164 return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
167 public void expandPaths(final Element element) {
168 getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
171 public void collapsePaths(final Element element) {
172 getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
175 public int hashCode() {
176 return getExpandMacroMap().hashCode();
179 public void invalidateUnknownMacros(final Set<String> macros) {
180 for (final String macro : macros) {
181 final Set<String> components = myMacroToComponentNames.get(macro);
182 for (final String component : components) {
183 myComponentNameToMacros.remove(component);
186 myMacroToComponentNames.remove(macro);
190 public Collection<String> getComponents(final Collection<String> macros) {
191 final Set<String> result = new HashSet<String>();
192 for (String macro : myMacroToComponentNames.keySet()) {
193 if (macros.contains(macro)) {
194 result.addAll(myMacroToComponentNames.get(macro));
201 public Collection<String> getUnknownMacros(final String componentName) {
202 final Set<String> result = new HashSet<String>();
203 result.addAll(componentName == null ? myMacroToComponentNames.keySet() : myComponentNameToMacros.get(componentName));
204 return Collections.unmodifiableCollection(result);
207 public void addUnknownMacros(final String componentName, final Collection<String> unknownMacros) {
208 if (unknownMacros.isEmpty()) return;
210 for (String unknownMacro : unknownMacros) {
211 final Set<String> stringList = myMacroToComponentNames.get(unknownMacro);
212 stringList.add(componentName);
215 myComponentNameToMacros.get(componentName).addAll(unknownMacros);