/*
* Copyright (C) 2003-2008 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.wcm.connector.fckeditor;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import org.exoplatform.commons.utils.ISO8601;
import org.exoplatform.commons.utils.PageList;
import org.exoplatform.container.PortalContainer;
import org.exoplatform.container.component.RequestLifeCycle;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.portal.config.DataStorage;
import org.exoplatform.portal.config.Query;
import org.exoplatform.portal.config.UserACL;
import org.exoplatform.portal.config.UserPortalConfig;
import org.exoplatform.portal.config.UserPortalConfigService;
import org.exoplatform.portal.config.model.PortalConfig;
import org.exoplatform.portal.mop.page.PageContext;
import org.exoplatform.portal.mop.page.PageKey;
import org.exoplatform.portal.mop.user.UserNavigation;
import org.exoplatform.portal.mop.user.UserNode;
import org.exoplatform.portal.mop.user.UserPortal;
import org.exoplatform.portal.mop.user.UserPortalContext;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.rest.resource.ResourceContainer;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.wcm.navigation.NavigationUtils;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* Returns a page URI for a given location.
*
* @LevelAPI Provisional
*
* @anchor PortalLinkConnector
*/
@Path("/portalLinks/")
public class PortalLinkConnector implements ResourceContainer {
/** The RESOURC e_ type. */
final private String RESOURCE_TYPE = "PortalPageURI";
/** The portal data storage. */
private DataStorage portalDataStorage;
/** The portal user acl. */
private UserACL portalUserACL;
/** The servlet context. */
private ServletContext servletContext;
/** The log. */
private static final Log LOG = ExoLogger.getLogger(PortalLinkConnector.class.getName());
/** The Constant LAST_MODIFIED_PROPERTY. */
private static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
/** The Constant IF_MODIFIED_SINCE_DATE_FORMAT. */
private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
/**
* Instantiates a new portal link connector.
*
* @param params The params.
* @param dataStorage The data storage.
* @param userACL The user ACL.
* @param servletContext The servlet context.
*
* @throws Exception the exception
*/
public PortalLinkConnector(InitParams params,
DataStorage dataStorage,
UserACL userACL,
ServletContext servletContext) throws Exception {
this.portalDataStorage = dataStorage;
this.portalUserACL = userACL;
this.servletContext = servletContext;
}
/**
* Gets the page URI.
*
* @param currentFolder The current folder.
* @param command The command to get folders/files.
* @param type The file type.
* @return The page URI.
* @throws Exception The exception
*
* @anchor PortalLinkConnector.getFoldersAndFiles
*/
@GET
@Path("/getFoldersAndFiles/")
// @OutputTransformer(XMLOutputTransformer.class)
public Response getPageURI(@QueryParam("currentFolder") String currentFolder,
@QueryParam("command") String command,
@QueryParam("type") String type) throws Exception {
try {
String userId = getCurrentUser();
return buildReponse(currentFolder, command, userId);
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error when perform getPageURI: ", e);
}
}
DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
}
/**
* Gets the current user.
*
* @return The current user
*/
private String getCurrentUser() {
try {
ConversationState conversationState = ConversationState.getCurrent();
return conversationState.getIdentity().getUserId();
} catch (Exception e) {
if (LOG.isErrorEnabled()) {
LOG.error("Error when perform getCurrentUser: ", e);
}
}
return null;
}
/**
* Builds the response.
*
* @param currentFolder The current folder.
* @param command The command.
* @param userId The user Id
*
* @return the response
*
* @throws Exception the exception
*/
private Response buildReponse(String currentFolder, String command, String userId) throws Exception {
Document document = null;
if (currentFolder == null || "/".equals(currentFolder)) {
document = buildPortalXMLResponse("/", command, userId);
} else {
document = buildNavigationXMLResponse(currentFolder, command, userId);
}
CacheControl cacheControl = new CacheControl();
cacheControl.setNoCache(true);
cacheControl.setNoStore(true);
DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
return Response.ok(new DOMSource(document), MediaType.TEXT_XML)
.cacheControl(cacheControl)
.header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
.build();
}
/**
* Builds the portal xml response.
*
* @param currentFolder The current folder.
* @param command The command.
* @param userId The user Id.
*
* @return The document
*
* @throws Exception the exception
*/
private Document buildPortalXMLResponse(String currentFolder, String command, String userId) throws Exception {
Element rootElement = initRootElement(command, currentFolder);
PortalContainer container = PortalContainer.getInstance();
RequestLifeCycle.begin(container);
Query<PortalConfig> query = new Query<PortalConfig>(null, null, null, null, PortalConfig.class);
PageList pageList = portalDataStorage.find(query, new Comparator<PortalConfig>() {
public int compare(PortalConfig pconfig1, PortalConfig pconfig2) {
return pconfig1.getName().compareTo(pconfig2.getName());
}
});
// should use PermissionManager to check access permission
Element foldersElement = rootElement.getOwnerDocument().createElement("Folders");
rootElement.appendChild(foldersElement);
for (Object object : pageList.getAll()) {
PortalConfig config = (PortalConfig) object;
// if (!portalUserACL.hasPermission(config, userId)) {
if (!portalUserACL.hasPermission(config)) {
continue;
}
Element folderElement = rootElement.getOwnerDocument().createElement("Folder");
folderElement.setAttribute("name", config.getName());
folderElement.setAttribute("url", "");
folderElement.setAttribute("folderType", "");
foldersElement.appendChild(folderElement);
}
RequestLifeCycle.end();
return rootElement.getOwnerDocument();
}
/**
* Builds the navigation xml response.
*
* @param currentFolder The current folder.
* @param command The command.
* @param userId The user Id.
*
* @return The document.
*
* @throws Exception the exception
*/
private Document buildNavigationXMLResponse(String currentFolder, String command, String userId) throws Exception {
PortalContainer container = PortalContainer.getInstance();
RequestLifeCycle.begin(container);
String portalName = currentFolder.substring(1, currentFolder.indexOf('/', 1));
String pageNodeUri = currentFolder.substring(portalName.length() + 1);
// init the return value
Element rootElement = initRootElement(command, currentFolder);
Element foldersElement = rootElement.getOwnerDocument().createElement("Folders");
Element filesElement = rootElement.getOwnerDocument().createElement("Files");
rootElement.appendChild(foldersElement);
rootElement.appendChild(filesElement);
// get navigation data
UserPortalConfigService pConfig = WCMCoreUtils.getService(UserPortalConfigService.class);
UserPortalContext NULL_CONTEXT = new UserPortalContext()
{
public ResourceBundle getBundle(UserNavigation navigation)
{
return null;
}
public Locale getUserLocale()
{
return Locale.ENGLISH;
}
};
UserPortalConfig userPortalCfg = pConfig.getUserPortalConfig(portalName,
userId,
NULL_CONTEXT);
UserPortal userPortal = userPortalCfg.getUserPortal();
UserNavigation navigation = NavigationUtils.getUserNavigationOfPortal(userPortal, portalName);
UserNode userNode = null;
if (pageNodeUri == null) {
RequestLifeCycle.end();
return rootElement.getOwnerDocument();
}
if ("/".equals(pageNodeUri)) {
userNode = userPortal.getNode(navigation, NavigationUtils.ECMS_NAVIGATION_SCOPE, null, null);
} else {
pageNodeUri = pageNodeUri.substring(1, pageNodeUri.length() - 1);
userNode = userPortal.resolvePath(navigation, null, pageNodeUri);
if (userNode != null) {
userPortal.updateNode(userNode, NavigationUtils.ECMS_NAVIGATION_SCOPE, null);
}
}
if (userNode != null) {
// expand root node
Iterator<UserNode> childrenIter = userNode.getChildren().iterator();
while (childrenIter.hasNext()) {
UserNode child = childrenIter.next();
processPageNode(portalName, child, foldersElement, filesElement, userId, pConfig);
}
}
RequestLifeCycle.end();
return rootElement.getOwnerDocument();
}
/**
* Initializes the root element.
*
* @param commandStr The command str.
* @param currentPath The current path.
*
* @return The element.
*
* @throws ParserConfigurationException the parser configuration exception
*/
private Element initRootElement(String commandStr, String currentPath) throws ParserConfigurationException {
Document doc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.newDocument();
Element rootElement = doc.createElement("Connector");
doc.appendChild(rootElement);
rootElement.setAttribute("command", commandStr);
rootElement.setAttribute("resourceType", RESOURCE_TYPE);
Element myEl = doc.createElement("CurrentFolder");
myEl.setAttribute("path", currentPath);
myEl.setAttribute("url", "");
rootElement.appendChild(myEl);
return rootElement;
}
/**
* Processes page nodes.
*
* @param portalName The portal name.
* @param userNode The user node.
* @param foldersElement The root element.
* @param filesElement
* @param userId The user Id.
* @param portalConfigService The portal config service.
*
* @throws Exception the exception
*/
private void processPageNode(String portalName,
UserNode userNode,
Element foldersElement,
Element filesElement,
String userId,
UserPortalConfigService portalConfigService) throws Exception {
PageKey pageRef = userNode.getPageRef();
PageContext page = portalConfigService.getPage(pageRef);
String pageUri = "";
if (page == null) {
pageUri = "/";
Element folderElement = foldersElement.getOwnerDocument().createElement("Folder");
folderElement.setAttribute("name", userNode.getName());
folderElement.setAttribute("folderType", "");
folderElement.setAttribute("url", pageUri);
foldersElement.appendChild(folderElement);
} else {
pageUri = "/" + servletContext.getServletContextName() + "/" + portalName + "/" + userNode.getURI();
Element folderElement = foldersElement.getOwnerDocument().createElement("Folder");
folderElement.setAttribute("name", userNode.getName());
folderElement.setAttribute("folderType", "");
folderElement.setAttribute("url", pageUri);
foldersElement.appendChild(folderElement);
SimpleDateFormat formatter = new SimpleDateFormat(ISO8601.SIMPLE_DATETIME_FORMAT);
String datetime = formatter.format(new Date());
Element fileElement = filesElement.getOwnerDocument().createElement("File");
fileElement.setAttribute("name", userNode.getName());
fileElement.setAttribute("dateCreated", datetime);
fileElement.setAttribute("fileType", "page node");
fileElement.setAttribute("url", pageUri);
fileElement.setAttribute("size", "");
filesElement.appendChild(fileElement);
}
}
}