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   * @author Sameer Charles
47   * @version 2.0 $Id: Path.java 36178 2010-08-03 16:34:52Z gjoseph $
48   */
49  public final class Path {
50      /**
51       * New unlabeled nodes default name.
52       */
53      private static final String DEFAULT_UNTITLED_NODE_NAME = "untitled";
54  
55      /**
56       * Utility class, don't instantiate.
57       */
58      private Path() {
59          // unused
60      }
61  
62      /**
63       * Gets the cache directory path (cms.cache.startdir) as set with Java options while startup or in web.xml.
64       * @return Cache directory path
65       */
66      public static String getCacheDirectoryPath() {
67          return getCacheDirectory().getAbsolutePath();
68      }
69  
70      public static File getCacheDirectory() {
71          String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_CACHE_STARTDIR);
72          File dir = isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
73          dir.mkdirs();
74          return dir;
75      }
76  
77      /**
78       * Gets the temporary directory path (cms.upload.tmpdir) as set with Java options while startup or in web.xml.
79       * @return Temporary directory path
80       */
81      public static String getTempDirectoryPath() {
82          return getTempDirectory().getAbsolutePath();
83      }
84  
85      public static File getTempDirectory() {
86          String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_UPLOAD_TMPDIR);
87          File dir = isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
88          dir.mkdirs();
89          return dir;
90      }
91  
92      /**
93       * Gets cms.exchange.history file location as set with Java options while startup or in web.xml.
94       * @return exchange history file location
95       */
96      public static String getHistoryFilePath() {
97          return getHistoryFile().getAbsolutePath();
98      }
99  
100     public static File getHistoryFile() {
101         String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_EXCHANGE_HISTORY);
102         return isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
103     }
104 
105     /**
106      * Gets repositories file location as set with Java options while startup or in web.xml.
107      * @return file location
108      */
109     public static String getRepositoriesConfigFilePath() {
110         return getRepositoriesConfigFile().getAbsolutePath();
111     }
112 
113     public static File getRepositoriesConfigFile() {
114         String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_REPOSITORIES_CONFIG);
115         return isAbsolute(path) ? new File(path) : new File(getAppRootDir(), path);
116     }
117 
118     /**
119      * Gets the root directory for the magnolia web application.
120      * @return magnolia root dir
121      */
122     public static File getAppRootDir() {
123         return new File(SystemProperty.getProperty(SystemProperty.MAGNOLIA_APP_ROOTDIR));
124     }
125 
126     // TODO : this should probably be in getAppRootDir()
127     private void checkAppRootDir() throws IOException {
128         String root = null;
129         // Try to get root
130         try {
131             File f = getAppRootDir();
132             if (f.isDirectory()) {
133                 root = f.getAbsolutePath();
134             }
135         }
136         catch (Exception e) {
137             // nothing
138         }
139 
140         if (root == null) {
141             throw new IOException("Invalid magnolia " + SystemProperty.MAGNOLIA_APP_ROOTDIR + " path"); //$NON-NLS-1$ //$NON-NLS-2$
142         }
143     }
144 
145     /**
146      * Gets absolute filesystem path, adds application root if path is not absolute.
147      */
148     public static String getAbsoluteFileSystemPath(String path) {
149         if (isAbsolute(path)) {
150             return path;
151         }
152         // using the file() constructor will allow relative paths in the form ../../apps
153         return new File(getAppRootDir(), path).getAbsolutePath();
154     }
155 
156     public static String getUniqueLabel(HierarchyManager hierarchyManager, String parent, String label) {
157         if (parent.equals("/")) { //$NON-NLS-1$
158             parent = StringUtils.EMPTY;
159         }
160         while (hierarchyManager.isExist(parent + "/" + label)) { //$NON-NLS-1$
161             label = createUniqueName(label);
162         }
163         return label;
164     }
165 
166     public static String getUniqueLabel(Content parent, String label) {
167         try {
168             while (parent.hasContent(label) || parent.hasNodeData(label)) { //$NON-NLS-1$
169                 label = createUniqueName(label);
170             }
171         }
172         catch (RepositoryException e) {
173             label = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
174         }
175         return label;
176     }
177 
178     public static boolean isAbsolute(String path) {
179 
180         if (path == null) {
181             return false;
182         }
183 
184         if (path.startsWith("/") || path.startsWith(File.separator)) { //$NON-NLS-1$
185             return true;
186         }
187 
188         // windows c:
189         if (path.length() >= 3 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') {
190             return true;
191         }
192 
193         return false;
194     }
195 
196     /**
197      * Replace illegal characters based on system property magnolia.ut8.enabled.
198      * @param label label to validate
199      * @return validated label
200      */
201     public static String getValidatedLabel(String label)
202     {
203         String charset = StringUtils.EMPTY;
204         if ((SystemProperty.getBooleanProperty(SystemProperty.MAGNOLIA_UTF8_ENABLED)))
205         {
206             charset = "UTF-8";
207         }
208         return getValidatedLabel(label, charset);
209    
210     }
211 
212     /**
213      * If charset eq to UTF-8 replaces these characters:
214      * jackrabbit not allowed 32: [ ] 91: [[] 93: []] 42: [*] 34: ["] 46: [.] 58 [:] 92: [\] 39 :[']
215      * url not valid 59: [;] 47: [/] 63: [?] 43: [+] 37: [%] 33: [!] 35:[#] 94: [^]
216      *  
217      * else replace illegal characters except [_] [0-9], [A-Z], [a-z], [-], [_]
218      * @param label label to validate
219      * @return validated label
220      */
221     public static String getValidatedLabel(String label, String charset)
222     {
223         StringBuffer s = new StringBuffer(label);
224         StringBuffer newLabel = new StringBuffer();
225 
226         for (int i = 0; i < s.length(); i++)
227         {
228             int charCode = s.charAt(i);
229             if (isCharValid(charCode, charset))
230             {
231                 newLabel.append(s.charAt(i));
232             }
233             else
234             {
235                 newLabel.append("-"); //$NON-NLS-1$
236             }
237         }
238         if (newLabel.length() == 0)
239         {
240             newLabel.append(DEFAULT_UNTITLED_NODE_NAME);
241         }
242         return newLabel.toString();
243     }
244 
245     /**
246      * @param charCode char code
247      * @param charset charset (ex. UTF-8)
248      * @return true if char can be used as a content name
249      */
250     public static boolean isCharValid(int charCode, String charset)
251     {
252         // http://www.ietf.org/rfc/rfc1738.txt
253         // safe = "$" | "-" | "_" | "." | "+"
254         // extra = "!" | "*" | "'" | "(" | ")" | ","
255         // national = "{" | "}" | "|" | "\" | "^" | "~" | "[" | "]" | "`"
256         // punctuation = "<" | ">" | "#" | "%" | <">
257         // reserved = ";" | "/" | "?" | ":" | "@" | "&" | "="
258 
259         if ("UTF-8".equals(charset))
260         {
261             // jackrabbit not allowed 32: [ ] 91: [[] 93: []] 42: [*] 34: ["] 46: [.] 58 [:] 92: [\] 39 :[']
262             // url not valid 59: [;] 47: [/] 63: [?] 43: [+] 37: [%] 33: [!] 35:[#]
263             if (charCode != 32
264                 && charCode != '['
265                 && charCode != ']'
266                 && charCode != '*'
267                 && charCode != '"'
268                 && charCode != '.'
269                 && charCode != ':'
270                 && charCode != 92
271                 && charCode != 39
272                 && charCode != ';'
273                 && charCode != '/'
274                 && charCode != '?'
275                 && charCode != '+'
276                 && charCode != '%'
277                 && charCode != '!'
278                 && charCode != '#'
279                 && charCode != '@'
280                 && charCode != '&'
281                 && charCode != '=')
282             {
283                 return true;
284             }
285         }
286         else
287         {
288             // charCodes: 48-57: [0-9]; 65-90: [A-Z]; 97-122: [a-z]; 45: [-]; 95:[_]
289             if (((charCode >= 48) && (charCode <= 57))
290                 || ((charCode >= 65) && (charCode <= 90))
291                 || ((charCode >= 97) && (charCode <= 122))
292                 || charCode == 45
293                 || charCode == 95)
294             {
295                 return true;
296             }
297 
298         }
299         return false;
300 
301     }
302 
303     private static String createUniqueName(String baseName) {
304         int pos;
305         for (pos = baseName.length() - 1; pos >= 0; pos--) {
306             char c = baseName.charAt(pos);
307             if (c < '0' || c > '9') {
308                 break;
309             }
310         }
311         String base;
312         int cnt;
313         if (pos == -1) {
314             if (baseName.length() > 1) {
315                 pos = baseName.length() - 2;
316             }
317         }
318         if (pos == -1) {
319             base = baseName;
320             cnt = -1;
321         }
322         else {
323             pos++;
324             base = baseName.substring(0, pos);
325             if (pos == baseName.length()) {
326                 cnt = -1;
327             }
328             else {
329                 cnt = new Integer(baseName.substring(pos)).intValue();
330             }
331         }
332         return (base + ++cnt);
333     }
334 
335     public static String getAbsolutePath(String path, String label) {
336         if (StringUtils.isEmpty(path) || (path.equals("/"))) { //$NON-NLS-1$
337             return "/" + label; //$NON-NLS-1$
338         }
339 
340         return path + "/" + label; //$NON-NLS-1$
341     }
342 
343     public static String getAbsolutePath(String path) {
344         if (!path.startsWith("/")) { //$NON-NLS-1$
345             return "/" + path; //$NON-NLS-1$
346         }
347         return path;
348     }
349 
350     /**
351      * @deprecated since 4.0 - untested and unused
352      */
353     public static String getNodePath(String path, String label) {
354         if (StringUtils.isEmpty(path) || (path.equals("/"))) { //$NON-NLS-1$
355             return label;
356         }
357         return getNodePath(path + "/" + label); //$NON-NLS-1$
358     }
359 
360     /**
361      * @deprecated since 4.0 - untested and unused
362      */
363     public static String getNodePath(String path) {
364         if (path.startsWith("/")) { //$NON-NLS-1$
365             return path.replaceFirst("/", StringUtils.EMPTY); //$NON-NLS-1$
366         }
367         return path;
368     }
369 
370     /**
371      * @deprecated since 4.0 - untested and unused
372      */
373     public static String getParentPath(String path) {
374         int lastIndexOfSlash = path.lastIndexOf("/"); //$NON-NLS-1$
375         if (lastIndexOfSlash > 0) {
376             return StringUtils.substringBefore(path, "/"); //$NON-NLS-1$
377         }
378         return "/"; //$NON-NLS-1$
379     }
380 }