KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > exoplatform > services > jcr > util > PathUtil


1 /*
2  * $Header: /cvsroot/exo/exoplatform/exo-services/jcr-service/api/src/java/exo/services/jcr/util/PathUtil.java,v 1.1 2004/09/16 15:27:38 geaz Exp $
3  * $Revision: 1.1 $
4  * $Date: 2004/09/16 15:27:38 $
5  *
6  * ====================================================================
7  *
8  * The Apache Software License, Version 1.1
9  *
10  * Copyright (c) 1999-2003 The Apache Software Foundation. All rights
11  * reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  *
25  * 3. The end-user documentation included with the redistribution, if
26  * any, must include the following acknowlegement:
27  * "This product includes software developed by the
28  * Apache Software Foundation (http://www.apache.org/)."
29  * Alternately, this acknowlegement may appear in the software itself,
30  * if and wherever such third-party acknowlegements normally appear.
31  *
32  * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
33  * Foundation" must not be used to endorse or promote products derived
34  * from this software without prior written permission. For written
35  * permission, please contact apache@apache.org.
36  *
37  * 5. Products derived from this software may not be called "Apache"
38  * nor may "Apache" appear in their names without prior written
39  * permission of the Apache Group.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  * ====================================================================
54  *
55  * This software consists of voluntary contributions made by many
56  * individuals on behalf of the Apache Software Foundation. For more
57  * information on the Apache Software Foundation, please see
58  * <http://www.apache.org/>.
59  *
60  * [Additional notices, if required by prior licensing conditions]
61  *
62  */

63
64 package org.exoplatform.services.jcr.util;
65
66 import java.util.Iterator JavaDoc;
67 import java.util.LinkedList JavaDoc;
68 import javax.jcr.PathNotFoundException;
69
70 /**
71  * The <code>PathUtil</code> utility class provides
72  * misc. methods to resolve and nornalize JCR-style element paths.
73  *
74  * @author Stefan Guggisberg
75  * @version $Revision: 1.1 $, $Date: 2004/09/16 15:27:38 $
76  */

