/*
* 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;
}
}