fix module relative macro replacements: do not step out of the project dir
[fedora-idea.git] / platform / lang-impl / src / com / intellij / openapi / components / impl / ModulePathMacroManager.java
blob190edb0a76912e52b6aaec1050abfc1f335edf58
1 /*
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.
17 package com.intellij.openapi.components.impl;
19 import com.intellij.application.options.PathMacrosImpl;
20 import com.intellij.application.options.ReplacePathToMacroMap;
21 import com.intellij.openapi.components.ExpandMacroToPathMap;
22 import com.intellij.openapi.components.PathMacroMap;
23 import com.intellij.openapi.diagnostic.Logger;
24 import com.intellij.openapi.module.Module;
25 import com.intellij.openapi.util.io.FileUtil;
26 import com.intellij.openapi.util.text.StringUtil;
27 import com.intellij.openapi.vfs.VirtualFile;
28 import org.jetbrains.annotations.NonNls;
29 import org.jetbrains.annotations.Nullable;
31 import java.io.File;
33 public class ModulePathMacroManager extends BasePathMacroManager /*ProjectPathMacroManager*/ {
34 private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.ModulePathMacroManager");
36 private final Module myModule;
39 public ModulePathMacroManager(final Module module) {
40 //super((ProjectEx) module.getProject());
41 myModule = module;
44 public ExpandMacroToPathMap getExpandMacroMap() {
45 ExpandMacroToPathMap result = new ExpandMacroToPathMap();
46 getExpandModuleHomeReplacements(result);
47 result.putAll(super.getExpandMacroMap());
48 return result;
51 public ReplacePathToMacroMap getReplacePathMap() {
52 ReplacePathToMacroMap result = new ReplacePathToMacroMap();
53 getModuleHomeReplacements(result, false);
54 result.putAll(super.getReplacePathMap());
55 getModuleHomeReplacements(result, true); // TODO: change to false and remove previous call to this method to save ABSOLUTE paths
56 return result;
59 private void getExpandModuleHomeReplacements(ExpandMacroToPathMap result) {
60 String moduleDir = getModuleDir(myModule.getModuleFilePath());
61 if (moduleDir == null) return;
63 File f = new File(moduleDir.replace('/', File.separatorChar));
65 getExpandModuleHomeReplacements(result, f, "$" + PathMacrosImpl.MODULE_DIR_MACRO_NAME + "$");
68 private static void getExpandModuleHomeReplacements(ExpandMacroToPathMap result, File f, String macro) {
69 if (f == null) return;
71 getExpandModuleHomeReplacements(result, f.getParentFile(), macro + "/..");
72 String path = PathMacroMap.quotePath(f.getAbsolutePath());
73 String s = macro;
75 if (StringUtil.endsWithChar(path, '/')) s += "/";
77 result.put(s, path);
80 private void getModuleHomeReplacements(@NonNls ReplacePathToMacroMap result, final boolean addRelativePathMacros) {
81 String moduleDir = getModuleDir(myModule.getModuleFilePath());
82 if (moduleDir == null) return;
84 File f = new File(moduleDir.replace('/', File.separatorChar));
85 // [dsl]: Q?
86 //if(!f.exists()) return;
88 final VirtualFile baseDir = myModule.getProject().getBaseDir();
89 final String projectParent = baseDir != null && baseDir.getParent() != null ? PathMacroMap.quotePath(baseDir.getParent().getPath()): null;
91 String macro = "$" + PathMacrosImpl.MODULE_DIR_MACRO_NAME + "$";
92 boolean check = false;
93 while (f != null) {
94 @NonNls String path = PathMacroMap.quotePath(f.getAbsolutePath());
95 String s = macro;
97 if (projectParent != null && path.equals(projectParent)) {
98 break; // never step out of the project dir
101 if (StringUtil.endsWithChar(path, '/')) s += "/";
102 if (path.equals("/")) break;
104 putIfAbsent(result, "file://" + path, "file://" + s, check);
105 putIfAbsent(result, "file:/" + path, "file:/" + s, check);
106 putIfAbsent(result, "file:" + path, "file:" + s, check);
107 putIfAbsent(result, "jar://" + path, "jar://" + s, check);
108 putIfAbsent(result, "jar:/" + path, "jar:/" + s, check);
109 putIfAbsent(result, "jar:" + path, "jar:" + s, check);
110 if (!path.equalsIgnoreCase("e:/") && !path.equalsIgnoreCase("r:/") && !path.equalsIgnoreCase("p:/")) {
111 putIfAbsent(result, path, s, check);
114 if (!addRelativePathMacros) break;
115 macro += "/..";
116 check = true;
117 f = f.getParentFile();
121 @Nullable
122 private String getModuleDir(String moduleFilePath) {
123 File moduleDirFile = new File(moduleFilePath).getParentFile();
124 if (moduleDirFile == null) return null;
126 // hack so that, if a module is stored inside the .idea directory, the base directory
127 // rather than the .idea directory itself is considered the module root
128 // (so that a Ruby IDE project doesn't break if its directory is moved together with the .idea directory)
129 final VirtualFile baseDir = myModule.getProject().getBaseDir();
130 if (baseDir != null) {
131 File moduleDirParent = moduleDirFile.getParentFile();
132 if (moduleDirParent != null && moduleDirFile.getName().equals(".idea") &&
133 moduleDirParent.getPath().equals(FileUtil.toSystemDependentName(baseDir.getPath()))) {
134 moduleDirFile = moduleDirParent;
137 String moduleDir = moduleDirFile.getPath();
138 moduleDir = moduleDir.replace(File.separatorChar, '/');
139 if (moduleDir.endsWith(":/")) {
140 moduleDir = moduleDir.substring(0, moduleDir.length() - 1);
142 return moduleDir;