77 public class PathUtil {
78
79   /**
80    * Builds a canonical path of the specified path.
81    * <p/>
82    * A canonical path is both absolute and unique.
83    * The special path elements "." and ".." are normalized.
84    *
85    * @param absolutePath absolute path which should be resolved as a canonical path
86    * @return a canonical path
87    * @throws MalformedPathException if the specified path is malformed
88    * (e.g. "/../../foo") or if it is not an absolute path.
89    */

90   public static String JavaDoc makeCanonicalPath(String JavaDoc absolutePath)
91       throws PathNotFoundException {
92     if (!absolutePath.startsWith("/")) {
93       throw new PathNotFoundException("'" + absolutePath + "' is not an absolute path");
94     }
95     // check for "." and ".." path elements
96
// (just an optimization, not 100% accurate;
97
// e.g. "/foo/.foo1" would incorrectly pass it)
98
if (absolutePath.indexOf("./") >= 0 || absolutePath.indexOf("/.") >= 0) {
99       LinkedList JavaDoc queue = new LinkedList JavaDoc();
100       int start = 0;
101       while (start >= 0) {
102         int end = absolutePath.indexOf('/', start + 1);
103         String JavaDoc element = absolutePath.substring(start + 1, end == -1 ? absolutePath.length() : end);
104         if (element.equals(".")) {
105           // ignore
106
} else if (element.equals("..")) {
107           if (queue.isEmpty()) {
108             throw new PathNotFoundException("'" + absolutePath + "' is not a valid path");
109           }
110           queue.removeLast();
111         } else {
112           queue.add(element);
113         }
114         start = end;
115       }
116       StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
117       Iterator JavaDoc iter = queue.iterator();
118       while (iter.hasNext()) {
119         buf.append('/');
120         buf.append((String JavaDoc) iter.next());
121       }
122       return buf.toString();
123     } else {
124       return absolutePath;
125     }
126   }
127
128   /**
129    * Builds a canonical path of the specified paths.
130    * <p/>
131    * A canonical path is both absolute and unique.
132    * The special path elements "." and ".." are normalized.
133    * <p/>
134    * If <code>somePath</code> specifies a relative path (i.e. one not
135    * starting with "/") then it is interpreted as being relative to
136    * <code>parentPath</code>; otherwise <code>parentPath</code> is ignored.
137    *
138    * @param parentPath parent path used to resolve a relative path with.
139    * @param somePath either relative or absolute path.
140    * @return a canonical path
141    * @throws MalformedPathException if at least one of the specified paths
142    * is malformed or if the resulting absolute path is malformed (e.g. "/../../foo")
143    */

144   public static String JavaDoc makeCanonicalPath(String JavaDoc parentPath, String JavaDoc somePath)
145       throws PathNotFoundException {
146     // @todo add additonal validations
147
if (somePath.startsWith("/")) {
148       return makeCanonicalPath(somePath);
149     } else {
150       // make absolute path
151
String JavaDoc absPath = (parentPath.equals("/") ? "" : parentPath) + "/" + somePath;
152       return makeCanonicalPath(absPath);
153     }
154   }
155
156   /**
157    * Returns the path to the ancestor of degree <code>degree</code> of the
158    * <code>Element</code> pointed to by <code>descendantPath</code>.
159    *
160    * @param descendantPath absolute path to the descendant of the requested ancestor.
161    * @param degree the degree of the requested ancestor.
162    * @return the path of the ancestor of the specified degree of the
163    * <code>Element</code> pointed to by <code>descendantPath</code>.
164    * @throws MalformedPathException if there is no ancestor of the specified
165    * degree or if the path is malformed (e.g. "/../../foo").
166    */

167   public static String JavaDoc getAncestorPath(String JavaDoc descendantPath, int degree)
168       throws PathNotFoundException {
169     descendantPath = makeCanonicalPath(descendantPath);
170     int pos = descendantPath.length();
171     int cnt = degree;
172     while (cnt-- > 0) {
173       pos = descendantPath.lastIndexOf('/', pos - 1);
174       if (pos < 0) {
175         throw new PathNotFoundException(degree + "nth ancestor of " + descendantPath);
176       }
177     }
178
179     String JavaDoc ancestorPath = descendantPath.substring(0, pos);
180     return ancestorPath.equals("") ? "/" : ancestorPath;
181   }
182
183   /**
184    * Returns the name element (i.e. the last element) of the supplied path.
185    *
186    * @param path the path whise name element should be returned.
187    * @return the name element of the path
188    * @throws MalformedPathException if the path is malformed (e.g. "/../../foo").
189    */

190   public static String JavaDoc getName(String JavaDoc path) throws PathNotFoundException {
191     path = makeCanonicalPath(path);
192
193     int pos = path.lastIndexOf("/");
194     if (pos < 0) {
195       return path;
196     } else if (pos == path.length()) {
197       return "";
198     }
199     return path.substring(pos + 1);
200   }
201
202   public static String JavaDoc rewriteSuffix(String JavaDoc path, String JavaDoc from, String JavaDoc to) throws PathNotFoundException {
203     path = makeCanonicalPath(path);
204
205     int pos = from.length();
206     if (pos == path.length()) {
207       return to;
208     } else {
209       return to + path.substring(pos);
210     }
211
212   }
213
214
215   public static boolean isDescendant(String JavaDoc testPath, String JavaDoc ancestorPath, boolean direct) /*throws PathNotFoundException*/ {
216
217     try {
218
219       int depth = getDepth(makeCanonicalPath(testPath));
220       if(depth == 0)
221          return false;
222
223       if(direct)
224          return getAncestorPath( makeCanonicalPath(testPath),1).equals(makeCanonicalPath(ancestorPath));
225       else {
226          for(int i=1; i<=depth; i++)
227             if(getAncestorPath( makeCanonicalPath(testPath),i).equals(makeCanonicalPath(ancestorPath)))
228                return true;
229       }
230
231     } catch (PathNotFoundException e) {throw new RuntimeException JavaDoc("isDescendanr failed "+e); }
232
233     return false;
234
235 /*
236     if (testPath.length() <= ancestorPath.length())
237       return false;
238     try {
239       if (getDepth(makeCanonicalPath(testPath)) <= getDepth(makeCanonicalPath(ancestorPath)))
240         return false;
241     } catch (Exception e) {
242       return false;
243     }
244
245     if(!testPath.startsWith(ancestorPath))
246       return false;
247
248     int pos = testPath.indexOf(ancestorPath);
249     if (pos == -1)
250       return false;
251
252     String desc = testPath.substring(pos + ancestorPath.length());
253
254 // System.out.println("DESC = "+desc+" "+ancestorPath+" "+desc.substring(0,desc.indexOf("/")));
255
256
257     if (desc.equals("/"))
258       return true;
259
260     if (desc.startsWith("/"))
261       desc = desc.substring(1);
262
263     if (direct && desc.indexOf("/") != -1)
264       return false;
265
266
267     return true;
268 */

269   }
270
271   public static int getDepth(String JavaDoc absolutePath) throws PathNotFoundException {
272     int cnt = 0;
273     String JavaDoc _path = makeCanonicalPath(absolutePath);
274     // Except trailing / - for ex. '/test/'
275
for (int i = 0; i < _path.length() - 1; i++)
276       if (_path.charAt(i) == '/')
277         cnt++;
278     return cnt;
279   }
280
281 }
282
Popular Tags