View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.core;
35  
36  import java.io.File;
37  import java.io.IOException;
38  
39  import javax.jcr.RepositoryException;
40  
41  import org.apache.commons.lang.StringUtils;
42  import org.safehaus.uuid.UUIDGenerator;
43  
44  
45  /**
46   * Utility class to retrieve files or directory used by Magnolia. Examples: cache directory, tmp files, ..
47   * @author Sameer Charles
48   * @version 2.0 $Id: Path.java 36516 2010-08-18 15:12:02Z pbaerfuss $
49   */
50  public final class Path {
51      /**
52       * New unlabeled nodes default name.
53       */
54      private static final String DEFAULT_UNTITLED_NODE_NAME = "untitled";
55  
56      /**
57       * Utility class, don't instantiate.
58       */
59      private Path() {
60          // unused
61      }
62  
63      /**
64       * Gets the cache directory path (cms.cache.startdir) as set with Java options while startup or in web.xml.
65       * @return Cache directory path
66       */
67      public static String getCacheDirectoryPath() {
68          return getCacheDirectory().getAbsolutePath();
69      }
70  
71      public static File getCacheDirectory() {
72          String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_CACHE_STARTDIR);
73          File dir = isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
74          dir.mkdirs();
75          return dir;
76      }
77  
78      /**
79       * Gets the temporary directory path (cms.upload.tmpdir) as set with Java options while startup or in web.xml.
80       * @return Temporary directory path
81       */
82      public static String getTempDirectoryPath() {
83          return getTempDirectory().getAbsolutePath();
84      }
85  
86      public static File getTempDirectory() {
87          String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_UPLOAD_TMPDIR);
88          File dir = isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
89          dir.mkdirs();
90          return dir;
91      }
92  
93      /**
94       * Gets cms.exchange.history file location as set with Java options while startup or in web.xml.
95       * @return exchange history file location
96       */
97      public static String getHistoryFilePath() {
98          return getHistoryFile().getAbsolutePath();
99      }
100 
101     public static File getHistoryFile() {
102         String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_EXCHANGE_HISTORY);
103         return isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
104     }
105 
106     /**
107      * Gets repositories file location as set with Java options while startup or in web.xml.
108      * @return file location
109      */
110     public static String getRepositoriesConfigFilePath() {
111         return getRepositoriesConfigFile().getAbsolutePath();
112     }
113 
114     public static File getRepositoriesConfigFile() {
115         String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_REPOSITORIES_CONFIG);
116         return isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
117     }
118 
119     /**
120      * Gets the root directory for the magnolia web application.
121      * @return magnolia root dir
122      */
123     public static File getAppRootDir() {
124         return new File(SystemProperty.getProperty(SystemProperty.MAGNOLIA_APP_ROOTDIR));
125     }
126 
127     // TODO : this should probably be in getAppRootDir()
128     private void checkAppRootDir() throws IOException {
129         String root = null;
130         // Try to get root
131         try {
132             File f = getAppRootDir();
133             if (f.isDirectory()) {
134                 root = f.getAbsolutePath();
135             }
136         }
137         catch (Exception e) {
138             // nothing
139         }
140 
141         if (root == null) {
142             throw new IOException("Invalid magnolia " + SystemProperty.MAGNOLIA_APP_ROOTDIR + " path"); //$NON-NLS-1$ //$NON-NLS-2$
143         }
144     }
145 
146     /**
147      * Gets absolute filesystem path, adds application root if path is not absolute.
148      */
149     public static String getAbsoluteFileSystemPath(String path) {
150         if (isAbsolute(path)) {
151             return path;
152         }
153         // using the file() constructor will allow relative paths in the form ../../apps
154         return new File(getAppRootDir(), path).getAbsolutePath();
155     }
156 
157     public static String getUniqueLabel(HierarchyManager hierarchyManager, String parent, String label) {
158         if (parent.equals("/")) { //$NON-NLS-1$
159             parent = StringUtils.EMPTY;
160         }
161         while (hierarchyManager.isExist(parent + "/" + label)) { //$NON-NLS-1$
162             label = createUniqueName(label);
163         }
164         return label;
165     }
166 
167     public static String getUniqueLabel(Content parent, String label) {
168         try {
169             while (parent.hasContent(label) || parent.hasNodeData(label)) { //$NON-NLS-1$
170                 label = createUniqueName(label);
171             }
172         }
173         catch (RepositoryException e) {
174             label = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
175         }
176         return label;
177     }
178 
179     public static boolean isAbsolute(String path) {
180 
181         if (path == null) {
182             return false;
183         }
184 
185         if (path.startsWith("/") || path.startsWith(File.separator)) { //$NON-NLS-1$
186             return true;
187         }
188 
189         // windows c:
190         if (path.length() >= 3 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') {
191             return true;
192         }
193 
194         return false;
195     }
196 
197     /**
198      * Replace illegal characters based on system property magnolia.ut8.enabled.
199      * @param label label to validate
200      * @return validated label
201      */
202     public static String getValidatedLabel(String label)
203     {
204         String charset = StringUtils.EMPTY;
205         if ((SystemProperty.getBooleanProperty(SystemProperty.MAGNOLIA_UTF8_ENABLED)))
206         {
207             charset = "UTF-8";
208         }
209         return getValidatedLabel(label, charset);
210 
211     }
212 
213     /**
214      * If charset eq to UTF-8 replaces these characters:
215      * jackrabbit not allowed 32: [ ] 91: [[] 93: []] 42: [*] 34: ["] 46: [.] 58 [:] 92: [\] 39 :[']
216      * url not valid 59: [;] 47: [/] 63: [?] 43: [+] 37: [%] 33: [!] 35:[#] 94: [^]
217      *
218      * else replace illegal characters except [_] [0-9], [A-Z], [a-z], [-], [_].
219      * @param label label to validate
220      * @return validated label
221      */
222     public static String getValidatedLabel(String label, String charset)
223     {
224         StringBuffer s = new StringBuffer(label);
225         StringBuffer newLabel = new StringBuffer();
226 
227         for (int i = 0; i < s.length(); i++)
228         {
229             int charCode = s.charAt(i);
230             if (isCharValid(charCode, charset))
231             {
232                 newLabel.append(s.charAt(i));
233             }
234             else
235             {
236                 newLabel.append("-"); //$NON-NLS-1$
237             }
238         }
239         if (newLabel.length() == 0)
240         {
241             newLabel.append(DEFAULT_UNTITLED_NODE_NAME);
242         }
243         return newLabel.toString();
244     }
245 
246     /**
247      * @param charCode char code
248      * @param charset charset (ex. UTF-8)
249      * @return true if char can be used as a content name
250      */
251     public static boolean isCharValid(int charCode, String charset)
252     {
253         // http://www.ietf.org/rfc/rfc1738.txt
254         // safe = "$" | "-" | "_" | "." | "+"
255         // extra = "!" | "*" | "'" | "(" | ")" | ","
256         // national = "{" | "}" | "|" | "\" | "^" | "~" | "[" | "]" | "`"
257         // punctuation = "<" | ">" | "#" | "%" | <">
258         // reserved = ";" | "/" | "?" | ":" | "@" | "&" | "="
259 
260         if ("UTF-8".equals(charset))
261         {
262             // jackrabbit not allowed 32: [ ] 91: [[] 93: []] 42: [*] 34: ["] 46: [.] 58 [:] 92: [\] 39 :[']
263             // url not valid 59: [;] 47: [/] 63: [?] 43: [+] 37: [%] 33: [!] 35:[#]
264             if (charCode != 32
265                 && charCode != '['
266                 && charCode != ']'
267                 && charCode != '*'
268                 && charCode != '"'
269                 && charCode != '.'
270                 && charCode != ':'
271                 && charCode != 92
272                 && charCode != 39
273                 && charCode != ';'
274                 && charCode != '/'
275                 && charCode != '?'
276                 && charCode != '+'
277                 && charCode != '%'
278                 && charCode != '!'
279                 && charCode != '#'
280                 && charCode != '@'
281                 && charCode != '&'
282                 && charCode != '=')
283             {
284                 return true;
285             }
286         }
287         else
288         {
289             // charCodes: 48-57: [0-9]; 65-90: [A-Z]; 97-122: [a-z]; 45: [-]; 95:[_]
290             if (((charCode >= 48) && (charCode <= 57))
291                 || ((charCode >= 65) && (charCode <= 90))
292                 || ((charCode >= 97) && (charCode <= 122))
293                 || charCode == 45
294                 || charCode == 95)
295             {
296                 return true;
297             }
298 
299         }
300         return false;
301 
302     }
303 
304     private static String createUniqueName(String baseName) {
305         int pos;
306         for (pos = baseName.length() - 1; pos >= 0; pos--) {
307             char c = baseName.charAt(pos);
308             if (c < '0' || c > '9') {
309                 break;
310             }
311         }
312         String base;
313         int cnt;
314         if (pos == -1) {
315             if (baseName.length() > 1) {
316                 pos = baseName.length() - 2;
317             }
318         }
319         if (pos == -1) {
320             base = baseName;
321             cnt = -1;
322         }
323         else {
324             pos++;
325             base = baseName.substring(0, pos);
326             if (pos == baseName.length()) {
327                 cnt = -1;
328             }
329             else {
330                 cnt = new Integer(baseName.substring(pos)).intValue();
331             }
332         }
333         return (base + ++cnt);
334     }
335 
336     public static String getAbsolutePath(String path, String label) {
337         if (StringUtils.isEmpty(path) || (path.equals("/"))) { //$NON-NLS-1$
338             return "/" + label; //$NON-NLS-1$
339         }
340 
341         return path + "/" + label; //$NON-NLS-1$
342     }
343 
344     public static String getAbsolutePath(String path) {
345         if (!path.startsWith("/")) { //$NON-NLS-1$
346             return "/" + path; //$NON-NLS-1$
347         }
348         return path;
349     }
350 
351     /**
352      * @deprecated since 4.0 - untested and unused
353      */
354     public static String getNodePath(String path, String label) {
355         if (StringUtils.isEmpty(path) || (path.equals("/"))) { //$NON-NLS-1$
356             return label;
357         }
358         return getNodePath(path + "/" + label); //$NON-NLS-1$
359     }
360 
361     /**
362      * @deprecated since 4.0 - untested and unused
363      */
364     public static String getNodePath(String path) {
365         if (path.startsWith("/")) { //$NON-NLS-1$
366             return path.replaceFirst("/", StringUtils.EMPTY); //$NON-NLS-1$
367         }
368         return path;
369     }
370 
371     /**
372      * @deprecated since 4.0 - untested and unused
373      */
374     public static String getParentPath(String path) {
375         int lastIndexOfSlash = path.lastIndexOf("/"); //$NON-NLS-1$
376         if (lastIndexOfSlash > 0) {
377             return StringUtils.substringBefore(path, "/"); //$NON-NLS-1$
378         }
379         return "/"; //$NON-NLS-1$
380     }
381 }