b06b4219704056f661fbdf8340c930f0b9622371
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / components / impl / BasePathMacroManager.java
1 /*
2  * Copyright 2000-2009 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.openapi.components.impl;
17
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;
32
33 import java.io.File;
34 import java.util.*;
35
36 public class BasePathMacroManager extends PathMacroManager {
37   private PathMacrosImpl myPathMacros;
38
39   protected static void addFileHierarchyReplacements(ReplacePathToMacroMap result,
40                                                      String variableName,
41                                                      @Nullable String _path, @Nullable String stopAt) {
42     if (_path == null) {
43       return;
44     }
45
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());
51       String s = macro;
52
53       if (StringUtil.endsWithChar(path, '/')) s += "/";
54
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);
63       }
64
65       if (dir.getPath().equals(stopAt)) {
66         break;
67       }
68
69       macro += "/..";
70       check = true;
71       dir = dir.getParentFile();
72     }
73   }
74
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, SystemProperties.getUserHome());
79     getPathMacros().addMacroExpands(result);
80     return result;
81   }
82
83
84   public ReplacePathToMacroMap getReplacePathMap() {
85     ReplacePathToMacroMap result = new ReplacePathToMacroMap();
86
87     result.addMacroReplacement(PathManager.getHomePath(), PathMacrosImpl.APPLICATION_HOME_MACRO_NAME);
88     result.addMacroReplacement(SystemProperties.getUserHome(), PathMacrosImpl.USER_HOME_MACRO_NAME);
89     getPathMacros().addMacroReplacements(result);
90     return result;
91   }
92
93   public TrackingPathMacroSubstitutor createTrackingSubstitutor() {
94     return new MyTrackingPathMacroSubstitutor();
95   }
96
97   public String expandPath(final String path) {
98     return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
99   }
100
101   public String collapsePath(final String path) {
102     return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
103   }
104
105   public void collapsePathsRecursively(final Element element) {
106     getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, true);
107   }
108
109   public void expandPaths(final Element element) {
110     getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
111   }
112
113
114   public void collapsePaths(final Element element) {
115     getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
116   }
117
118   public PathMacrosImpl getPathMacros() {
119     if (myPathMacros == null) {
120       myPathMacros = PathMacrosImpl.getInstanceEx();
121     }
122
123     return myPathMacros;
124   }
125
126
127   protected static void putIfAbsent(final ReplacePathToMacroMap result, @NonNls final String pathWithPrefix, @NonNls final String substWithPrefix, final boolean check) {
128     if (check && result.get(pathWithPrefix) != null) return;
129     result.put(pathWithPrefix, substWithPrefix);
130   }
131
132   private class MyTrackingPathMacroSubstitutor implements TrackingPathMacroSubstitutor {
133     private final Map<String, Set<String>> myMacroToComponentNames = new FactoryMap<String, Set<String>>() {
134       @Override
135       protected Set<String> create(String key) {
136         return new HashSet<String>();
137       }
138     };
139
140     private final Map<String, Set<String>> myComponentNameToMacros = new FactoryMap<String, Set<String>>() {
141       @Override
142       protected Set<String> create(String key) {
143         return new HashSet<String>();
144       }
145     };
146
147     public MyTrackingPathMacroSubstitutor() {
148     }
149
150     public void reset() {
151       myMacroToComponentNames.clear();
152       myComponentNameToMacros.clear();
153     }
154
155     public String expandPath(final String path) {
156       return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
157     }
158
159     public String collapsePath(final String path) {
160       return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
161     }
162
163     public void expandPaths(final Element element) {
164       getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
165     }
166
167     public void collapsePaths(final Element element) {
168       getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
169     }
170
171     public int hashCode() {
172       return getExpandMacroMap().hashCode();
173     }
174
175     public void invalidateUnknownMacros(final Set<String> macros) {
176       for (final String macro : macros) {
177         final Set<String> components = myMacroToComponentNames.get(macro);
178         for (final String component : components) {
179           myComponentNameToMacros.remove(component);
180         }
181
182         myMacroToComponentNames.remove(macro);
183       }
184     }
185
186     public Collection<String> getComponents(final Collection<String> macros) {
187       final Set<String> result = new HashSet<String>();
188       for (String macro : myMacroToComponentNames.keySet()) {
189         if (macros.contains(macro)) {
190           result.addAll(myMacroToComponentNames.get(macro));
191         }
192       }
193
194       return result;
195     }
196
197     public Collection<String> getUnknownMacros(final String componentName) {
198       final Set<String> result = new HashSet<String>();
199       result.addAll(componentName == null ? myMacroToComponentNames.keySet() : myComponentNameToMacros.get(componentName));
200       return Collections.unmodifiableCollection(result);
201     }
202
203     public void addUnknownMacros(final String componentName, final Collection<String> unknownMacros) {
204       if (unknownMacros.isEmpty()) return;
205       
206       for (String unknownMacro : unknownMacros) {
207         final Set<String> stringList = myMacroToComponentNames.get(unknownMacro);
208         stringList.add(componentName);
209       }
210
211       myComponentNameToMacros.get(componentName).addAll(unknownMacros);
212     }
213   }
214 }