under USER_HOME, prefer storing paths relatively MODULE_DIR unless the common ancesto...
[idea/community.git] / platform / lang-impl / src / com / intellij / openapi / components / impl / ModulePathMacroManager.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
17 package com.intellij.openapi.components.impl;
18
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.module.Module;
24 import com.intellij.openapi.util.io.FileUtil;
25 import com.intellij.openapi.util.text.StringUtil;
26 import com.intellij.openapi.vfs.VirtualFile;
27 import org.jetbrains.annotations.Nullable;
28
29 import java.io.File;
30
31 public class ModulePathMacroManager extends BasePathMacroManager {
32   private final Module myModule;
33
34   public ModulePathMacroManager(final Module module) {
35     myModule = module;
36   }
37
38   public ExpandMacroToPathMap getExpandMacroMap() {
39     ExpandMacroToPathMap result = new ExpandMacroToPathMap();
40     getExpandModuleHomeReplacements(result);
41     result.putAll(super.getExpandMacroMap());
42     return result;
43   }
44
45   public ReplacePathToMacroMap getReplacePathMap() {
46     ReplacePathToMacroMap result = super.getReplacePathMap();
47     if (!myModule.isDisposed()) {
48       String projectDir = ProjectPathMacroManager.getProjectDir(myModule.getProject());
49       if (projectDir != null) {
50         projectDir = projectDir.replace('/', File.separatorChar);
51       }
52       String stopAt = projectDir;
53
54       final String userHome = getUserHome();
55       if (stopAt != null && stopAt.startsWith(userHome)) {
56         stopAt = userHome;
57       }
58
59       addFileHierarchyReplacements(result, PathMacrosImpl.MODULE_DIR_MACRO_NAME, getModuleDir(myModule.getModuleFilePath()), stopAt);
60     }
61     return result;
62   }
63
64   private void getExpandModuleHomeReplacements(ExpandMacroToPathMap result) {
65     String moduleDir = myModule.isDisposed() ? null : getModuleDir(myModule.getModuleFilePath());
66     if (moduleDir == null) return;
67
68     File f = new File(moduleDir.replace('/', File.separatorChar));
69
70     getExpandModuleHomeReplacements(result, f, "$" + PathMacrosImpl.MODULE_DIR_MACRO_NAME + "$");
71   }
72
73   private static void getExpandModuleHomeReplacements(ExpandMacroToPathMap result, File f, String macro) {
74     if (f == null) return;
75
76     getExpandModuleHomeReplacements(result, f.getParentFile(), macro + "/..");
77     String path = PathMacroMap.quotePath(f.getAbsolutePath());
78     String s = macro;
79
80     if (StringUtil.endsWithChar(path, '/')) s += "/";
81
82     result.put(s, path);
83   }
84
85   @Nullable
86   private String getModuleDir(String moduleFilePath) {
87     File moduleDirFile = new File(moduleFilePath).getParentFile();
88     if (moduleDirFile == null) return null;
89
90     // hack so that, if a module is stored inside the .idea directory, the base directory
91     // rather than the .idea directory itself is considered the module root
92     // (so that a Ruby IDE project doesn't break if its directory is moved together with the .idea directory)
93     final VirtualFile baseDir = myModule.getProject().getBaseDir();
94     if (baseDir != null) {
95       File moduleDirParent = moduleDirFile.getParentFile();
96       if (moduleDirParent != null && moduleDirFile.getName().equals(".idea") &&
97           moduleDirParent.getPath().equals(FileUtil.toSystemDependentName(baseDir.getPath()))) {
98         moduleDirFile = moduleDirParent;
99       }
100     }
101     String moduleDir = moduleDirFile.getPath();
102     moduleDir = moduleDir.replace(File.separatorChar, '/');
103     if (moduleDir.endsWith(":/")) {
104       moduleDir = moduleDir.substring(0, moduleDir.length() - 1);
105     }
106     return moduleDir;
107   }
108
109 }