/* * Copyright (C) 2003-2009 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.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.Random; import java.util.ResourceBundle; 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.transform.dom.DOMSource; import org.apache.commons.io.IOUtils; import org.exoplatform.application.gadget.Gadget; import org.exoplatform.application.gadget.GadgetRegistryService; import org.exoplatform.application.registry.Application; import org.exoplatform.application.registry.ApplicationCategory; import org.exoplatform.application.registry.ApplicationRegistryService; import org.exoplatform.container.PortalContainer; import org.exoplatform.container.component.RequestLifeCycle; import org.exoplatform.container.xml.InitParams; import org.exoplatform.portal.config.model.ApplicationType; import org.exoplatform.portal.gadget.core.ExoDefaultSecurityTokenGenerator; 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.utils.WCMCoreUtils; import org.json.JSONObject; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Instantiates a new gadget connector. * * @LevelAPI Provisional * * @anchor GadgetConnector */ @Path("/wcmGadget/") public class GadgetConnector extends ExoDefaultSecurityTokenGenerator implements ResourceContainer { /** The Constant FCK_RESOURCE_BUNDLE_FILE. */ public static final String FCK_RESOURCE_BUNDLE_FILE = "locale.services.fckeditor.FCKConnector"; /** The application registry service. */ private ApplicationRegistryService applicationRegistryService; /** The gadget registry service. */ private GadgetRegistryService gadgetRegistryService; /** 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"; /** The log. */ private static final Log LOG = ExoLogger.getLogger(GadgetConnector.class.getName()); /** * Instantiates a new gadget connector. * * @param initParams the init params. */ public GadgetConnector(InitParams initParams) throws Exception { applicationRegistryService = WCMCoreUtils.getService(ApplicationRegistryService.class); gadgetRegistryService = WCMCoreUtils.getService(GadgetRegistryService.class); } /** * Gets folders and files. * * @param currentFolder The current folder. * @param lang The language. * @param host The server address on which the gadget is deployed. * @return The folders and files. * @throws Exception The exception * * @anchor GadgetConnector.getFoldersAndFiles */ @GET @Path("/getFoldersAndFiles/") public Response getFoldersAndFiles(@QueryParam("currentFolder") String currentFolder, @QueryParam("lang") String lang, @QueryParam("host") String host) throws Exception { try { Response response = buildXMLResponse(currentFolder, lang, host); if (response != null) return response; } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("Error when perform getFoldersAndFiles: ", e); } } DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT); return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build(); } /** * Builds the XML response. * * @param currentFolder The current folder. * @param language The language. * @param host The server address on which the gadget is deployed. * * @return the response * * @throws Exception the exception */ public Response buildXMLResponse(String currentFolder, String language, String host) throws Exception { List<ApplicationCategory> applicationCategories = getGadgetCategories(); Element rootElement = createRootElement(currentFolder, applicationCategories, language, host); Document document = rootElement.getOwnerDocument(); 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(); } /** * Creates the root element. * * @param currentFolder The current folder. * @param applicationCategories The application categories. * @param language The language. * * @return The element * * @throws Exception the exception */ private Element createRootElement(String currentFolder, List<ApplicationCategory> applicationCategories, String language, String host) throws Exception { Document document = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); document = builder.newDocument(); if (applicationCategories.isEmpty()) { Locale locale = null; if (language == null) { locale = Locale.ENGLISH; } else { locale = new Locale(language); } ResourceBundle resourceBundle = ResourceBundle.getBundle(FCK_RESOURCE_BUNDLE_FILE, locale); String message = ""; try { message = resourceBundle.getString("fckeditor.no-gadget"); } catch (MissingResourceException e) { message = "fckeditor.no-gadget"; } Element rootElement = document.createElement("Message"); document.appendChild(rootElement); rootElement.setAttribute("number", "555"); rootElement.setAttribute("text", message); rootElement.setAttribute("type", "Error"); return rootElement; } Element rootElement = document.createElement("Connector"); document.appendChild(rootElement); rootElement.setAttribute("resourceType", "Gadget"); Element currentFolderElement = document.createElement("CurrentFolder"); if (currentFolder == null || currentFolder.equals("/")){ currentFolderElement.setAttribute("name", applicationCategories.get(0).getName()); Element foldersElement = createFolderElement(document, applicationCategories); rootElement.appendChild(foldersElement); } else { PortalContainer container = PortalContainer.getInstance(); RequestLifeCycle.begin(container); try { ApplicationCategory applicationCategory = applicationRegistryService .getApplicationCategory(currentFolder.substring(1, currentFolder.length() - 1)); currentFolderElement.setAttribute("name", applicationCategory.getDisplayName()); Element filesElement = createFileElement(document, applicationCategory, host); rootElement.appendChild(filesElement); } finally { RequestLifeCycle.end(); } } rootElement.appendChild(currentFolderElement); return rootElement; } /** * Creates the folder element. * * @param document The document. * @param applicationCategories The application categories. * * @return The element * * @throws Exception the exception */ private Element createFolderElement(Document document, List<ApplicationCategory> applicationCategories) throws Exception { Element folders = document.createElement("Folders"); for (ApplicationCategory applicationCategory : applicationCategories) { Element folder = document.createElement("Folder"); folder.setAttribute("name", applicationCategory.getDisplayName()); folders.appendChild(folder); } return folders; } /** * Creates the file element. * * @param document The document. * @param applicationCategory The application category. * * @return the element * * @throws Exception the exception */ private Element createFileElement(Document document, ApplicationCategory applicationCategory, String host) throws Exception { Element files = document.createElement("Files"); List<Application> listApplication = applicationRegistryService.getApplications(applicationCategory, ApplicationType.GADGET); for (Application application : listApplication) { Gadget gadget = gadgetRegistryService.getGadget(application.getApplicationName()); Element file = document.createElement("File"); file.setAttribute("name", gadget.getName()); file.setAttribute("fileType", "nt_unstructured"); file.setAttribute("size", "0"); file.setAttribute("thumbnail", gadget.getThumbnail()); file.setAttribute("description", gadget.getDescription()); String fullurl = ""; if (gadget.isLocal()) { fullurl = "/" + PortalContainer.getCurrentRestContextName() + "/" + gadget.getUrl(); } else { fullurl = gadget.getUrl(); } file.setAttribute("url", fullurl); String data = "{\"context\":{\"country\":\"US\",\"language\":\"en\"},\"gadgets\":[{\"moduleId\":0,\"url\":\"" + fullurl + "\",\"prefs\":[]}]}"; URL url = new URL(host + "/eXoGadgetServer/gadgets/metadata"); URLConnection conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write(data); wr.flush(); String strMetadata = IOUtils.toString(conn.getInputStream(), "UTF-8"); wr.close(); JSONObject metadata = new JSONObject(strMetadata.toString()); ConversationState conversationState = ConversationState.getCurrent(); String userId = conversationState.getIdentity().getUserId(); String token = createToken(gadget.getUrl(), userId, userId, new Random().nextLong(), "default"); JSONObject obj = metadata.getJSONArray("gadgets").getJSONObject(0); obj.put("secureToken", token); file.setAttribute("metadata", metadata.toString()); files.appendChild(file); } return files; } /** * Gets the gadget categories. * * @return The gadget categories. * * @throws Exception the exception */ private List<ApplicationCategory> getGadgetCategories() throws Exception { List<ApplicationCategory> gadgetCategories = new ArrayList<ApplicationCategory>(); PortalContainer container = PortalContainer.getInstance(); RequestLifeCycle.begin(container); try { List<ApplicationCategory> applicationCategories = applicationRegistryService.getApplicationCategories(); for (ApplicationCategory applicationCategory : applicationCategories) { if (!applicationRegistryService.getApplications(applicationCategory, ApplicationType.GADGET) .isEmpty()) { gadgetCategories.add(applicationCategory); } } } finally { RequestLifeCycle.end(); } return gadgetCategories; } }