View Javadoc
1   /*
2    * Copyright (C) 2003-2009 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.services.cms.link;
18  
19  import javax.jcr.Node;
20  import javax.jcr.RepositoryException;
21  import javax.jcr.Session;
22  
23  import org.exoplatform.container.ExoContainer;
24  import org.exoplatform.container.ExoContainerContext;
25  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
26  
27  /**
28   * Created by The eXo Platform SAS
29   * Author : eXoPlatform
30   *          nicolas.filotto@exoplatform.com
31   * 1 avr. 2009
32   */
33  public final class LinkUtils {
34  
35    /**
36     * Convert a path of type /my/../folder or /my/./folder to a real path
37     * @param path the path to convert
38     * @return the real absolute path
39     */
40  
41    public static String evaluatePath(String path) {
42      if (!path.startsWith("/")) {
43        throw new IllegalArgumentException("The path '" + path +  "' must be an absolute path");
44      }
45      path = cleanPath(path);
46      int index;
47      while ((index = path.indexOf("/..")) != -1) {
48        if (index == 0) {
49          path = path.substring(3);
50        } else {
51          path = createPath(getParentPath(path.substring(0, index)), path.substring(index + 3));
52          if (!path.endsWith("/")) path = path.concat("/");
53        }
54      }
55      // Avoid for file with name starts with a dot
56      while ((index = path.indexOf("/./")) != -1) {
57        if (index == 0) {
58          path = path.substring(2);
59        } else {
60          path = createPath(path.substring(0, index), path.substring(index + 2));
61        }
62      }
63      path = cleanPath(path);
64      return path.length() == 0 ? "/" : path;
65    }
66  
67    /**
68     * Gives the name of the item according to the given absolute path
69     * @param path the absolute of the item
70     * @return the item name
71     */
72    public static String getItemName(String path) {
73      if (!path.startsWith("/")) {
74        throw new IllegalArgumentException("The path '" + path +  "' must be an absolute path");
75      }
76      path = cleanPath(path);
77      int index = path.lastIndexOf('/');
78      return path.substring(index + 1);
79    }
80  
81    /**
82     * Appends the parentPath and the relativePath to give a full absolute path
83     */
84    public static String createPath(String parentPath, String relativePath) {
85      if (!parentPath.startsWith("/")) {
86        throw new IllegalArgumentException("The path '" + parentPath +  "' must be an absolute path");
87      }
88      parentPath = cleanPath(parentPath);
89      relativePath = cleanPath(relativePath);
90      if (relativePath.startsWith("/")) {
91        relativePath = relativePath.substring(1);
92      }
93      StringBuilder path = new StringBuilder(128);
94      path.append(parentPath);
95      if (relativePath.length() > 0) {
96        if (!parentPath.equals("/")) {
97          path.append('/');
98        }
99        path.append(relativePath);
100     }
101     return path.toString();
102   }
103 
104   /**
105    * Gives the total depth of the given absolute path
106    * @param path an absolute path
107    * @return the depth of the path
108    */
109   public static int getDepth(String path) {
110     if (!path.startsWith("/")) {
111       throw new IllegalArgumentException("The path '" + path +  "' must be an absolute path");
112     }
113     path = cleanPath(path);
114     if (path.equals("/")) {
115       return 0;
116     }
117     return path.substring(1).split("/").length;
118   }
119 
120   /**
121    * Gives the ancestor of the given path corresponding to the given depth knowing that:
122    * <ul>
123    * <li><i>depth</i> = 0 returns the root node.
124    * <li><i>depth</i> = 1 returns the child of the root node along the path
125    * to <i>this</i> <code>Item</code>.
126    * <li><i>depth</i> = 2 returns the grandchild of the root node along the
127    * path to <i>this</i> <code>Item</code>.
128    * <li>And so on to <i>depth</i> = <i>n</i>, where <i>n</i> is the depth
129    * of <i>this</i> <code>Item</code>, which returns <i>this</i>
130    * <code>Item</code> itself.
131    * </ul>
132    */
133   public static String getAncestorPath(String path, int depth) {
134     if (!path.startsWith("/")) {
135       throw new IllegalArgumentException("The path '" + path +  "' must be an absolute path");
136     }
137     path = cleanPath(path);
138     if (depth == 0) {
139       return "/";
140     }
141     String[] subpath = path.substring(1).split("/");
142     StringBuilder result = new StringBuilder(128);
143     for (int i = 0; i < depth; i++) {
144       result.append('/');
145       result.append(subpath[i]);
146     }
147     return result.toString();
148   }
149 
150   /**
151    * Gives the parent path of the given path
152    * @param path an absolute path
153    * @return the parent path
154    */
155   public static String getParentPath(String path) {
156     if (!path.startsWith("/")) {
157       throw new IllegalArgumentException("The path '" + path +  "' must be an absolute path");
158     }
159     path = cleanPath(path);
160     if (path.equals("/")) {
161       return "/";
162     }
163     int index = path.lastIndexOf('/');
164     if (index == 0) {
165       return "/";
166     }
167     return path.substring(0, index);
168   }
169 
170   public static NodeFinder getNodeFinder() {
171     ExoContainer context = ExoContainerContext.getCurrentContainer();
172     return (NodeFinder) context.getComponentInstance(NodeFinder.class);
173   }
174 
175   public static LinkManager getLinkManager() {
176     return WCMCoreUtils.getService(LinkManager.class);
177   }
178 
179   /**
180    * The procedure which return the path existed in tree.
181    *
182    * @param node is a Node type which represents current node.
183    * @param path a current path
184    * @return the path existed in tree
185    * @throws RepositoryException when some exceptions occurrence.
186    */
187   public static String getExistPath(Node node, String path) throws RepositoryException {
188 
189     // The following process is added by lampt.
190     int deep = getDepth(path);
191 
192     // In case of path is root path.
193     if (deep == 0) {
194       path = LinkUtils.getAncestorPath(path, 0);
195     } else {
196       Session session = node.getSession();
197       for (int i = deep; i > 0; i-- ) {
198         if (session.itemExists(path))
199           break;
200         path = getParentPath(path);
201       }
202     }
203     return path;
204   }
205 
206   private static String cleanPath(String path) {
207 
208     // Remove unnecessary '/'
209     path = path.replaceAll("/+", "/");
210     // Avoid for file with name starts with a dot
211     if ((!(path.contains("/./"))) && path.length() > 1 && path.charAt(path.length() - 1) == '/') {
212       path = path.substring(0, path.length() - 1);
213     }
214     return path;
215   }
216 
217 }