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   **************************************************************************/
18  package org.exoplatform.services.cms.link.impl;
19  
20  import javax.jcr.Item;
21  import javax.jcr.Node;
22  import javax.jcr.PathNotFoundException;
23  import javax.jcr.RepositoryException;
24  import javax.jcr.Session;
25  
26  import org.exoplatform.services.cms.link.LinkManager;
27  import org.exoplatform.services.cms.link.NodeFinder;
28  import org.exoplatform.services.jcr.RepositoryService;
29  import org.exoplatform.services.jcr.core.ManageableRepository;
30  import org.exoplatform.services.jcr.ext.app.SessionProviderService;
31  import org.exoplatform.services.jcr.util.Text;
32  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
33  
34  /**
35   * Created by The eXo Platform SARL Author : Hoang Van Hung hunghvit@gmail.com
36   * Mar 14, 2009
37   */
38  public class NodeFinderImpl implements NodeFinder {
39  
40    private final RepositoryService repositoryService_;
41  
42    private final LinkManager linkManager_;
43  
44    public NodeFinderImpl(RepositoryService repositoryService, LinkManager linkManager){
45      this.repositoryService_ = repositoryService;
46      this.linkManager_ = linkManager;
47    }
48  
49    /**
50     * {@inheritDoc}
51     */
52    public Item getItem(String workspace, String absPath, boolean giveTarget) throws PathNotFoundException,
53                                                                             RepositoryException {
54      return getItemGiveTargetSys(workspace, absPath, giveTarget, false);
55    }
56  
57    /**
58     * {@inheritDoc}
59     */
60    public Item getItemGiveTargetSys(String workspace,
61                                     String absPath,
62                                     boolean giveTarget,
63                                     boolean system) throws PathNotFoundException,
64                                                    RepositoryException {
65      if (!absPath.startsWith("/"))
66        throw new IllegalArgumentException(absPath + " isn't absolute path");
67      Session session = getSession(repositoryService_.getCurrentRepository(), workspace);
68      return getItemTarget(session, absPath, giveTarget, system);
69    }
70  
71    /**
72     * {@inheritDoc}
73     */
74    public Item getItem(String workspace, String absPath) throws PathNotFoundException,
75                                                         RepositoryException {
76      return getItem(workspace, absPath, false);
77    }
78  
79    /**
80     * {@inheritDoc}
81     */
82    public Item getItemSys(String workspace, String absPath, boolean system) throws PathNotFoundException,
83                                                                                               RepositoryException {
84      return getItemGiveTargetSys(workspace, absPath, false, system);
85    }
86  
87    /**
88     * {@inheritDoc}
89     */
90    public Node getNode(Node ancestorNode, String relativePath, boolean giveTarget) throws PathNotFoundException,
91                                                               RepositoryException {
92      if (relativePath.startsWith("/"))
93        throw new IllegalArgumentException("Invalid relative path: " + relativePath);
94      String absPath = "";
95      if (ancestorNode.getPath().equals("/"))
96        absPath = "/" + relativePath;
97      else
98        absPath = ancestorNode.getPath() + "/" + relativePath;
99      Session session = ancestorNode.getSession();
100     return (Node) getItem(session, absPath, giveTarget);
101   }
102 
103   /**
104    * {@inheritDoc}
105    */
106   public Node getNode(Node ancestorNode, String relativePath) throws PathNotFoundException,
107                                                              RepositoryException {
108     return getNode(ancestorNode, relativePath, false);
109   }
110 
111   /**
112    * {@inheritDoc}
113    */
114   public Item getItem(Session session, String absPath, boolean giveTarget) throws PathNotFoundException,
115                                                                           RepositoryException {
116     return getItem(session, absPath, giveTarget, 0, false);
117   }
118 
119   /**
120    * {@inheritDoc}
121    */
122   public Item getItemTarget(Session session, String absPath, boolean giveTarget, boolean system) throws PathNotFoundException,
123                                                                                                 RepositoryException {
124     return getItem(session, absPath, giveTarget, 0, system);
125   }
126 
127   /**
128    * {@inheritDoc}
129    */
130   public Item getItem(Session session, String absPath) throws PathNotFoundException, RepositoryException {
131     return getItem(session, absPath, false);
132   }
133 
134   /**
135    * {@inheritDoc}
136    */
137   public boolean itemExists(Session session, String absPath) throws RepositoryException {
138     try {
139       return getItem(session, absPath) != null;
140     } catch (PathNotFoundException e) {
141       return false;
142     }
143   }
144 
145   /**
146    * Get item by absolute path
147    * @param session    The user session
148    * @param absPath    The absolute path to node
149    * @param fromIdx    The start index used to find the link
150    * @param giveTarget Indicates if the target must be returned in case the item is a link
151    * @return the item corresponding to the path
152    */
153   public Item getItem(Session session,
154                        String absPath,
155                        boolean giveTarget,
156                        int fromIdx,
157                        boolean system) throws PathNotFoundException, RepositoryException {
158     if(absPath.contains("\\'")) {
159       absPath = absPath.replaceAll("\\\\'", "'");
160     }
161 
162     boolean itemExists = session.itemExists(absPath);
163     if (!itemExists && absPath.contains("%") && session.itemExists(Text.unescapeIllegalJcrChars(absPath))) {
164       absPath = Text.unescapeIllegalJcrChars(absPath);
165       itemExists = session.itemExists(absPath);
166     }
167 
168     if (itemExists) {
169       // The item corresponding to absPath can be found
170       Item item = session.getItem(absPath);
171       if (giveTarget && linkManager_.isLink(item)) {
172         return linkManager_.getTarget((Node) item);
173       }
174       return item;
175     }
176     // The item corresponding to absPath can not be found so we split absPath
177     // and check
178     String[] splitPath = absPath.substring(1).split("/");
179     int low = fromIdx;
180     int high = splitPath.length - 1;
181     int mid = high;
182     while (low <= mid) {
183       mid--;
184       String partPath = makePath(splitPath, mid);
185 
186       if (session.itemExists(partPath)) {
187         // The item can be found
188         Item item = session.getItem(partPath);
189         if (linkManager_.isLink(item)) {
190           // The item is a link
191           Node link = (Node) item;
192           if (linkManager_.isTargetReachable(link, system)) {
193             // The target can be reached
194             Node target = linkManager_.getTarget(link, system);
195             String targetPath = target.getPath();
196             return getItem(target.getSession(),
197                            targetPath + absPath.substring(partPath.length()),
198                            giveTarget,
199                            targetPath.substring(1).split("/").length, system);
200           }
201           // The target cannot be found
202           throw new PathNotFoundException("Can't reach the target of the link: " + link.getPath());
203         }
204       }
205     }
206     throw new PathNotFoundException("Can't find path: " + absPath);
207   }
208 
209   /**
210    * Get session of user in given workspace and repository
211    * @param manageableRepository
212    * @param workspace
213    * @throws RepositoryException
214    */
215   public Session getSession(ManageableRepository manageableRepository, String workspace) throws RepositoryException {
216     SessionProviderService service = WCMCoreUtils.getService(SessionProviderService.class);
217     return service.getSessionProvider(null).getSession(workspace, manageableRepository);
218   }
219 
220   /**
221    * Make sub path of absolute path from 0 to toIdx index
222    *
223    * @param splitString
224    * @param toIdx
225    */
226   public String makePath(String[] splitString, int toIdx) {
227     StringBuilder buffer = new StringBuilder(1024);
228     for(int i = 0; i <= toIdx; i++) {
229       buffer.append('/').append(splitString[i]);
230     }
231     return buffer.toString();
232   }
233 }