View Javadoc
1   /*
2    * Copyright (C) 2003-2008 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.wcm.connector.fckeditor;
18  
19  import java.text.DateFormat;
20  import java.text.SimpleDateFormat;
21  import java.util.Comparator;
22  import java.util.Date;
23  import java.util.Iterator;
24  import java.util.Locale;
25  import java.util.ResourceBundle;
26  
27  import javax.servlet.ServletContext;
28  import javax.ws.rs.GET;
29  import javax.ws.rs.Path;
30  import javax.ws.rs.QueryParam;
31  import javax.ws.rs.core.CacheControl;
32  import javax.ws.rs.core.MediaType;
33  import javax.ws.rs.core.Response;
34  import javax.xml.parsers.DocumentBuilder;
35  import javax.xml.parsers.DocumentBuilderFactory;
36  import javax.xml.parsers.ParserConfigurationException;
37  import javax.xml.transform.dom.DOMSource;
38  
39  import org.exoplatform.commons.utils.ISO8601;
40  import org.exoplatform.commons.utils.PageList;
41  import org.exoplatform.container.PortalContainer;
42  import org.exoplatform.container.component.RequestLifeCycle;
43  import org.exoplatform.container.xml.InitParams;
44  import org.exoplatform.portal.config.DataStorage;
45  import org.exoplatform.portal.config.Query;
46  import org.exoplatform.portal.config.UserACL;
47  import org.exoplatform.portal.config.UserPortalConfig;
48  import org.exoplatform.portal.config.UserPortalConfigService;
49  import org.exoplatform.portal.config.model.PortalConfig;
50  import org.exoplatform.portal.mop.page.PageContext;
51  import org.exoplatform.portal.mop.page.PageKey;
52  import org.exoplatform.portal.mop.user.UserNavigation;
53  import org.exoplatform.portal.mop.user.UserNode;
54  import org.exoplatform.portal.mop.user.UserPortal;
55  import org.exoplatform.portal.mop.user.UserPortalContext;
56  import org.exoplatform.services.log.ExoLogger;
57  import org.exoplatform.services.log.Log;
58  import org.exoplatform.services.rest.resource.ResourceContainer;
59  import org.exoplatform.services.security.ConversationState;
60  import org.exoplatform.services.wcm.navigation.NavigationUtils;
61  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
62  import org.w3c.dom.Document;
63  import org.w3c.dom.Element;
64  
65  /**
66   * Returns a page URI for a given location.
67   *
68   * @LevelAPI Provisional
69   *
70   * @anchor PortalLinkConnector
71   */
72  @Path("/portalLinks/")
73  public class PortalLinkConnector implements ResourceContainer {
74  
75    /** The RESOURC e_ type. */
76    final private String RESOURCE_TYPE       = "PortalPageURI";
77  
78    /** The portal data storage. */
79    private DataStorage  portalDataStorage;
80  
81    /** The portal user acl. */
82    private UserACL      portalUserACL;
83  
84    /** The servlet context. */
85    private ServletContext servletContext;
86  
87    /** The log. */
88    private static final Log LOG = ExoLogger.getLogger(PortalLinkConnector.class.getName());
89  
90    /** The Constant LAST_MODIFIED_PROPERTY. */
91    private static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
92  
93    /** The Constant IF_MODIFIED_SINCE_DATE_FORMAT. */
94    private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
95  
96    /**
97     * Instantiates a new portal link connector.
98     *
99     * @param params The params.
100    * @param dataStorage The data storage.
101    * @param userACL The user ACL.
102    * @param servletContext The servlet context.
103    *
104    * @throws Exception the exception
105    */
106   public PortalLinkConnector(InitParams params,
107                              DataStorage dataStorage,
108                              UserACL userACL,
109                              ServletContext servletContext) throws Exception {
110     this.portalDataStorage = dataStorage;
111     this.portalUserACL = userACL;
112     this.servletContext = servletContext;
113   }
114 
115   /**
116    * Gets the page URI.
117    *
118    * @param currentFolder The current folder.
119    * @param command The command to get folders/files.
120    * @param type The file type.
121    * @return The page URI.
122    * @throws Exception The exception
123    *
124    * @anchor PortalLinkConnector.getFoldersAndFiles
125    */
126   @GET
127   @Path("/getFoldersAndFiles/")
128 //  @OutputTransformer(XMLOutputTransformer.class)
129   public Response getPageURI(@QueryParam("currentFolder") String currentFolder,
130                              @QueryParam("command") String command,
131                              @QueryParam("type") String type) throws Exception {
132     try {
133       String userId = getCurrentUser();
134       return buildReponse(currentFolder, command, userId);
135     } catch (Exception e) {
136       if (LOG.isErrorEnabled()) {
137         LOG.error("Error when perform getPageURI: ", e);
138       }
139     }
140     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
141     return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
142   }
143 
144   /**
145    * Gets the current user.
146    *
147    * @return The current user
148    */
149   private String getCurrentUser() {
150     try {
151       ConversationState conversationState = ConversationState.getCurrent();
152       return conversationState.getIdentity().getUserId();
153     } catch (Exception e) {
154       if (LOG.isErrorEnabled()) {
155         LOG.error("Error when perform getCurrentUser: ", e);
156       }
157     }
158     return null;
159   }
160 
161   /**
162    * Builds the response.
163    *
164    * @param currentFolder The current folder.
165    * @param command The command.
166    * @param userId The user Id
167    *
168    * @return the response
169    *
170    * @throws Exception the exception
171    */
172   private Response buildReponse(String currentFolder, String command, String userId) throws Exception {
173     Document document = null;
174     if (currentFolder == null || "/".equals(currentFolder)) {
175       document = buildPortalXMLResponse("/", command, userId);
176     } else {
177       document = buildNavigationXMLResponse(currentFolder, command, userId);
178     }
179     CacheControl cacheControl = new CacheControl();
180     cacheControl.setNoCache(true);
181     cacheControl.setNoStore(true);
182     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
183     return Response.ok(new DOMSource(document), MediaType.TEXT_XML)
184                    .cacheControl(cacheControl)
185                    .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
186                    .build();
187   }
188 
189   /**
190    * Builds the portal xml response.
191    *
192    * @param currentFolder The current folder.
193    * @param command The command.
194    * @param userId The user Id.
195    *
196    * @return The document
197    *
198    * @throws Exception the exception
199    */
200   private Document buildPortalXMLResponse(String currentFolder, String command, String userId) throws Exception {
201     Element rootElement = initRootElement(command, currentFolder);
202     PortalContainer container = PortalContainer.getInstance();
203     RequestLifeCycle.begin(container);
204     Query<PortalConfig> query = new Query<PortalConfig>(null, null, null, null, PortalConfig.class);
205     PageList pageList = portalDataStorage.find(query, new Comparator<PortalConfig>() {
206       public int compare(PortalConfig pconfig1, PortalConfig pconfig2) {
207         return pconfig1.getName().compareTo(pconfig2.getName());
208       }
209     });
210     // should use PermissionManager to check access permission
211     Element foldersElement = rootElement.getOwnerDocument().createElement("Folders");
212     rootElement.appendChild(foldersElement);
213     for (Object object : pageList.getAll()) {
214       PortalConfig config = (PortalConfig) object;
215 //      if (!portalUserACL.hasPermission(config, userId)) {
216       if (!portalUserACL.hasPermission(config)) {
217         continue;
218       }
219       Element folderElement = rootElement.getOwnerDocument().createElement("Folder");
220       folderElement.setAttribute("name", config.getName());
221       folderElement.setAttribute("url", "");
222       folderElement.setAttribute("folderType", "");
223       foldersElement.appendChild(folderElement);
224     }
225     RequestLifeCycle.end();
226     return rootElement.getOwnerDocument();
227   }
228 
229   /**
230    * Builds the navigation xml response.
231    *
232    * @param currentFolder The current folder.
233    * @param command The command.
234    * @param userId The user Id.
235    *
236    * @return The document.
237    *
238    * @throws Exception the exception
239    */
240   private Document buildNavigationXMLResponse(String currentFolder, String command, String userId) throws Exception {
241     PortalContainer container = PortalContainer.getInstance();
242     RequestLifeCycle.begin(container);
243     String portalName = currentFolder.substring(1, currentFolder.indexOf('/', 1));
244     String pageNodeUri = currentFolder.substring(portalName.length() + 1);
245 
246     // init the return value
247     Element rootElement = initRootElement(command, currentFolder);
248     Element foldersElement = rootElement.getOwnerDocument().createElement("Folders");
249     Element filesElement = rootElement.getOwnerDocument().createElement("Files");
250     rootElement.appendChild(foldersElement);
251     rootElement.appendChild(filesElement);
252 
253     // get navigation data
254     UserPortalConfigService pConfig = WCMCoreUtils.getService(UserPortalConfigService.class);
255     UserPortalContext NULL_CONTEXT = new UserPortalContext()
256     {
257        public ResourceBundle getBundle(UserNavigation navigation)
258        {
259           return null;
260        }
261        public Locale getUserLocale()
262        {
263           return Locale.ENGLISH;
264        }
265     };
266     UserPortalConfig userPortalCfg = pConfig.getUserPortalConfig(portalName,
267                                                                  userId,
268                                                                  NULL_CONTEXT);
269     UserPortal userPortal = userPortalCfg.getUserPortal();
270     UserNavigation navigation = NavigationUtils.getUserNavigationOfPortal(userPortal, portalName);
271     UserNode userNode = null;
272 
273     if (pageNodeUri == null) {
274       RequestLifeCycle.end();
275       return rootElement.getOwnerDocument();
276     }
277 
278     if ("/".equals(pageNodeUri)) {
279       userNode = userPortal.getNode(navigation, NavigationUtils.ECMS_NAVIGATION_SCOPE, null, null);
280     } else {
281       pageNodeUri = pageNodeUri.substring(1, pageNodeUri.length() - 1);
282       userNode = userPortal.resolvePath(navigation, null, pageNodeUri);
283 
284       if (userNode != null) {
285         userPortal.updateNode(userNode, NavigationUtils.ECMS_NAVIGATION_SCOPE, null);
286       }
287     }
288 
289     if (userNode != null) {
290       // expand root node
291       Iterator<UserNode> childrenIter = userNode.getChildren().iterator();
292       while (childrenIter.hasNext()) {
293         UserNode child = childrenIter.next();
294         processPageNode(portalName, child, foldersElement, filesElement, userId, pConfig);
295       }
296     }
297     RequestLifeCycle.end();
298     return rootElement.getOwnerDocument();
299   }
300 
301   /**
302    * Initializes the root element.
303    *
304    * @param commandStr The command str.
305    * @param currentPath The current path.
306    *
307    * @return The element.
308    *
309    * @throws ParserConfigurationException the parser configuration exception
310    */
311   private Element initRootElement(String commandStr, String currentPath) throws ParserConfigurationException {
312     Document doc = null;
313     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
314     DocumentBuilder builder = factory.newDocumentBuilder();
315     doc = builder.newDocument();
316     Element rootElement = doc.createElement("Connector");
317     doc.appendChild(rootElement);
318     rootElement.setAttribute("command", commandStr);
319     rootElement.setAttribute("resourceType", RESOURCE_TYPE);
320     Element myEl = doc.createElement("CurrentFolder");
321     myEl.setAttribute("path", currentPath);
322     myEl.setAttribute("url", "");
323     rootElement.appendChild(myEl);
324     return rootElement;
325   }
326 
327   /**
328    * Processes page nodes.
329    *
330    * @param portalName The portal name.
331    * @param userNode The user node.
332    * @param foldersElement The root element.
333    * @param filesElement
334    * @param userId The user Id.
335    * @param portalConfigService The portal config service.
336    *
337    * @throws Exception the exception
338    */
339   private void processPageNode(String portalName,
340                                UserNode userNode,
341                                Element foldersElement,
342                                Element filesElement,
343                                String userId,
344                                UserPortalConfigService portalConfigService) throws Exception {
345     PageKey pageRef = userNode.getPageRef();
346     PageContext page = portalConfigService.getPage(pageRef);
347     String pageUri = "";
348     if (page == null) {
349     pageUri = "/";
350     Element folderElement = foldersElement.getOwnerDocument().createElement("Folder");
351       folderElement.setAttribute("name", userNode.getName());
352       folderElement.setAttribute("folderType", "");
353       folderElement.setAttribute("url", pageUri);
354       foldersElement.appendChild(folderElement);
355     } else {
356       pageUri = "/" + servletContext.getServletContextName() + "/" + portalName + "/" + userNode.getURI();
357 
358       Element folderElement = foldersElement.getOwnerDocument().createElement("Folder");
359       folderElement.setAttribute("name", userNode.getName());
360       folderElement.setAttribute("folderType", "");
361       folderElement.setAttribute("url", pageUri);
362       foldersElement.appendChild(folderElement);
363 
364       SimpleDateFormat formatter = new SimpleDateFormat(ISO8601.SIMPLE_DATETIME_FORMAT);
365       String datetime = formatter.format(new Date());
366       Element fileElement = filesElement.getOwnerDocument().createElement("File");
367       fileElement.setAttribute("name", userNode.getName());
368       fileElement.setAttribute("dateCreated", datetime);
369       fileElement.setAttribute("fileType", "page node");
370       fileElement.setAttribute("url", pageUri);
371       fileElement.setAttribute("size", "");
372       filesElement.appendChild(fileElement);
373     }
374   }
375 }