/* * Copyright (C) 2003-2017 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.management.portlet; import juzu.Path; import juzu.Response; import juzu.Route; import juzu.SessionScoped; import juzu.View; import juzu.impl.common.JSON; import juzu.impl.request.Request; import juzu.request.RequestParameter; import juzu.template.Template; import org.apache.commons.fileupload.FileItem; import org.exoplatform.commons.juzu.ajax.Ajax; import org.exoplatform.container.PortalContainer; import org.exoplatform.management.service.api.Resource; import org.exoplatform.management.service.api.ResourceCategory; import org.exoplatform.management.service.api.ResourceHandler; import org.exoplatform.management.service.api.StagingService; import org.exoplatform.management.service.api.SynchronizationService; import org.exoplatform.management.service.api.TargetServer; import org.exoplatform.management.service.handler.ResourceHandlerLocator; import org.exoplatform.portal.application.PortalRequestContext; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.security.ConversationState; import org.gatein.management.api.ManagementService; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.inject.Inject; /** * The Class StagingExtensionController. */ @SessionScoped public class StagingExtensionController { /** The log. */ private static Log log = ExoLogger.getLogger(StagingExtensionController.class); /** The Constant OPERATION_IMPORT_PREFIX. */ public static final String OPERATION_IMPORT_PREFIX = "IMPORT"; /** The Constant OPERATION_EXPORT_PREFIX. */ public static final String OPERATION_EXPORT_PREFIX = "EXPORT"; /** The Constant PARAM_PREFIX_OPTION. */ public static final String PARAM_PREFIX_OPTION = "staging-option:"; /** The Constant IMPORT_ZIP_PATH_EXCEPTIONS. */ public static final Map<String, String> IMPORT_ZIP_PATH_EXCEPTIONS = new HashMap<String, String>(); /** The Constant IMPORT_PATH_EXCEPTIONS. */ public static final Map<String, String> IMPORT_PATH_EXCEPTIONS = new HashMap<String, String>(); /** The file to import. */ private FileItem fileToImport; // Don't use inject to not get the merge of all resource bundles /** The bundle. */ // @Inject ResourceBundle bundle; /** The staging service. */ @Inject StagingService stagingService; /** The synchronization service. */ @Inject SynchronizationService synchronizationService; /** The management service. */ @Inject ManagementService managementService; /** The selected resources tmpl. */ @Inject @Path("selectedResources.gtmpl") Template selectedResourcesTmpl; /** The index tmpl. */ @Inject @Path("index.gtmpl") Template indexTmpl; /** The bundle string. */ private String bundleString; /** The Constant resourceCategories. */ private static final List<ResourceCategory> resourceCategories = new ArrayList<ResourceCategory>(); /** The spaces category index. */ private static int SPACES_CATEGORY_INDEX = -1; /** The forum category index. */ private static int FORUM_CATEGORY_INDEX = -1; /** The calendar category index. */ private static int CALENDAR_CATEGORY_INDEX = -1; /** The wiki category index. */ private static int WIKI_CATEGORY_INDEX = -1; /** The count all. */ private static int COUNT_ALL = 0; static { String activatedModules = System.getProperty("exo.staging.portlet.modules", ""); activatedModules = activatedModules == null ? "" : activatedModules.trim(); // ZIP PATH EXCEPTIONS IMPORT_ZIP_PATH_EXCEPTIONS.put("/portal", "/site/portalsites"); IMPORT_ZIP_PATH_EXCEPTIONS.put("/group", "/site/groupsites"); IMPORT_ZIP_PATH_EXCEPTIONS.put("/user", "/site/usersites"); // PATH EXCEPTIONS IMPORT_PATH_EXCEPTIONS.put("/site/portalsites", "/site"); IMPORT_PATH_EXCEPTIONS.put("/site/groupsites", "/site"); IMPORT_PATH_EXCEPTIONS.put("/site/usersites", "/site"); // RESOURCES CATEGORIES if (activatedModules.isEmpty() || activatedModules.contains("/site:activated")) { ResourceCategory sites = new ResourceCategory("staging.sites", "/site"); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SITES_PORTAL_PATH + ":activated")) { sites.getSubResourceCategories().add(new ResourceCategory("staging.portalSites", StagingService.SITES_PORTAL_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SITES_GROUP_PATH + ":activated")) { sites.getSubResourceCategories().add(new ResourceCategory("staging.groupSites", StagingService.SITES_GROUP_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SITES_USER_PATH + ":activated")) { sites.getSubResourceCategories().add(new ResourceCategory("staging.userSites", StagingService.SITES_USER_PATH)); } resourceCategories.add(sites); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SOCIAL_PARENT_PATH + ":activated")) { ResourceCategory social = new ResourceCategory("staging.social", StagingService.SOCIAL_PARENT_PATH); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SOCIAL_SPACE_PATH + ":activated")) { social.getSubResourceCategories().add(new ResourceCategory("staging.spaces", StagingService.SOCIAL_SPACE_PATH)); } resourceCategories.add(social); SPACES_CATEGORY_INDEX = resourceCategories.size() - 1; } if (activatedModules.isEmpty() || activatedModules.contains("/content:activated")) { ResourceCategory contents = new ResourceCategory("staging.contents", "/content"); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.CONTENT_SITES_PATH + ":activated")) { contents.getSubResourceCategories().add(new ResourceCategory("staging.sitesContents", StagingService.CONTENT_SITES_PATH)); } resourceCategories.add(contents); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.FORUMS_PARENT_PATH + ":activated")) { ResourceCategory forums = new ResourceCategory("staging.forums", StagingService.FORUMS_PARENT_PATH); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.PUBLIC_FORUM_PATH + ":activated")) { forums.getSubResourceCategories().add(new ResourceCategory("staging.publicForums", StagingService.PUBLIC_FORUM_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SPACE_FORUM_PATH + ":activated")) { forums.getSubResourceCategories().add(new ResourceCategory("staging.spaceForums", StagingService.SPACE_FORUM_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.FORUM_SETTINGS + ":activated")) { forums.getSubResourceCategories().add(new ResourceCategory("staging.forumSettings", StagingService.FORUM_SETTINGS)); } resourceCategories.add(forums); FORUM_CATEGORY_INDEX = resourceCategories.size() - 1; } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.CALENDARS_PARENT_PATH + ":activated")) { ResourceCategory calendars = new ResourceCategory("staging.calendar", StagingService.CALENDARS_PARENT_PATH); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.GROUP_CALENDAR_PATH + ":activated")) { calendars.getSubResourceCategories().add(new ResourceCategory("staging.groupCalendar", StagingService.GROUP_CALENDAR_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.SPACE_CALENDAR_PATH + ":activated")) { calendars.getSubResourceCategories().add(new ResourceCategory("staging.spaceCalendar", StagingService.SPACE_CALENDAR_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.PERSONAL_FORUM_PATH + ":activated")) { calendars.getSubResourceCategories().add(new ResourceCategory("staging.personalCalendar", StagingService.PERSONAL_FORUM_PATH)); } resourceCategories.add(calendars); CALENDAR_CATEGORY_INDEX = resourceCategories.size() - 1; } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.WIKIS_PARENT_PATH + ":activated")) { ResourceCategory wikis = new ResourceCategory("staging.wikis", StagingService.WIKIS_PARENT_PATH); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.PORTAL_WIKIS_PATH + ":activated")) { wikis.getSubResourceCategories().add(new ResourceCategory("staging.portalWikis", StagingService.PORTAL_WIKIS_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.GROUP_WIKIS_PATH + ":activated")) { wikis.getSubResourceCategories().add(new ResourceCategory("staging.spaceWikis", StagingService.GROUP_WIKIS_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.USER_WIKIS_PATH + ":activated")) { wikis.getSubResourceCategories().add(new ResourceCategory("staging.userWikis", StagingService.USER_WIKIS_PATH)); } resourceCategories.add(wikis); WIKI_CATEGORY_INDEX = resourceCategories.size() - 1; } if (activatedModules.isEmpty() || activatedModules.contains("/organization:activated")) { ResourceCategory organization = new ResourceCategory("staging.organization", "/organization"); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.USERS_PATH + ":activated")) { organization.getSubResourceCategories().add(new ResourceCategory("staging.users", StagingService.USERS_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.GROUPS_PATH + ":activated")) { organization.getSubResourceCategories().add(new ResourceCategory("staging.groups", StagingService.GROUPS_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ROLE_PATH + ":activated")) { organization.getSubResourceCategories().add(new ResourceCategory("staging.roles", StagingService.ROLE_PATH)); } resourceCategories.add(organization); } if (activatedModules.isEmpty() || activatedModules.contains("/application:activated")) { ResourceCategory applications = new ResourceCategory("staging.applications", "/application"); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.REGISTRY_PATH + ":activated")) { applications.getSubResourceCategories().add(new ResourceCategory("staging.applicationRegistry", StagingService.REGISTRY_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.GADGET_PATH + ":activated")) { applications.getSubResourceCategories().add(new ResourceCategory("staging.gadgets", StagingService.GADGET_PATH)); } resourceCategories.add(applications); } if (activatedModules.isEmpty() || activatedModules.contains("/ecmadmin:activated")) { ResourceCategory ecmAdmin = new ResourceCategory("staging.cmsAdmin", "/ecmadmin"); if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_TEMPLATES_APPLICATION_CLV_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.clv", StagingService.ECM_TEMPLATES_APPLICATION_CLV_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_TEMPLATES_DOCUMENT_TYPE_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.docTemplates", StagingService.ECM_TEMPLATES_DOCUMENT_TYPE_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_TEMPLATES_METADATA_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.metadataTemplates", StagingService.ECM_TEMPLATES_METADATA_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_TAXONOMY_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.taxonomies", StagingService.ECM_TAXONOMY_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_QUERY_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.queries", StagingService.ECM_QUERY_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_DRIVE_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.drives", StagingService.ECM_DRIVE_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_SCRIPT_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.scripts", StagingService.ECM_SCRIPT_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_VIEW_TEMPLATES_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.viewTemplate", StagingService.ECM_VIEW_TEMPLATES_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_VIEW_CONFIGURATION_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.viewConfiguration", StagingService.ECM_VIEW_CONFIGURATION_PATH)); } if (activatedModules.isEmpty() || activatedModules.contains(StagingService.ECM_NODETYPE_PATH + ":activated")) { ecmAdmin.getSubResourceCategories().add(new ResourceCategory("staging.nodetypes", StagingService.ECM_NODETYPE_PATH)); } resourceCategories.add(ecmAdmin); } COUNT_ALL = resourceCategories.size(); } /** * Index. * * @return the response. content */ @View public Response.Content index() { if (resourceCategories.size() == COUNT_ALL) { if (!isWikiActivated() && WIKI_CATEGORY_INDEX > 0) { resourceCategories.remove(WIKI_CATEGORY_INDEX); } if (!isCalendarActivated() && CALENDAR_CATEGORY_INDEX > 0) { resourceCategories.remove(CALENDAR_CATEGORY_INDEX); } if (!isForumActivated() && FORUM_CATEGORY_INDEX > 0) { resourceCategories.remove(FORUM_CATEGORY_INDEX); } if (!isSocialActivated() && SPACES_CATEGORY_INDEX > 0) { resourceCategories.remove(SPACES_CATEGORY_INDEX); } } return indexTmpl.ok(Collections.singletonMap("isAdmin", isUserAdmin())); } /** * Gets the categories. * * @return the categories */ @Ajax @juzu.Resource public Response getCategories() { try { StringBuilder jsonCategories = new StringBuilder(50); jsonCategories.append("{\"categories\":["); for (ResourceCategory category : resourceCategories) { jsonCategories.append("{\"path\":\"").append(category.getPath()).append("\",\"label\":\"").append(getResourceBundle().getString(category.getLabel())).append("\",\"subcategories\":["); for (ResourceCategory subcategory : category.getSubResourceCategories()) { jsonCategories.append("{\"path\":\"").append(subcategory.getPath()).append("\",\"label\":\"").append(getResourceBundle().getString(subcategory.getLabel())).append("\"},"); } if (!category.getSubResourceCategories().isEmpty()) { jsonCategories.deleteCharAt(jsonCategories.length() - 1); } jsonCategories.append("]},"); } if (!resourceCategories.isEmpty()) { jsonCategories.deleteCharAt(jsonCategories.length() - 1); } jsonCategories.append("]}"); return Response.ok(jsonCategories.toString()); } catch (Throwable e) { log.error("error while getting categories", e); return Response.status(500).content(getResourceBundle().getString("staging.error")); } } /** * Gets the bundle. * * @return the bundle */ @Ajax @juzu.Resource @juzu.MimeType.JSON public Response getBundle() { try { if (bundleString != null && getResourceBundle().getLocale().equals(PortalRequestContext.getCurrentInstance().getLocale())) { return Response.ok(bundleString); } bundle = getResourceBundle(PortalRequestContext.getCurrentInstance().getLocale()); JSON data = new JSON(); Enumeration<String> enumeration = getResourceBundle().getKeys(); while (enumeration.hasMoreElements()) { String key = (String) enumeration.nextElement(); if (key.startsWith("staging.")) { try { data.set(key.replace("staging.", ""), getResourceBundle().getObject(key)); } catch(MissingResourceException e) { // Nothing to do, this happens sometimes } } } bundleString = data.toString(); return Response.ok(bundleString); } catch (Throwable e) { log.error("error while getting categories", e); return Response.status(500).content(getResourceBundle().getString("staging.error")); } } /** * Gets the resources of category. * * @param path the path * @return the resources of category */ @Ajax @juzu.Resource public Response getResourcesOfCategory(String path) { try { Set<Resource> resources = stagingService.getResources(path); StringBuilder jsonResources = new StringBuilder(50); jsonResources.append("{\"resources\":["); for (Resource resource : resources) { jsonResources.append("{\"path\":\"").append(resource.getPath()).append("\",\"description\":\"").append(resource.getDescription()).append("\",\"text\":\"").append(resource.getText()).append("\"},"); } if (!resources.isEmpty()) { jsonResources.deleteCharAt(jsonResources.length() - 1); } jsonResources.append("]}"); return Response.ok(jsonResources.toString()); } catch (Throwable e) { log.error(e); return Response.content(500, getResourceBundle().getString("staging.error")); } } /** * Prepare import resources. * * @param file the file * @return the response. content * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response.Content prepareImportResources(FileItem file) throws IOException { try { if (file == null || file.getSize() == 0) { return Response.content(500, getResourceBundle().getString("staging.emptyFile")); } ZipInputStream zipInputStream = new ZipInputStream(file.getInputStream()); Set<String> foundResources = new HashSet<String>(); try { ZipEntry entry = zipInputStream.getNextEntry(); while (entry != null) { String fileName = entry.getName(); if (entry.isDirectory()) { entry = zipInputStream.getNextEntry(); continue; } fileName = fileName.startsWith("/") ? "" : "/" + fileName; String resourcePath = transformSpecialPath(fileName); // If resource path transformed and treated with Exceptions Resource // Paths if (!resourcePath.equals(fileName)) { // Got it ! foundResources.add(resourcePath); // Manage only one resource at a time for the moment } else if (!parentAlreadyAddedInList(foundResources, resourcePath)) { ResourceHandler resourceHandler = ResourceHandlerLocator.findResourceByPath(resourcePath); foundResources.add(resourceHandler.getPath()); } entry = zipInputStream.getNextEntry(); } fileToImport = file; log.info("Found resources zip file : {}", foundResources); } finally { zipInputStream.close(); } if (!foundResources.isEmpty()) { return Response.ok(toString(foundResources)); } else { return Response.content(500, getResourceBundle().getString("staging.invalidArchive")); } } catch (Throwable e) { log.error(e); return Response.content(500, getResourceBundle().getString("staging.error")); } } /** * Backup. * * @param backupDirectory the backup directory * @param exportJCR the export JCR * @param exportIDM the export IDM * @param writeStrategy the write strategy * @param displayMessageFor the display message for * @param message the message * @return the response * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response backup(String backupDirectory, String exportJCR, String exportIDM, String writeStrategy, String displayMessageFor, String message) throws IOException { try { if (!isUserAdmin()) { log.warn("User '" + getCurrentUser() + "' is not authorized to backup the system."); return Response.content(403, getResourceBundle().getString("staging.unauthorizedUser")); } ResourceCategory category = new ResourceCategory("/backup"); String resourcePath = "/backup/" + PortalContainer.getCurrentPortalContainerName(); category.getResources().add(new Resource(resourcePath, resourcePath, "")); category.getExportOptions().put("directory", backupDirectory); category.getExportOptions().put("export-jcr", exportJCR); category.getExportOptions().put("export-idm", exportIDM); category.getExportOptions().put("writeStrategy", writeStrategy); category.getExportOptions().put("displayMessageFor", displayMessageFor); category.getExportOptions().put("message", message); List<ResourceCategory> resourceCategories = Collections.singletonList(category); stagingService.export(resourceCategories); return Response.ok(getResourceBundle().getString("staging.backupSuccess")); } catch (Throwable e) { log.error("Error occured while backup: ", e); return Response.content(500, getResourceBundle().getString("staging.error")); } } /** * Restore. * * @param backupDirectory the backup directory * @return the response * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response restore(String backupDirectory) throws IOException { try { if (!isUserAdmin()) { log.warn("User '" + getCurrentUser() + "' is not authorized to restore the system."); return Response.content(403, "User is not authorized to restore the system."); } Map<String, List<String>> attributes = new HashMap<String, List<String>>(); attributes.put("directory", Collections.singletonList(backupDirectory)); stagingService.importResource("/backup/portal", null, attributes); return Response.ok(getResourceBundle().getString("staging.restoreSuccess")); } catch (Throwable e) { log.error("Error occured while restoring databases", e); return Response.content(500, getResourceBundle().getString("staging.error")); } } /** * Export. * * @param resourceCategories the resource categories * @param resources the resources * @param options the options * @return the response. content * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response.Content export(String[] resourceCategories, String[] resources, String[] options) throws IOException { try { // Create selected resources categories List<ResourceCategory> selectedResourceCategories = new ArrayList<ResourceCategory>(); for (String selectedResourcesCategory : resourceCategories) { ResourceCategory resourceCategory = new ResourceCategory(selectedResourcesCategory); selectedResourceCategories.add(resourceCategory); } // Dispatch selected resources in resources categories for (String selectedResource : resources) { for (ResourceCategory resourceCategory : selectedResourceCategories) { if (selectedResource.startsWith(resourceCategory.getPath())) { resourceCategory.getResources().add(new Resource(selectedResource, null, null)); break; } } } // Dispatch selected options in resources categories for (String selectedOption : options) { int indexColon = selectedOption.indexOf(":"); if (indexColon > 0) { String optionName = selectedOption.substring(0, indexColon); String optionValue = selectedOption.substring(indexColon + 1); String optionParts[] = optionName.split("_"); for (ResourceCategory resourceCategory : selectedResourceCategories) { if (optionParts[0].equals(resourceCategory.getPath())) { if (optionParts[1].equals(OPERATION_EXPORT_PREFIX)) { resourceCategory.getExportOptions().put(optionParts[2], optionValue); } else if (optionParts[1].equals(OPERATION_IMPORT_PREFIX)) { resourceCategory.getImportOptions().put(optionParts[2], optionValue); } break; } } } } // Manage paths exceptions (/site/portalsites -> /site) List<ResourceCategory> selectedResourceCategoriesWithExceptions = new ArrayList<ResourceCategory>(); for (ResourceCategory resourceCategory : selectedResourceCategories) { if (IMPORT_PATH_EXCEPTIONS.containsKey(resourceCategory.getPath())) { resourceCategory.setPath(IMPORT_PATH_EXCEPTIONS.get(resourceCategory.getPath())); } selectedResourceCategoriesWithExceptions.add(resourceCategory); } File file = stagingService.export(selectedResourceCategoriesWithExceptions); if (file == null) { return Response.content(500, getResourceBundle().getString("staging.emptyResourceList")); } else { return Response.ok(new FileInputStream(file)).withMimeType("application/zip").withHeader("Set-Cookie", "fileDownload=true; path=/").withHeader("Content-Disposition", "filename=\"StagingExport.zip\""); } } catch (Throwable e) { log.error("Error while exporting resources, ", e); return Response.content(500, getResourceBundle().getString("staging.exportError")); } } /** * Import resources. * * @return the response. content * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response.Content importResources() throws IOException { if (fileToImport == null || fileToImport.getSize() == 0) { return Response.content(500, getResourceBundle().getString("staging.emptyFile")); } Map<String, RequestParameter> parameters = Request.getCurrent().getParameterArguments(); RequestParameter selectedResourcesCategories = parameters.get("staging:resourceCategory"); if (selectedResourcesCategories == null || selectedResourcesCategories.size() == 0) { return Response.content(500, getResourceBundle().getString("staging.emptyResourceList")); } try { List<String> selectedResourcesCategoriesList = new ArrayList<String>(selectedResourcesCategories); Collections.sort(selectedResourcesCategoriesList, new Comparator<String>() { @Override public int compare(String o1, String o2) { return ResourceCategory.getOrder(o1) - ResourceCategory.getOrder(o1); } }); for (String selectedResourcesCategory : selectedResourcesCategoriesList) { log.info("inporting resources for : " + selectedResourcesCategory); String exceptionPathCategory = IMPORT_PATH_EXCEPTIONS.get(selectedResourcesCategory); // filter ResourceCategory options coming from request Map<String, List<String>> attributes = new HashMap<String, List<String>>(); for (String param : parameters.keySet()) { if (param.startsWith(PARAM_PREFIX_OPTION)) { String paramPath = param.replace(PARAM_PREFIX_OPTION, ""); if (parameters.get(param) == null || parameters.get(param).size() == 0) { log.error("Can't parse empty parameters for filter: " + paramPath); continue; } String categoryPath = paramPath.substring(0, paramPath.indexOf("_")); if (categoryPath.equals(selectedResourcesCategory) || (exceptionPathCategory != null && categoryPath.equals(exceptionPathCategory))) { String attributeName = paramPath.substring(paramPath.indexOf("_") + 1); if (attributeName.startsWith("filter/")) { if (!attributes.containsKey("filter")) { attributes.put("filter", new ArrayList<String>()); } List<String> values = attributes.get("filter"); if (parameters.get(param).size() > 1) { log.error("Can't parse all parameters for filter: '" + paramPath + "' with values = " + parameters.get(param) + ". Only first parameter will be used: " + parameters.get(param).get(0)); } String value = parameters.get(param).get(0); attributeName = attributeName.replace("filter/", ""); value = attributeName + ":" + value; values.add(value); } else { attributes.put(attributeName, parameters.get(param)); } } } } if (exceptionPathCategory != null) { selectedResourcesCategory = exceptionPathCategory; } stagingService.importResource(selectedResourcesCategory, fileToImport.getInputStream(), attributes); } return Response.ok(getResourceBundle().getString("staging.importSuccess")); } catch (Throwable e) { log.error("Error occured while importing content", e); return Response.content(500, getResourceBundle().getString("staging.importError")); } } /** * Gets the synchonization servers. * * @return the synchonization servers */ @Ajax @juzu.Resource @Route("/servers") public Response getSynchonizationServers() { try { List<TargetServer> synchronizationServers = synchronizationService.getSynchonizationServers(); StringBuilder jsonServers = new StringBuilder(50); jsonServers.append("{\"synchronizationServers\":["); for (TargetServer targetServer : synchronizationServers) { jsonServers.append("{\"id\":\"").append(targetServer.getId()).append("\",\"name\":\"").append(targetServer.getName()).append("\",\"host\":\"").append(targetServer.getHost()).append("\",\"port\":\"").append(targetServer.getPort()).append("\",\"username\":\"").append(targetServer.getUsername()).append("\",\"password\":\"").append(targetServer.getPassword()).append("\",\"ssl\":").append(targetServer.isSsl()).append("},"); } if (!synchronizationServers.isEmpty()) { jsonServers.deleteCharAt(jsonServers.length() - 1); } jsonServers.append("]}"); return Response.ok(jsonServers.toString()); } catch (Throwable e) { log.error("Error while getting target server list", e); return Response.content(500, getResourceBundle().getString("staging.error")); } } /** * Test server connection. * * @param name the name * @param host the host * @param port the port * @param username the username * @param password the password * @param ssl the ssl * @return the response * @throws Exception the exception */ @Ajax @juzu.Resource public Response testServerConnection(String name, String host, String port, String username, String password, String ssl) throws Exception { try { TargetServer targetServer = new TargetServer(name, host, port, username, password, "true".equals(ssl)); synchronizationService.testServerConnection(targetServer); return Response.ok(getResourceBundle().getString("staging.connectionSuccess")); } catch (Throwable e) { if (log.isTraceEnabled()) { log.warn("Test connection error: ", e); } return Response.content(500, getResourceBundle().getString("staging.connectionError")); } } /** * Adds the synchonization server. * * @param name the name * @param host the host * @param port the port * @param username the username * @param password the password * @param ssl the ssl * @return the response */ @Ajax @juzu.Resource public Response addSynchonizationServer(String name, String host, String port, String username, String password, String ssl) { try { TargetServer targetServer = new TargetServer(name, host, port, username, password, "true".equals(ssl)); List<TargetServer> targetServers = synchronizationService.getSynchonizationServers(); if(targetServers.contains(targetServer)) { return Response.content(500, getResourceBundle().getString("staging.serverAlreadyExists")); } synchronizationService.addSynchonizationServer(targetServer); return Response.ok(getResourceBundle().getString("staging.serverCreated")); } catch (Throwable e) { log.error("Error while creating target server", e); return Response.content(500, getResourceBundle().getString("staging.serverCreationError")); } } /** * Removes the synchonization server. * * @param id the id * @return the response */ @Ajax @juzu.Resource public Response removeSynchonizationServer(String id) { try { TargetServer targetServer = new TargetServer(id, null, null, null, null, null, false); synchronizationService.removeSynchonizationServer(targetServer); return Response.ok(getResourceBundle().getString("staging.serverRemoved")); } catch (Throwable e) { log.error("Error while deleting target server", e); return Response.content(500, getResourceBundle().getString("staging.serverRemovalError")); } } /** * Synchronize. * * @param isSSLString the is SSL string * @param host the host * @param port the port * @param username the username * @param password the password * @param resourceCategories the resource categories * @param resources the resources * @param options the options * @return the response * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response synchronize(String isSSLString, String host, String port, String username, String password, String[] resourceCategories, String[] resources, String[] options) throws IOException { TargetServer targetServer = new TargetServer(host, port, username, password, "true".equals(isSSLString)); try { // Create selected resources categories List<ResourceCategory> selectedResourceCategories = new ArrayList<ResourceCategory>(); for (String selectedResourcesCategory : resourceCategories) { ResourceCategory resourceCategory = new ResourceCategory(selectedResourcesCategory); selectedResourceCategories.add(resourceCategory); } // Dispatch selected resources in resources categories for (String selectedResource : resources) { for (ResourceCategory resourceCategory : selectedResourceCategories) { if (selectedResource.startsWith(resourceCategory.getPath())) { resourceCategory.getResources().add(new Resource(selectedResource, null, null)); break; } } } // Dispatch selected options in resources categories for (String selectedOption : options) { int indexColon = selectedOption.indexOf(":"); if (indexColon > 0) { String optionName = selectedOption.substring(0, indexColon); String optionValue = selectedOption.substring(indexColon + 1); String optionParts[] = optionName.split("_"); for (ResourceCategory resourceCategory : selectedResourceCategories) { if (optionParts[0].equals(resourceCategory.getPath())) { if (optionParts[1].equals(OPERATION_EXPORT_PREFIX)) { resourceCategory.getExportOptions().put(optionParts[2], optionValue); } else if (optionParts[1].equals(OPERATION_IMPORT_PREFIX)) { resourceCategory.getImportOptions().put(optionParts[2], optionValue); } break; } } } } // Manage paths exceptions (/site/portalsites -> /site) List<ResourceCategory> selectedResourceCategoriesWithExceptions = new ArrayList<ResourceCategory>(); for (ResourceCategory resourceCategory : selectedResourceCategories) { if (IMPORT_PATH_EXCEPTIONS.containsKey(resourceCategory.getPath())) { resourceCategory.setPath(IMPORT_PATH_EXCEPTIONS.get(resourceCategory.getPath())); } selectedResourceCategoriesWithExceptions.add(resourceCategory); } // Sort categories with order of export/import operation dependency Collections.sort(selectedResourceCategoriesWithExceptions); synchronizationService.synchronize(selectedResourceCategoriesWithExceptions, targetServer); return Response.ok(getResourceBundle().getString("staging.synchronizationSuccess")); } catch (Throwable e) { log.error("Error while synchronizing data to target server: " + targetServer, e); return Response.content(500, getResourceBundle().getString("staging.synchronizationError")); } } /** * Execute SQL. * * @param sql the sql * @param sites the sites * @return the response * @throws IOException Signals that an I/O exception has occurred. */ @Ajax @juzu.Resource public Response executeSQL(String sql, String[] sites) throws IOException { try { StringBuilder builder = new StringBuilder(); if (sites != null && sites.length > 0) { builder.append("Results").append("\r\n"); builder.append("<ul>"); Set<String> resultedNodePaths = stagingService.executeSQL(sql, new HashSet<String>(Arrays.asList(sites))); for (String path : resultedNodePaths) { builder.append("<li>"); builder.append(path); builder.append("</li>"); } builder.append("</ul>"); } return Response.ok(builder.toString()); } catch (Throwable e) { log.error("Error while executing request: " + sql, e); return Response.content(500, getResourceBundle().getString("staging.testSQLError") + ":" + e.getMessage()); } } /** * Gets the resource bundle. * * @param locale the locale * @return the resource bundle */ private ResourceBundle getResourceBundle(Locale locale) { return bundle = ResourceBundle.getBundle("locale.portlet.staging", locale, PortalContainer.getInstance().getPortalClassLoader()); } /** * Gets the resource bundle. * * @return the resource bundle */ private ResourceBundle getResourceBundle() { if(bundle == null) { bundle = ResourceBundle.getBundle("locale.portlet.staging", PortalRequestContext.getCurrentInstance().getLocale(), PortalContainer.getInstance().getPortalClassLoader()); } return bundle; } /** * Checks if is wiki activated. * * @return true, if is wiki activated */ private boolean isWikiActivated() { try { return PortalContainer.getInstance().getComponentInstanceOfType(Class.forName("org.exoplatform.wiki.service.WikiService")) != null; } catch (ClassNotFoundException e) { return false; } } /** * Checks if is calendar activated. * * @return true, if is calendar activated */ private boolean isCalendarActivated() { try { return PortalContainer.getInstance().getComponentInstanceOfType(Class.forName("org.exoplatform.calendar.service.CalendarService")) != null; } catch (ClassNotFoundException e) { return false; } } /** * Checks if is forum activated. * * @return true, if is forum activated */ private boolean isForumActivated() { try { return PortalContainer.getInstance().getComponentInstanceOfType(Class.forName("org.exoplatform.forum.service.ForumService")) != null; } catch (ClassNotFoundException e) { return false; } } /** * Checks if is social activated. * * @return true, if is social activated */ private boolean isSocialActivated() { try { return PortalContainer.getInstance().getComponentInstanceOfType(Class.forName("org.exoplatform.social.core.space.spi.SpaceService")) != null; } catch (ClassNotFoundException e) { return false; } } /** * Parent already added in list. * * @param foundResources the found resources * @param address the address * @return true, if successful */ private boolean parentAlreadyAddedInList(Set<String> foundResources, String address) { for (String path : foundResources) { if (address.startsWith(path)) { return true; } } return false; } /** * To string. * * @param foundResources the found resources * @return the char sequence */ private CharSequence toString(Set<String> foundResources) { StringBuilder result = new StringBuilder(); for (String string : foundResources) { result.append(string + ","); } return result; } /** * Transform special path. * * @param resourcePath the resource path * @return the string */ private String transformSpecialPath(String resourcePath) { Set<String> keys = IMPORT_ZIP_PATH_EXCEPTIONS.keySet(); KEYS: for (String key : keys) { if (resourcePath.startsWith(key)) { resourcePath = IMPORT_ZIP_PATH_EXCEPTIONS.get(key); break KEYS; } } return resourcePath; } /** * Checks if is user admin. * * @return true, if is user admin */ private boolean isUserAdmin() { try { return ConversationState.getCurrent().getIdentity().getRoles().contains("administrators"); } catch (Throwable e) { log.error(e); return false; } } /** * Gets the current user. * * @return the current user */ private String getCurrentUser() { try { return ConversationState.getCurrent().getIdentity().getUserId(); } catch (Throwable e) { log.error(e); return null; } } }