Projects >> opencms-core >>71b343a67063c8798d5d42ed2fa0f7ddf3f7d976

Chunk
Conflicting content
        // NOOP
    }

    /**
                    }
    }
    /**
    /**
<<<<<<< HEAD
/*
 * File   : $Source$
 * Date   : $Date$
 * Version: $Revision$
 *
 * This library is part of OpenCms -
import org.opencms.file.types.I_CmsResourceType;
 * the Open Source Content Management System
 *
 * Copyright (C) 2002 - 2009 Alkacon Software (http://www.alkacon.com)
 *
 * This library 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 library 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.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.workplace.tools.modules;

import org.opencms.ade.configuration.CmsADEManager;
import org.opencms.configuration.CmsConfigurationCopyResource;
import org.opencms.configuration.Messages;
import org.opencms.db.CmsExportPoint;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.types.A_CmsResourceType;
import org.opencms.file.types.CmsResourceTypeFolder;
import org.opencms.file.types.CmsResourceTypeUnknown;
import org.opencms.file.types.CmsResourceTypeXmlContainerPage;

import org.opencms.i18n.CmsLocaleManager;
import org.opencms.i18n.CmsVfsBundleManager;
import org.opencms.jsp.CmsJspActionElement;
import org.opencms.loader.CmsLoaderException;
import org.opencms.lock.CmsLock;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.module.CmsModule;
import org.opencms.report.CmsLogReport;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.workplace.CmsWorkplace;
import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
import org.opencms.xml.CmsXmlException;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;

import org.apache.commons.logging.Log;

/**
 * Clones a module.

*/ public class CmsCloneModule extends CmsJspActionElement { /** The icon path. */ public static final String ICON_PATH = CmsWorkplace.VFS_PATH_RESOURCES + CmsWorkplace.RES_PATH_FILETYPES; /** Classes folder within the module. */ public static final String PATH_CLASSES = "classes/"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsCloneModule.class); /** The action class used for the clone. */ private String m_actionClass; /** The author's email used for the clone. */ private String m_authorEmail = "sales@alkacon.com"; } /** The author's name used for the clone. */ private String m_authorName = "Alkacon Software GmbH"; /** Option to change the resource types (optional flag). */ private String m_changeResourceTypes; /** If 'true' resource types in all sites will be adjusted. */ private String m_changeResourceTypesEverywhere; /** Option to delete the source module after cloning (optional flag). */ private String m_deleteModule; /** The description used for the clone. */ private String m_description = "This module provides the template layout."; /** A module name where the formatters are located that are referenced within the XSDs of the module to clone. */ private String m_formatterSourceModule = "com.alkacon.bootstrap.formatters"; /** A module name where the formatters are located that should be referenced by the XSDs of the clone. */ private String m_formatterTargetModule; /** The module group used for the clone. */ private String m_group; /** The nice name used for the clone. */ private String m_niceName = "My new template module."; /** The new module name used for the clone. */ private String m_packageName = "my.company.template"; /** The name of the source module to be cloned. */ private String m_sourceModuleName = "com.alkacon.bootstrap.formatters"; /** The prefix that is used by the source module. */ private String m_sourceNamePrefix = "bs"; /** The prefix that is used by the target module. */ private String m_targetNamePrefix = "my"; /** * Public constructor.

*/ public CmsCloneModule() { * Constructor, with parameters.

* * @param context the JSP page context object * @param req the JSP request * @param res the JSP response */ public CmsCloneModule(PageContext context, HttpServletRequest req, HttpServletResponse res) { super(context, req, res); } /** * Bean constructor.

* * @param actionClass action class * @param authorEmail author email * @param authorName author name * @param changeResourceTypes change resource type flags * @param description module description * @param formatterSourceModule formatter source module * @param formatterTargetModule formatter target module * @param group module group * @param niceName nice name * @param packageName package/module name * @param sourceModuleName source module package/name * @param sourceNamePrefix source name prefix * @param targetNamePrefix source name prefix */ public CmsCloneModule( String actionClass, String authorEmail, String authorName, String changeResourceTypes, String description, String formatterSourceModule, String formatterTargetModule, String group, String niceName, String packageName, String sourceModuleName, String sourceNamePrefix, String targetNamePrefix) { super(); m_actionClass = actionClass; m_authorEmail = authorEmail; m_authorName = authorName; m_changeResourceTypes = changeResourceTypes; m_description = description; m_formatterSourceModule = formatterSourceModule; m_formatterTargetModule = formatterTargetModule; m_group = group; m_niceName = niceName; m_packageName = packageName; m_sourceModuleName = sourceModuleName; m_sourceNamePrefix = sourceNamePrefix; m_targetNamePrefix = targetNamePrefix; } /** * Executes the module clone and returns the new module.

* * @throws Throwable if anything goes wrong */ public void executeModuleClone() throws Throwable { CmsModule sourceModule = OpenCms.getModuleManager().getModule(m_sourceModuleName); // clone the module object CmsModule targetModule = (CmsModule)sourceModule.clone(); targetModule.setName(m_packageName); targetModule.setNiceName(m_niceName); targetModule.setDescription(m_description); targetModule.setAuthorEmail(m_authorEmail); targetModule.setAuthorName(m_authorName); targetModule.setGroup(m_group); targetModule.setActionClass(m_actionClass); try { // store the module paths String sourceModulePath = CmsWorkplace.VFS_PATH_MODULES + sourceModule.getName() + "/"; String targetModulePath = CmsWorkplace.VFS_PATH_MODULES + targetModule.getName() + "/"; // store the package name as path part String sourcePathPart = sourceModule.getName().replaceAll("\\.", "/"); String targetPathPart = targetModule.getName().replaceAll("\\.", "/"); // store the classes folder paths String sourceClassesPath = targetModulePath + PATH_CLASSES + sourcePathPart + "/"; String targetClassesPath = targetModulePath + PATH_CLASSES + targetPathPart + "/"; // copy the resources getCmsObject().copyResource(sourceModulePath, targetModulePath); // check if we have to create the classes folder if (getCmsObject().existsResource(sourceClassesPath)) { // in the source module a classes folder was defined, // now create all sub-folders for the package structure in the new module folder createTargetClassesFolder(targetModule, sourceClassesPath, targetModulePath + PATH_CLASSES); // delete the origin classes folder deleteSourceClassesFolder(targetModulePath, sourcePathPart, targetPathPart); } // TODO: clone module dependencies // adjust the export points cloneExportPoints(sourceModule, targetModule, sourcePathPart, targetPathPart); // adjust the resource type names and IDs Map descKeys = new HashMap(); Map resTypeMap = cloneResourceTypes( sourceModule, targetModule, sourcePathPart, targetPathPart, descKeys); // adjust the explorer type names and store referred icons and message keys Map iconPaths = new HashMap(); cloneExplorerTypes(targetModule, iconPaths, descKeys); // rename the icon file names cloneExplorerTypeIcons(iconPaths); // adjust the module resources adjustModuleResources(sourceModule, targetModule, sourcePathPart, targetPathPart, iconPaths); // search and replace the localization keys if (getCmsObject().existsResource(targetClassesPath)) { List props = getCmsObject().readResources( targetClassesPath, CmsResourceFilter.DEFAULT_FILES); replacesMessages(descKeys, props); } int type = OpenCms.getResourceManager().getResourceType(CmsVfsBundleManager.TYPE_XML_BUNDLE).getTypeId(); CmsResourceFilter filter = CmsResourceFilter.requireType(type); List resources = getCmsObject().readResources(targetModulePath, filter); replacesMessages(descKeys, resources); renameXmlVfsBundles(resources, targetModule, sourceModule.getName()); List allModuleResources = getCmsObject().readResources(targetModulePath, CmsResourceFilter.ALL); replacePath(sourceModulePath, targetModulePath, allModuleResources); // search and replace paths replaceModuleName(); // replace formatter paths if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_formatterTargetModule) && !targetModule.getResourceTypes().isEmpty()) { replaceFormatterPaths(targetModule); } adjustModuleConfig(targetModule, resTypeMap); // publish the new module for (String res : targetModule.getResources()) { OpenCms.getPublishManager().publishResource(getCmsObject(), res); OpenCms.getPublishManager().waitWhileRunning(); } // add the imported module to the module manager OpenCms.getModuleManager().addModule(getCmsObject(), targetModule); // reinitialize the resource manager with additional module resource types if necessary if (targetModule.getResourceTypes() != Collections.EMPTY_LIST) { OpenCms.getResourceManager().initialize(getCmsObject()); } // reinitialize the workplace manager with additional module explorer types if necessary if (targetModule.getExplorerTypes() != Collections.EMPTY_LIST) { OpenCms.getWorkplaceManager().addExplorerTypeSettings(targetModule); } // re-initialize the workplace OpenCms.getWorkplaceManager().initialize(getCmsObject()); // fire "clear caches" event to reload all cached resource bundles OpenCms.fireCmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, new HashMap()); // change resource types and schema locations if (isTrue(m_changeResourceTypes)) { changeResourceTypes(resTypeMap); } // adjust container pages CmsObject cms = OpenCms.initCmsObject(getCmsObject()); if (isTrue(m_changeResourceTypesEverywhere)) { cms.getRequestContext().setSiteRoot("/"); } CmsResourceFilter f = CmsResourceFilter.requireType(CmsResourceTypeXmlContainerPage.getContainerPageTypeId()); List allContainerPages = cms.readResources("/", f); replacePath(sourceModulePath, targetModulePath, allContainerPages); // delete the old module if (isTrue(m_deleteModule)) { OpenCms.getModuleManager().deleteModule( getCmsObject(), sourceModule.getName(), false, new CmsLogReport(getCmsObject().getRequestContext().getLocale(), CmsCloneModule.class)); } } catch (Throwable t) { LOG.error(t.getMessage(), t); throw t; } } /** * Returns the action class.

* * @return the action class */ public String getActionClass() { return m_actionClass; } /** * Returns a list of all module names.

* * @return a list of all module names */ public List getAllModuleNames() { List sortedModuleNames = new ArrayList(OpenCms.getModuleManager().getModuleNames()); java.util.Collections.sort(sortedModuleNames); return sortedModuleNames; } * Returns the author email.

* * @return the author email */ public String getAuthorEmail() { return m_authorEmail; } /** * Returns the author name.

* * @return the author name */ public String getAuthorName() { return m_authorName; } /** * Returns the change resource types flag as String.

* * @return the change resource types flag as String */ public String getChangeResourceTypes() { return m_changeResourceTypes; } /** * Returns the changeResourceTypesEverywhere.

* * @return the changeResourceTypesEverywhere */ public String getChangeResourceTypesEverywhere() { return m_changeResourceTypesEverywhere; } /** * Returns the delete module flag String.

* * @return the delete module flag as String */ public String getDeleteModule() { return m_deleteModule; } /** * Returns the description.

* * @return the description */ public String getDescription() { return m_description; } /** * Returns the formatter source module package/name.

* * @return the formatter source module package/name */ public String getFormatterSourceModule() { return m_formatterSourceModule; } /** * Returns the formatter target module package/name.

* * @return the formatter target module package/name */ public String getFormatterTargetModule() { return m_formatterTargetModule; } /** * Returns the group.

* * @return the group */ public String getGroup() { return m_group; } /** * Returns the nice name.

* * @return the nice name */ public String getNiceName() { return m_niceName; } /** * Returns the package/module name for the clone/target.

* * @return the package/module name for the clone/target */ public String getPackageName() { return m_packageName; } /** * Returns the source module package/name (the module to clone).

* * @return the source module package/name (the module to clone) */ public String getSourceModuleName() { return m_sourceModuleName; } /** * Returns the source name prefix.

* * @return the source name prefix */ public String getSourceNamePrefix() { return m_sourceNamePrefix; } /** * Returns the target name prefix.

* * @return the target name prefix */ public String getTargetNamePrefix() { return m_targetNamePrefix; } /** * Sets the action class.

* * @param actionClass the action class */ public void setActionClass(String actionClass) { m_actionClass = actionClass; } /** * Sets the author email.

* * @param authorEmail the author email to set */ public void setAuthorEmail(String authorEmail) { m_authorEmail = authorEmail; } /** * Sets the author name.

* * @param authorName the author name to set */ public void setAuthorName(String authorName) { m_authorName = authorName; } /** * Sets the change resource types flag.

* * @param changeResourceTypes the change resource types falg to set */ public void setChangeResourceTypes(String changeResourceTypes) { m_changeResourceTypes = changeResourceTypes; } /** * Sets the changeResourceTypesEverywhere.

* * @param changeResourceTypesEverywhere the changeResourceTypesEverywhere to set */ public void setChangeResourceTypesEverywhere(String changeResourceTypesEverywhere) { m_changeResourceTypesEverywhere = changeResourceTypesEverywhere; } /** * Sets the delete module flag.

* * @param deleteModule the delete module flag to set */ public void setDeleteModule(String deleteModule) { m_deleteModule = deleteModule; } /** * Sets the description.

* * @param description the description to set */ public void setDescription(String description) { m_description = description; } /** * Sets the formatter source module name.

* * @param formatterSourceModule the formatter source module name to set */ public void setFormatterSourceModule(String formatterSourceModule) { m_formatterSourceModule = formatterSourceModule; } /** * Sets the formatter target module name.

* * @param formatterTargetModule the formatter target module name to set */ public void setFormatterTargetModule(String formatterTargetModule) { m_formatterTargetModule = formatterTargetModule; } /** * Sets the group.

* * @param group the group to set */ public void setGroup(String group) { m_group = group; * Sets the nice name.

* * @param niceName the nice name to set */ public void setNiceName(String niceName) { m_niceName = niceName; } /** * Sets the package name.

* * @param packageName the package name to set */ public void setPackageName(String packageName) { m_packageName = packageName; } /** * Sets the source module name.

* * @param sourceModuleName the source module name to set */ public void setSourceModuleName(String sourceModuleName) { m_sourceModuleName = sourceModuleName; } /** * Sets the source name prefix.

* * @param sourceNamePrefix the source name prefix to set */ public void setSourceNamePrefix(String sourceNamePrefix) { m_sourceNamePrefix = sourceNamePrefix; } /** * Sets the target name prefix.

* * @param targetNamePrefix the target name prefix to set */ public void setTargetNamePrefix(String targetNamePrefix) { m_targetNamePrefix = targetNamePrefix; } /** * Returns true if the module has been created successful.

* * @return true if the module has been created successful */ public boolean success() { return OpenCms.getModuleManager().getModule(m_packageName) != null; } /** * Adjusts the module configuration file.

* * @param targetModule the target moodule * @param resTypeMap the resource type mapping * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void adjustModuleConfig(CmsModule targetModule, Map resTypeMap) throws CmsException, UnsupportedEncodingException { String modPath = CmsWorkplace.VFS_PATH_MODULES + targetModule.getName() + "/" + CmsADEManager.CONFIG_FILE_NAME; CmsResource config = getCmsObject().readResource( modPath, CmsResourceFilter.requireType(OpenCms.getResourceManager().getResourceType(CmsADEManager.MODULE_CONFIG_TYPE).getTypeId())); CmsFile file = getCmsObject().readFile(config); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); for (Map.Entry mapping : resTypeMap.entrySet()) { content = content.replaceAll(mapping.getKey().getTypeName(), mapping.getValue().getTypeName()); file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } /** * Adjusts the paths of the module resources from the source path to the target path.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the path part of the source module * @param targetPathPart the path part of the target module * @param iconPaths the path where resource type icons are located */ private void adjustModuleResources( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart, Map iconPaths) { List newTargetResources = new ArrayList(); List targetResources = targetModule.getResources(); for (String modRes : targetResources) { String nIcon = iconPaths.get(modRes.substring(modRes.lastIndexOf('/') + 1)); if (nIcon != null) { // the referenced resource is an resource type icon, add the new icon path newTargetResources.add(ICON_PATH + nIcon); } else if (modRes.contains(sourceModule.getName())) { // there is the name in it newTargetResources.add(modRes.replaceAll(sourceModule.getName(), targetModule.getName())); } else if (modRes.contains(sourcePathPart)) { // there is a path in it newTargetResources.add(modRes.replaceAll(sourcePathPart, targetPathPart)); } else { // there is whether the path nor the name in it newTargetResources.add(modRes); } } targetModule.setResources(newTargetResources); } /** * Changes the resource types and the schema locations of existing content.

* * @param resTypeMap a map containing the source types as keys and the target types as values * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void changeResourceTypes(Map resTypeMap) throws CmsException, UnsupportedEncodingException { CmsObject clone = OpenCms.initCmsObject(getCmsObject()); if (isTrue(m_changeResourceTypesEverywhere)) { clone.getRequestContext().setSiteRoot("/"); } for (Map.Entry mapping : resTypeMap.entrySet()) { CmsResourceFilter filter = CmsResourceFilter.requireType(mapping.getKey().getTypeId()); List resources = clone.readResources("/", filter); } String sourceSchemaPath = mapping.getKey().getConfiguration().get("schema"); String targetSchemaPath = mapping.getValue().getConfiguration().get("schema"); for (CmsResource res : resources) { if (lockResource(getCmsObject(), res)) { CmsFile file = getCmsObject().readFile(res); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); content = content.replaceAll(sourceSchemaPath, targetSchemaPath); file.setContents(content.getBytes(encoding)); try { getCmsObject().writeFile(file); } catch (CmsXmlException e) { LOG.error(e.getMessage(), e); } res.setType(mapping.getValue().getTypeId()); getCmsObject().writeResource(res); } } } } /** * Copies the explorer type icons.

* * @param iconPaths the path to the location where the icons are located * * @throws CmsException if something goes wrong */ private void cloneExplorerTypeIcons(Map iconPaths) throws CmsException { for (Map.Entry entry : iconPaths.entrySet()) { String source = ICON_PATH + entry.getKey(); String target = ICON_PATH + entry.getValue(); if (!getCmsObject().existsResource(target)) { getCmsObject().copyResource(source, target); } } } /** * Copies the explorer type definitions.

* * @param targetModule the target module * @param iconPaths the path to the location where the icons are located * @param descKeys a map that contains a mapping of the explorer type definitions messages */ private void cloneExplorerTypes(CmsModule targetModule, Map iconPaths, Map descKeys) { List targetExplorerTypes = targetModule.getExplorerTypes(); for (CmsExplorerTypeSettings expSetting : targetExplorerTypes) { descKeys.put(expSetting.getKey(), expSetting.getKey().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); String newIcon = expSetting.getIcon().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix); String newBigIcon = expSetting.getBigIconIfAvailable().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix); iconPaths.put(expSetting.getIcon(), newIcon); iconPaths.put(expSetting.getBigIconIfAvailable(), newBigIcon); expSetting.setName(expSetting.getName().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setKey(expSetting.getKey().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setIcon(expSetting.getIcon().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setBigIcon(expSetting.getBigIconIfAvailable().replaceFirst( m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setNewResourceUri(expSetting.getNewResourceUri().replaceFirst( m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setInfo(expSetting.getInfo().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); } } /** * Clones the export points of the module and adjusts its paths.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the source path part * @param targetPathPart the target path part */ private void cloneExportPoints( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart) { for (CmsExportPoint exp : targetModule.getExportPoints()) { if (exp.getUri().contains(sourceModule.getName())) { * exp.setUri(exp.getUri().replaceAll(sourceModule.getName(), targetModule.getName())); } if (exp.getUri().contains(sourcePathPart)) { exp.setUri(exp.getUri().replaceAll(sourcePathPart, targetPathPart)); } } } /** * Clones/copies the resource types.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the source path part * @param targetPathPart the target path part * @param keys the map where to put in the messages of the resource type * * @return a map with source resource types as key and the taregt resource types as value */ private Map cloneResourceTypes( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart, Map keys) { Map resourceTypeMapping = new HashMap(); List targetResourceTypes = new ArrayList(); for (I_CmsResourceType sourceResType : targetModule.getResourceTypes()) { // get the class name attribute String className = sourceResType.getClassName(); // create the class instance I_CmsResourceType targetResType; try { if (className != null) { className = className.trim(); } int newId = -1; boolean exists = true; do { newId = new Random().nextInt((99999)) + 10000; try { OpenCms.getResourceManager().getResourceType(newId); } catch (CmsLoaderException e) { exists = false; } while (exists); targetResType = (I_CmsResourceType)Class.forName(className).newInstance(); for (String mapping : sourceResType.getConfiguredMappings()) { targetResType.addMappingType(mapping); } targetResType.setAdjustLinksFolder(sourceResType.getAdjustLinksFolder()); if (targetResType instanceof A_CmsResourceType) { A_CmsResourceType concreteTargetResType = (A_CmsResourceType)targetResType; for (CmsProperty prop : sourceResType.getConfiguredDefaultProperties()) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(prop.getValue())) { prop.setStructureValue(prop.getStructureValue().replaceAll( sourceModule.getName(), targetModule.getName()).replaceAll(sourcePathPart, targetPathPart)); prop.setResourceValue(prop.getResourceValue().replaceAll( sourceModule.getName(), targetModule.getName()).replaceAll(sourcePathPart, targetPathPart)); } concreteTargetResType.addDefaultProperty(prop); } for (CmsConfigurationCopyResource conres : sourceResType.getConfiguredCopyResources()) { concreteTargetResType.addCopyResource( conres.getSource(), conres.getTarget(), conres.getTypeString()); } } for (Map.Entry entry : sourceResType.getConfiguration().entrySet()) { targetResType.addConfigurationParameter( entry.getKey(), entry.getValue().replaceAll(sourceModule.getName(), targetModule.getName())); } targetResType.setAdditionalModuleResourceType(true); targetResType.initConfiguration( sourceResType.getTypeName().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix), newId + "", sourceResType.getClassName()); keys.put(sourceResType.getTypeName(), targetResType.getTypeName()); targetResourceTypes.add(targetResType); resourceTypeMapping.put(sourceResType, targetResType); } catch (Exception e) { // resource type is unknown, use dummy class to import the module resources targetResType = new CmsResourceTypeUnknown(); // write an error to the log LOG.error( Messages.get().getBundle().key( Messages.ERR_UNKNOWN_RESTYPE_CLASS_2, className, targetResType.getClass().getName()), e); } } targetModule.setResourceTypes(targetResourceTypes); return resourceTypeMapping; } /** * Creates the target folder for the module clone.

* * @param targetModule the target module * @param sourceClassesPath the source module class path * @param targetBaseClassesPath the 'classes' folder of the target module * * @throws CmsException if something goes wrong */ private void createTargetClassesFolder( CmsModule targetModule, String sourceClassesPath, String targetBaseClassesPath) throws CmsException { StringTokenizer tok = new StringTokenizer(targetModule.getName(), "."); int folderId = CmsResourceTypeFolder.getStaticTypeId(); String targetClassesPath = targetBaseClassesPath; while (tok.hasMoreTokens()) { String folder = tok.nextToken(); targetClassesPath += folder + "/"; if (!getCmsObject().existsResource(targetClassesPath)) { getCmsObject().createResource(targetClassesPath, folderId); } } // move exiting content into new classes sub-folder List propertyFiles = getCmsObject().readResources(sourceClassesPath, CmsResourceFilter.ALL); for (CmsResource res : propertyFiles) { if (!getCmsObject().existsResource(targetClassesPath + res.getName())) { getCmsObject().copyResource(res.getRootPath(), targetClassesPath + res.getName()); } } } /** * Deletes the temporarily copied classes files.

* * @param targetModulePath the target module path * @param sourcePathPart the path part of the source module * @param targetPathPart the target path part * * @throws CmsException if something goes wrong */ private void deleteSourceClassesFolder(String targetModulePath, String sourcePathPart, String targetPathPart) throws CmsException { String sourceFirstFolder = sourcePathPart.substring(0, sourcePathPart.indexOf('/')); String targetFirstFolder = sourcePathPart.substring(0, sourcePathPart.indexOf('/')); if (!sourceFirstFolder.equals(targetFirstFolder)) { getCmsObject().deleteResource( targetModulePath + PATH_CLASSES + sourceFirstFolder, CmsResource.DELETE_PRESERVE_SIBLINGS); return; } String[] targetPathParts = CmsStringUtil.splitAsArray(targetPathPart, '/'); String[] sourcePathParts = CmsStringUtil.splitAsArray(sourcePathPart, '/'); int sourceLength = sourcePathParts.length; int diff = 0; for (int i = 0; i < targetPathParts.length; i++) { if (sourceLength >= i) { if (!targetPathParts[i].equals(sourcePathParts[i])) { diff = i + 1; } } String topSourceClassesPath = targetModulePath + PATH_CLASSES + sourcePathPart.substring(0, sourcePathPart.indexOf('/')) + "/"; if (diff != 0) { topSourceClassesPath = targetModulePath + PATH_CLASSES; for (int i = 0; i < diff; i++) { topSourceClassesPath += sourcePathParts[i] + "/"; } } getCmsObject().deleteResource(topSourceClassesPath, CmsResource.DELETE_PRESERVE_SIBLINGS); } /** * Returns true if form imput is selected, checked, on or yes.

* * @param value the value to check * * @return true if form imput is selected, checked, on or yes */ private boolean isTrue(String value) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(value)) { if (Boolean.valueOf(value.toLowerCase()).booleanValue() || value.toLowerCase().equals("on") || value.toLowerCase().equals("yes") || value.toLowerCase().equals("checked") || value.toLowerCase().equals("selected")) { return true; } } return false; } /** * Locks the current resource.

* * @param cms the current CmsObject * @param cmsResource the resource to lock * * @return true if the given resource was locked was successfully * * @throws CmsException if some goes wrong */ private boolean lockResource(CmsObject cms, CmsResource cmsResource) throws CmsException { CmsLock lock = cms.getLock(cms.getSitePath(cmsResource)); // check the lock if ((lock != null) getCmsObject().writeFile(file); && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // prove is current lock from current user in current project return true; } else if ((lock != null) && !lock.isUnlocked() && !lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { // the resource is not locked by the current user, so can not lock it return false; } else if ((lock != null) && !lock.isUnlocked() && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && !lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // prove is current lock from current user but not in current project // file is locked by current user but not in current project // change the lock cms.changeLock(cms.getSitePath(cmsResource)); } else if ((lock != null) && lock.isUnlocked()) { // lock resource from current user in current project cms.lockResource(cms.getSitePath(cmsResource)); } lock = cms.getLock(cms.getSitePath(cmsResource)); if ((lock != null) && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && !lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // resource could not be locked return false; } // resource is locked successfully return true; } /** * Renames the vfs resource bundle files within the target module according to the new module's name.

* * @param resources the vfs resource bundle files * @param targetModule the target module * @param name the package name of the source module * * @return a list of all xml vfs bundles within the given module * * @throws CmsException if something gows wrong */ private List renameXmlVfsBundles(List resources, CmsModule targetModule, String name) throws CmsException { for (CmsResource res : resources) { String newName = res.getName().replaceAll(name, targetModule.getName()); String targetRootPath = CmsResource.getFolderPath(res.getRootPath()) + newName; if (!getCmsObject().existsResource(targetRootPath)) { getCmsObject().moveResource(res.getRootPath(), targetRootPath); } } return resources; } /** * Replaces the referenced formatters within the new XSD files with the new formatter paths.

* * @param targetModule the target module * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replaceFormatterPaths(CmsModule targetModule) throws CmsException, UnsupportedEncodingException { CmsResource formatterSourceFolder = getCmsObject().readResource( "/system/modules/" + m_formatterSourceModule + "/"); CmsResource formatterTargetFolder = getCmsObject().readResource( "/system/modules/" + m_formatterTargetModule + "/"); for (I_CmsResourceType type : targetModule.getResourceTypes()) { String schemaPath = type.getConfiguration().get("schema"); CmsResource res = getCmsObject().readResource(schemaPath); CmsFile file = getCmsObject().readFile(res); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); content = content.replaceAll(formatterSourceFolder.getRootPath(), formatterTargetFolder.getRootPath()); file.setContents(content.getBytes(encoding)); } /** * Initializes a thread to find and replace all occurrence of the module's path.

* * @throws CmsException * @throws UnsupportedEncodingException */ private void replaceModuleName() throws CmsException, UnsupportedEncodingException { CmsResourceFilter filter = CmsResourceFilter.ALL.addRequireFile().addExcludeState(CmsResource.STATE_DELETED).addRequireTimerange().addRequireVisible(); List resources = getCmsObject().readResources( CmsWorkplace.VFS_PATH_MODULES + m_packageName + "/", filter); for (CmsResource resource : resources) { CmsFile file = getCmsObject().readFile(resource); byte[] contents = file.getContents(); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(contents, encoding); Matcher matcher = Pattern.compile(m_sourceModuleName).matcher(content); if (matcher.find()) { contents = matcher.replaceAll(m_packageName).getBytes(encoding); if (lockResource(getCmsObject(), file)) { file.setContents(contents); getCmsObject().writeFile(file); } } } } /** * Replaces the paths within all the given resources and removes all UUIDs by an regex.

* * @param sourceModulePath the search path * @param targetModulePath the replace path * @param allModuleResources the resources * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replacePath(String sourceModulePath, String targetModulePath, List allModuleResources) throws CmsException, UnsupportedEncodingException { for (CmsResource resource : allModuleResources) { if (resource.isFile()) { CmsFile file = getCmsObject().readFile(resource); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String oldContent = new String(file.getContents(), encoding); String newContent = oldContent.replaceAll(sourceModulePath, targetModulePath); Matcher matcher = Pattern.compile(CmsUUID.UUID_REGEX).matcher(newContent); newContent = matcher.replaceAll(""); newContent = newContent.replaceAll("", ""); if (!oldContent.equals(newContent)) { file.setContents(newContent.getBytes(encoding)); if (!resource.getRootPath().startsWith(CmsWorkplace.VFS_PATH_SYSTEM)) { if (lockResource(getCmsObject(), resource)) { getCmsObject().writeFile(file); } } else { getCmsObject().writeFile(file); } } } } } /** * Replaces the messages for the given resources.

* * @param descKeys the replacement mapping * @param resources the resources to consult * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replacesMessages(Map descKeys, List resources) throws CmsException, UnsupportedEncodingException { for (CmsResource resource : resources) { CmsFile file = getCmsObject().readFile(resource); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); for (Map.Entry entry : descKeys.entrySet()) { content = content.replaceAll(entry.getKey(), entry.getValue()); } file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } } ======= /* * File : $Source$ * Date : $Date$ * Version: $Revision$ * * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (C) 2002 - 2009 Alkacon Software (http://www.alkacon.com) * * This library 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 library 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. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.workplace.tools.modules; import org.opencms.ade.configuration.CmsADEManager; import org.opencms.configuration.CmsConfigurationCopyResource; import org.opencms.configuration.Messages; import org.opencms.db.CmsExportPoint; import org.opencms.file.CmsFile; import org.opencms.file.CmsObject; import org.opencms.file.CmsProperty; import org.opencms.file.CmsResource; import org.opencms.file.CmsResourceFilter; import org.opencms.file.types.A_CmsResourceType; import org.opencms.file.types.CmsResourceTypeFolder; import org.opencms.file.types.CmsResourceTypeUnknown; import org.opencms.file.types.CmsResourceTypeXmlContainerPage; import org.opencms.file.types.I_CmsResourceType; import org.opencms.i18n.CmsLocaleManager; import org.opencms.i18n.CmsVfsBundleManager; import org.opencms.jsp.CmsJspActionElement; import org.opencms.loader.CmsLoaderException; import org.opencms.lock.CmsLock; import org.opencms.main.CmsException; import org.opencms.main.CmsLog; import org.opencms.main.I_CmsEventListener; import org.opencms.main.OpenCms; import org.opencms.module.CmsModule; import org.opencms.report.CmsLogReport; import org.opencms.util.CmsStringUtil; import org.opencms.util.CmsUUID; import org.opencms.workplace.CmsWorkplace; import org.opencms.workplace.explorer.CmsExplorerTypeSettings; import org.opencms.xml.CmsXmlException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.PageContext; import org.apache.commons.logging.Log; /** * Clones a module.

*/ public class CmsCloneModule extends CmsJspActionElement { /** The icon path. */ public static final String ICON_PATH = CmsWorkplace.VFS_PATH_RESOURCES + CmsWorkplace.RES_PATH_FILETYPES; /** Classes folder within the module. */ public static final String PATH_CLASSES = "classes/"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsCloneModule.class); /** The action class used for the clone. */ private String m_actionClass; /** The author's email used for the clone. */ private String m_authorEmail = "sales@alkacon.com"; /** The author's name used for the clone. */ private String m_authorName = "Alkacon Software GmbH"; /** Option to change the resource types (optional flag). */ private String m_changeResourceTypes; /** If 'true' resource types in all sites will be adjusted. */ private String m_changeResourceTypesEverywhere; /** Option to delete the source module after cloning (optional flag). */ private String m_deleteModule; /** The description used for the clone. */ private String m_description = "This module provides the template layout."; /** A module name where the formatters are located that are referenced within the XSDs of the module to clone. */ private String m_formatterSourceModule = "com.alkacon.bootstrap.formatters"; /** A module name where the formatters are located that should be referenced by the XSDs of the clone. */ private String m_formatterTargetModule; /** The module group used for the clone. */ private String m_group; /** The nice name used for the clone. */ private String m_niceName = "My new template module."; /** The new module name used for the clone. */ private String m_packageName = "my.company.template"; /** The name of the source module to be cloned. */ private String m_sourceModuleName = "com.alkacon.bootstrap.formatters"; /** The prefix that is used by the source module. */ private String m_sourceNamePrefix = "bs"; // store the classes folder paths /** The prefix that is used by the target module. */ private String m_targetNamePrefix = "my"; /** * Public constructor.

*/ public CmsCloneModule() { // NOOP } /** * Constructor, with parameters.

* * @param context the JSP page context object * @param req the JSP request * @param res the JSP response */ public CmsCloneModule(PageContext context, HttpServletRequest req, HttpServletResponse res) { super(context, req, res); } /** * Bean constructor.

* * @param actionClass action class * @param authorEmail author email * @param authorName author name * @param changeResourceTypes change resource type flags * @param description module description * @param formatterSourceModule formatter source module * @param formatterTargetModule formatter target module * @param group module group * @param niceName nice name * @param packageName package/module name * @param sourceModuleName source module package/name * @param sourceNamePrefix source name prefix * @param targetNamePrefix source name prefix */ public CmsCloneModule( String actionClass, String authorEmail, String authorName, String changeResourceTypes, String description, String formatterSourceModule, String formatterTargetModule, String group, String niceName, String packageName, String sourceModuleName, String sourceNamePrefix, String targetNamePrefix) { super(); m_actionClass = actionClass; m_authorEmail = authorEmail; m_authorName = authorName; m_changeResourceTypes = changeResourceTypes; m_description = description; m_formatterSourceModule = formatterSourceModule; m_formatterTargetModule = formatterTargetModule; m_group = group; m_niceName = niceName; m_packageName = packageName; m_sourceModuleName = sourceModuleName; m_sourceNamePrefix = sourceNamePrefix; m_targetNamePrefix = targetNamePrefix; } /** * Executes the module clone and returns the new module.

* * @throws Throwable if anything goes wrong */ public void executeModuleClone() throws Throwable { CmsModule sourceModule = OpenCms.getModuleManager().getModule(m_sourceModuleName); // clone the module object CmsModule targetModule = (CmsModule)sourceModule.clone(); targetModule.setName(m_packageName); targetModule.setNiceName(m_niceName); targetModule.setDescription(m_description); targetModule.setAuthorEmail(m_authorEmail); targetModule.setAuthorName(m_authorName); targetModule.setGroup(m_group); targetModule.setActionClass(m_actionClass); try { // store the module paths String sourceModulePath = CmsWorkplace.VFS_PATH_MODULES + sourceModule.getName() + "/"; String targetModulePath = CmsWorkplace.VFS_PATH_MODULES + targetModule.getName() + "/"; // store the package name as path part String sourcePathPart = sourceModule.getName().replaceAll("\\.", "/"); String targetPathPart = targetModule.getName().replaceAll("\\.", "/"); String sourceClassesPath = targetModulePath + PATH_CLASSES + sourcePathPart + "/"; String targetClassesPath = targetModulePath + PATH_CLASSES + targetPathPart + "/"; // copy the resources getCmsObject().copyResource(sourceModulePath, targetModulePath); // check if we have to create the classes folder if (getCmsObject().existsResource(sourceClassesPath)) { // in the source module a classes folder was defined, // now create all sub-folders for the package structure in the new module folder createTargetClassesFolder(targetModule, sourceClassesPath, targetModulePath + PATH_CLASSES); // delete the origin classes folder deleteSourceClassesFolder(targetModulePath, sourcePathPart, targetPathPart); } // TODO: clone module dependencies // adjust the export points cloneExportPoints(sourceModule, targetModule, sourcePathPart, targetPathPart); // adjust the resource type names and IDs Map descKeys = new HashMap(); Map resTypeMap = cloneResourceTypes( sourceModule, targetModule, sourcePathPart, targetPathPart, descKeys); // adjust the explorer type names and store referred icons and message keys Map iconPaths = new HashMap(); cloneExplorerTypes(targetModule, iconPaths, descKeys); // rename the icon file names cloneExplorerTypeIcons(iconPaths); // adjust the module resources adjustModuleResources(sourceModule, targetModule, sourcePathPart, targetPathPart, iconPaths); // search and replace the localization keys if (getCmsObject().existsResource(targetClassesPath)) { List props = getCmsObject().readResources( */ targetClassesPath, CmsResourceFilter.DEFAULT_FILES); replacesMessages(descKeys, props); } int type = OpenCms.getResourceManager().getResourceType(CmsVfsBundleManager.TYPE_XML_BUNDLE).getTypeId(); CmsResourceFilter filter = CmsResourceFilter.requireType(type); List resources = getCmsObject().readResources(targetModulePath, filter); replacesMessages(descKeys, resources); renameXmlVfsBundles(resources, targetModule, sourceModule.getName()); List allModuleResources = getCmsObject().readResources(targetModulePath, CmsResourceFilter.ALL); replacePath(sourceModulePath, targetModulePath, allModuleResources); // search and replace paths replaceModuleName(); // replace formatter paths if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_formatterTargetModule) && !targetModule.getResourceTypes().isEmpty()) { replaceFormatterPaths(targetModule); } adjustModuleConfig(targetModule, resTypeMap); // publish the new module for (String res : targetModule.getResources()) { OpenCms.getPublishManager().publishResource(getCmsObject(), res); OpenCms.getPublishManager().waitWhileRunning(); } // add the imported module to the module manager OpenCms.getModuleManager().addModule(getCmsObject(), targetModule); // reinitialize the resource manager with additional module resource types if necessary if (targetModule.getResourceTypes() != Collections.EMPTY_LIST) { OpenCms.getResourceManager().initialize(getCmsObject()); } // reinitialize the workplace manager with additional module explorer types if necessary if (targetModule.getExplorerTypes() != Collections.EMPTY_LIST) { /** OpenCms.getWorkplaceManager().addExplorerTypeSettings(targetModule); } // re-initialize the workplace OpenCms.getWorkplaceManager().initialize(getCmsObject()); // fire "clear caches" event to reload all cached resource bundles OpenCms.fireCmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, new HashMap()); // change resource types and schema locations if (isTrue(m_changeResourceTypes)) { changeResourceTypes(resTypeMap); } // adjust container pages CmsObject cms = OpenCms.initCmsObject(getCmsObject()); if (isTrue(m_changeResourceTypesEverywhere)) { cms.getRequestContext().setSiteRoot("/"); } CmsResourceFilter f = CmsResourceFilter.requireType(CmsResourceTypeXmlContainerPage.getContainerPageTypeId()); List allContainerPages = cms.readResources("/", f); replacePath(sourceModulePath, targetModulePath, allContainerPages); // delete the old module if (isTrue(m_deleteModule)) { OpenCms.getModuleManager().deleteModule( getCmsObject(), sourceModule.getName(), false, new CmsLogReport(getCmsObject().getRequestContext().getLocale(), CmsCloneModule.class)); } } catch (Throwable t) { LOG.error(t.getMessage(), t); throw t; } } /** * Returns the action class.

* * @return the action class */ public String getActionClass() { return m_actionClass; } /** * Returns a list of all module names.

* * @return a list of all module names public List getAllModuleNames() { List sortedModuleNames = new ArrayList(OpenCms.getModuleManager().getModuleNames()); java.util.Collections.sort(sortedModuleNames); return sortedModuleNames; } /** * Returns the author email.

* * @return the author email */ public String getAuthorEmail() { return m_authorEmail; } /** * Returns the author name.

* * @return the author name */ public String getAuthorName() { return m_authorName; } /** * Returns the change resource types flag as String.

* * @return the change resource types flag as String */ public String getChangeResourceTypes() { return m_changeResourceTypes; } /** * Returns the changeResourceTypesEverywhere.

* * @return the changeResourceTypesEverywhere */ public String getChangeResourceTypesEverywhere() { return m_changeResourceTypesEverywhere; } /** * Returns the delete module flag String.

* * @return the delete module flag as String */ public String getDeleteModule() { return m_deleteModule; } * Returns the description.

* * @return the description */ public String getDescription() { return m_description; } /** * Returns the formatter source module package/name.

* * @return the formatter source module package/name */ public String getFormatterSourceModule() { return m_formatterSourceModule; } /** * Returns the formatter target module package/name.

* * @return the formatter target module package/name */ public String getFormatterTargetModule() { return m_formatterTargetModule; } /** * Returns the group.

* * @return the group */ public String getGroup() { return m_group; } /** * Returns the nice name.

* * @return the nice name */ public String getNiceName() { return m_niceName; } /** * Returns the package/module name for the clone/target.

* * @return the package/module name for the clone/target */ public String getPackageName() { return m_packageName; } /** * Returns the source module package/name (the module to clone).

* * @return the source module package/name (the module to clone) */ public String getSourceModuleName() { return m_sourceModuleName; } /** * Returns the source name prefix.

* * @return the source name prefix */ public String getSourceNamePrefix() { return m_sourceNamePrefix; } /** * Returns the target name prefix.

* * @return the target name prefix */ public String getTargetNamePrefix() { return m_targetNamePrefix; } /** * Sets the action class.

* * @param actionClass the action class */ public void setActionClass(String actionClass) { m_actionClass = actionClass; } /** * Sets the author email.

* * @param authorEmail the author email to set */ public void setAuthorEmail(String authorEmail) { m_authorEmail = authorEmail; } /** * Sets the author name.

* * @param authorName the author name to set */ public void setAuthorName(String authorName) { m_authorName = authorName; } /** * Sets the change resource types flag.

* @param changeResourceTypes the change resource types falg to set */ public void setChangeResourceTypes(String changeResourceTypes) { m_changeResourceTypes = changeResourceTypes; } /** * Sets the changeResourceTypesEverywhere.

* * @param changeResourceTypesEverywhere the changeResourceTypesEverywhere to set */ public void setChangeResourceTypesEverywhere(String changeResourceTypesEverywhere) { m_changeResourceTypesEverywhere = changeResourceTypesEverywhere; } /** * Sets the delete module flag.

* * @param deleteModule the delete module flag to set */ public void setDeleteModule(String deleteModule) { m_deleteModule = deleteModule; } /** * Sets the description.

* * @param description the description to set */ public void setDescription(String description) { m_description = description; } /** * Sets the formatter source module name.

* * @param formatterSourceModule the formatter source module name to set */ public void setFormatterSourceModule(String formatterSourceModule) { m_formatterSourceModule = formatterSourceModule; } /** * Sets the formatter target module name.

* * @param formatterTargetModule the formatter target module name to set */ public void setFormatterTargetModule(String formatterTargetModule) { m_formatterTargetModule = formatterTargetModule; } /** * Sets the group.

* * @param group the group to set */ public void setGroup(String group) { m_group = group; } /** * Sets the nice name.

* * @param niceName the nice name to set */ public void setNiceName(String niceName) { m_niceName = niceName; } /** * Sets the package name.

* * @param packageName the package name to set */ public void setPackageName(String packageName) { m_packageName = packageName; } /** * Sets the source module name.

* * @param sourceModuleName the source module name to set */ public void setSourceModuleName(String sourceModuleName) { m_sourceModuleName = sourceModuleName; } /** * Sets the source name prefix.

* * @param sourceNamePrefix the source name prefix to set */ public void setSourceNamePrefix(String sourceNamePrefix) { m_sourceNamePrefix = sourceNamePrefix; } /** * Sets the target name prefix.

* * @param targetNamePrefix the target name prefix to set */ public void setTargetNamePrefix(String targetNamePrefix) { m_targetNamePrefix = targetNamePrefix; } /** * Returns true if the module has been created successful.

* * @return true if the module has been created successful */ public boolean success() { return OpenCms.getModuleManager().getModule(m_packageName) != null; } /** * Adjusts the module configuration file.

* * @param targetModule the target moodule * @param resTypeMap the resource type mapping * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void adjustModuleConfig(CmsModule targetModule, Map resTypeMap) throws CmsException, UnsupportedEncodingException { String modPath = CmsWorkplace.VFS_PATH_MODULES + targetModule.getName() + "/" + CmsADEManager.CONFIG_FILE_NAME; CmsResource config = getCmsObject().readResource( modPath, CmsResourceFilter.requireType(OpenCms.getResourceManager().getResourceType(CmsADEManager.MODULE_CONFIG_TYPE).getTypeId())); CmsFile file = getCmsObject().readFile(config); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); for (Map.Entry mapping : resTypeMap.entrySet()) { content = content.replaceAll(mapping.getKey().getTypeName(), mapping.getValue().getTypeName()); file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } /** * Adjusts the paths of the module resources from the source path to the target path.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the path part of the source module * @param targetPathPart the path part of the target module * @param iconPaths the path where resource type icons are located */ private void adjustModuleResources( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart, Map iconPaths) { List newTargetResources = new ArrayList(); List targetResources = targetModule.getResources(); for (String modRes : targetResources) { String nIcon = iconPaths.get(modRes.substring(modRes.lastIndexOf('/') + 1)); if (nIcon != null) { // the referenced resource is an resource type icon, add the new icon path newTargetResources.add(ICON_PATH + nIcon); } else if (modRes.contains(sourceModule.getName())) { // there is the name in it newTargetResources.add(modRes.replaceAll(sourceModule.getName(), targetModule.getName())); } else if (modRes.contains(sourcePathPart)) { // there is a path in it newTargetResources.add(modRes.replaceAll(sourcePathPart, targetPathPart)); } else { // there is whether the path nor the name in it newTargetResources.add(modRes); } } targetModule.setResources(newTargetResources); } /** * Changes the resource types and the schema locations of existing content.

* * @param resTypeMap a map containing the source types as keys and the target types as values * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void changeResourceTypes(Map resTypeMap) throws CmsException, UnsupportedEncodingException { } CmsObject clone = OpenCms.initCmsObject(getCmsObject()); if (isTrue(m_changeResourceTypesEverywhere)) { clone.getRequestContext().setSiteRoot("/"); } for (Map.Entry mapping : resTypeMap.entrySet()) { CmsResourceFilter filter = CmsResourceFilter.requireType(mapping.getKey().getTypeId()); List resources = clone.readResources("/", filter); String sourceSchemaPath = mapping.getKey().getConfiguration().get("schema"); String targetSchemaPath = mapping.getValue().getConfiguration().get("schema"); for (CmsResource res : resources) { if (lockResource(getCmsObject(), res)) { CmsFile file = getCmsObject().readFile(res); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); content = content.replaceAll(sourceSchemaPath, targetSchemaPath); file.setContents(content.getBytes(encoding)); try { getCmsObject().writeFile(file); } catch (CmsXmlException e) { LOG.error(e.getMessage(), e); } res.setType(mapping.getValue().getTypeId()); getCmsObject().writeResource(res); } } } } /** * Copies the explorer type icons.

* * @param iconPaths the path to the location where the icons are located * * @throws CmsException if something goes wrong */ private void cloneExplorerTypeIcons(Map iconPaths) throws CmsException { for (Map.Entry entry : iconPaths.entrySet()) { String source = ICON_PATH + entry.getKey(); String target = ICON_PATH + entry.getValue(); if (!getCmsObject().existsResource(target)) { getCmsObject().copyResource(source, target); } } } /** * Copies the explorer type definitions.

* * @param targetModule the target module * @param iconPaths the path to the location where the icons are located * @param descKeys a map that contains a mapping of the explorer type definitions messages */ private void cloneExplorerTypes(CmsModule targetModule, Map iconPaths, Map descKeys) { List targetExplorerTypes = targetModule.getExplorerTypes(); for (CmsExplorerTypeSettings expSetting : targetExplorerTypes) { descKeys.put(expSetting.getKey(), expSetting.getKey().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); String newIcon = expSetting.getIcon().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix); String newBigIcon = expSetting.getBigIconIfAvailable().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix); iconPaths.put(expSetting.getIcon(), newIcon); iconPaths.put(expSetting.getBigIconIfAvailable(), newBigIcon); expSetting.setName(expSetting.getName().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setKey(expSetting.getKey().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setIcon(expSetting.getIcon().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setBigIcon(expSetting.getBigIconIfAvailable().replaceFirst( m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setNewResourceUri(expSetting.getNewResourceUri().replaceFirst( m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setInfo(expSetting.getInfo().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); } } /** * Clones the export points of the module and adjusts its paths.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the source path part * @param targetPathPart the target path part */ private void cloneExportPoints( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart) { for (CmsExportPoint exp : targetModule.getExportPoints()) { if (exp.getUri().contains(sourceModule.getName())) { exp.setUri(exp.getUri().replaceAll(sourceModule.getName(), targetModule.getName())); } if (exp.getUri().contains(sourcePathPart)) { exp.setUri(exp.getUri().replaceAll(sourcePathPart, targetPathPart)); } } } /** * Clones/copies the resource types.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the source path part * @param targetPathPart the target path part * @param keys the map where to put in the messages of the resource type * * @return a map with source resource types as key and the taregt resource types as value */ private Map cloneResourceTypes( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart, Map keys) { Map resourceTypeMapping = new HashMap(); List targetResourceTypes = new ArrayList(); for (I_CmsResourceType sourceResType : targetModule.getResourceTypes()) { // get the class name attribute String className = sourceResType.getClassName(); // create the class instance I_CmsResourceType targetResType; try { if (className != null) { className = className.trim(); } int newId = -1; boolean exists = true; do { newId = new Random().nextInt((99999)) + 10000; try { OpenCms.getResourceManager().getResourceType(newId); } catch (CmsLoaderException e) { exists = false; } } while (exists); targetResType = (I_CmsResourceType)Class.forName(className).newInstance(); for (String mapping : sourceResType.getConfiguredMappings()) { targetResType.addMappingType(mapping); } targetResType.setAdjustLinksFolder(sourceResType.getAdjustLinksFolder()); if (targetResType instanceof A_CmsResourceType) { A_CmsResourceType concreteTargetResType = (A_CmsResourceType)targetResType; for (CmsProperty prop : sourceResType.getConfiguredDefaultProperties()) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(prop.getValue())) { prop.setStructureValue(prop.getStructureValue().replaceAll( sourceModule.getName(), targetModule.getName()).replaceAll(sourcePathPart, targetPathPart)); prop.setResourceValue(prop.getResourceValue().replaceAll( sourceModule.getName(), targetModule.getName()).replaceAll(sourcePathPart, targetPathPart)); } concreteTargetResType.addDefaultProperty(prop); } for (CmsConfigurationCopyResource conres : sourceResType.getConfiguredCopyResources()) { concreteTargetResType.addCopyResource( conres.getSource(), conres.getTarget(), conres.getTypeString()); } for (Map.Entry entry : sourceResType.getConfiguration().entrySet()) { targetResType.addConfigurationParameter( entry.getKey(), entry.getValue().replaceAll(sourceModule.getName(), targetModule.getName())); } targetResType.setAdditionalModuleResourceType(true); targetResType.initConfiguration( sourceResType.getTypeName().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix), newId + "", sourceResType.getClassName()); keys.put(sourceResType.getTypeName(), targetResType.getTypeName()); targetResourceTypes.add(targetResType); resourceTypeMapping.put(sourceResType, targetResType); } catch (Exception e) { // resource type is unknown, use dummy class to import the module resources targetResType = new CmsResourceTypeUnknown(); // write an error to the log LOG.error( Messages.get().getBundle().key( Messages.ERR_UNKNOWN_RESTYPE_CLASS_2, className, targetResType.getClass().getName()), e); } } targetModule.setResourceTypes(targetResourceTypes); return resourceTypeMapping; } /** * Creates the target folder for the module clone.

* * @param targetModule the target module * @param sourceClassesPath the source module class path * @param targetBaseClassesPath the 'classes' folder of the target module * * @throws CmsException if something goes wrong */ private void createTargetClassesFolder( CmsModule targetModule, String sourceClassesPath, String targetBaseClassesPath) throws CmsException { StringTokenizer tok = new StringTokenizer(targetModule.getName(), "."); int folderId = CmsResourceTypeFolder.getStaticTypeId(); String targetClassesPath = targetBaseClassesPath; while (tok.hasMoreTokens()) { String folder = tok.nextToken(); targetClassesPath += folder + "/"; if (!getCmsObject().existsResource(targetClassesPath)) { getCmsObject().createResource(targetClassesPath, folderId); } } // move exiting content into new classes sub-folder List propertyFiles = getCmsObject().readResources(sourceClassesPath, CmsResourceFilter.ALL); for (CmsResource res : propertyFiles) { if (!getCmsObject().existsResource(targetClassesPath + res.getName())) { getCmsObject().copyResource(res.getRootPath(), targetClassesPath + res.getName()); } } } /** * Deletes the temporarily copied classes files.

* * @param targetModulePath the target module path * @param sourcePathPart the path part of the source module * @param targetPathPart the target path part * * @throws CmsException if something goes wrong */ private void deleteSourceClassesFolder(String targetModulePath, String sourcePathPart, String targetPathPart) throws CmsException { String sourceFirstFolder = sourcePathPart.substring(0, sourcePathPart.indexOf('/')); String targetFirstFolder = sourcePathPart.substring(0, sourcePathPart.indexOf('/')); if (!sourceFirstFolder.equals(targetFirstFolder)) { getCmsObject().deleteResource( targetModulePath + PATH_CLASSES + sourceFirstFolder, CmsResource.DELETE_PRESERVE_SIBLINGS); return; } String[] targetPathParts = CmsStringUtil.splitAsArray(targetPathPart, '/'); } String[] sourcePathParts = CmsStringUtil.splitAsArray(sourcePathPart, '/'); int sourceLength = sourcePathParts.length; int diff = 0; for (int i = 0; i < targetPathParts.length; i++) { if (sourceLength >= i) { if (!targetPathParts[i].equals(sourcePathParts[i])) { diff = i + 1; } } } String topSourceClassesPath = targetModulePath + PATH_CLASSES + sourcePathPart.substring(0, sourcePathPart.indexOf('/')) + "/"; if (diff != 0) { topSourceClassesPath = targetModulePath + PATH_CLASSES; for (int i = 0; i < diff; i++) { topSourceClassesPath += sourcePathParts[i] + "/"; } } getCmsObject().deleteResource(topSourceClassesPath, CmsResource.DELETE_PRESERVE_SIBLINGS); } /** * Returns true if form imput is selected, checked, on or yes.

* * @param value the value to check * * @return true if form imput is selected, checked, on or yes */ private boolean isTrue(String value) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(value)) { if (Boolean.valueOf(value.toLowerCase()).booleanValue() || value.toLowerCase().equals("on") || value.toLowerCase().equals("yes") || value.toLowerCase().equals("checked") || value.toLowerCase().equals("selected")) { return true; } } return false; } /** * Locks the current resource.

* * @param cms the current CmsObject * @param cmsResource the resource to lock * * @return true if the given resource was locked was successfully * * @throws CmsException if some goes wrong */ private boolean lockResource(CmsObject cms, CmsResource cmsResource) throws CmsException { CmsLock lock = cms.getLock(cms.getSitePath(cmsResource)); // check the lock if ((lock != null) && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // prove is current lock from current user in current project return true; } else if ((lock != null) && !lock.isUnlocked() && !lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { // the resource is not locked by the current user, so can not lock it return false; } else if ((lock != null) && !lock.isUnlocked() && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && !lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // prove is current lock from current user but not in current project // file is locked by current user but not in current project // change the lock cms.changeLock(cms.getSitePath(cmsResource)); } else if ((lock != null) && lock.isUnlocked()) { // lock resource from current user in current project cms.lockResource(cms.getSitePath(cmsResource)); } lock = cms.getLock(cms.getSitePath(cmsResource)); if ((lock != null) && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && !lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // resource could not be locked return false; // resource is locked successfully return true; } /** * Renames the vfs resource bundle files within the target module according to the new module's name.

* * @param resources the vfs resource bundle files * @param targetModule the target module * @param name the package name of the source module * * @return a list of all xml vfs bundles within the given module * * @throws CmsException if something gows wrong */ private List renameXmlVfsBundles(List resources, CmsModule targetModule, String name) throws CmsException { for (CmsResource res : resources) { String newName = res.getName().replaceAll(name, targetModule.getName()); String targetRootPath = CmsResource.getFolderPath(res.getRootPath()) + newName; if (!getCmsObject().existsResource(targetRootPath)) { getCmsObject().moveResource(res.getRootPath(), targetRootPath); } } return resources; } /** * Replaces the referenced formatters within the new XSD files with the new formatter paths.

* * @param targetModule the target module * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replaceFormatterPaths(CmsModule targetModule) throws CmsException, UnsupportedEncodingException { CmsResource formatterSourceFolder = getCmsObject().readResource( "/system/modules/" + m_formatterSourceModule + "/"); CmsResource formatterTargetFolder = getCmsObject().readResource( "/system/modules/" + m_formatterTargetModule + "/"); for (I_CmsResourceType type : targetModule.getResourceTypes()) { String schemaPath = type.getConfiguration().get("schema"); CmsResource res = getCmsObject().readResource(schemaPath); CmsFile file = getCmsObject().readFile(res); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); content = content.replaceAll(formatterSourceFolder.getRootPath(), formatterTargetFolder.getRootPath()); file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } /** * Initializes a thread to find and replace all occurrence of the module's path.

* * @throws CmsException * @throws UnsupportedEncodingException */ private void replaceModuleName() throws CmsException, UnsupportedEncodingException { CmsResourceFilter filter = CmsResourceFilter.ALL.addRequireFile().addExcludeState(CmsResource.STATE_DELETED).addRequireTimerange().addRequireVisible(); List resources = getCmsObject().readResources( CmsWorkplace.VFS_PATH_MODULES + m_packageName + "/", filter); for (CmsResource resource : resources) { CmsFile file = getCmsObject().readFile(resource); byte[] contents = file.getContents(); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(contents, encoding); Matcher matcher = Pattern.compile(m_sourceModuleName).matcher(content); if (matcher.find()) { contents = matcher.replaceAll(m_packageName).getBytes(encoding); if (lockResource(getCmsObject(), file)) { file.setContents(contents); getCmsObject().writeFile(file); getCmsObject().unlockResource(getCmsObject().getSitePath(file)); } } } } /** * Replaces the paths within all the given resources and removes all UUIDs by an regex.

* * @param sourceModulePath the search path * @param targetModulePath the replace path * @param allModuleResources the resources * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replacePath(String sourceModulePath, String targetModulePath, List allModuleResources) throws CmsException, UnsupportedEncodingException { for (CmsResource resource : allModuleResources) { if (resource.isFile()) { CmsFile file = getCmsObject().readFile(resource); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String oldContent = new String(file.getContents(), encoding); String newContent = oldContent.replaceAll(sourceModulePath, targetModulePath); Matcher matcher = Pattern.compile(CmsUUID.UUID_REGEX).matcher(newContent); newContent = matcher.replaceAll(""); newContent = newContent.replaceAll("", ""); if (!oldContent.equals(newContent)) { file.setContents(newContent.getBytes(encoding)); if (!resource.getRootPath().startsWith(CmsWorkplace.VFS_PATH_SYSTEM)) { if (lockResource(getCmsObject(), resource)) { getCmsObject().writeFile(file); } } else { getCmsObject().writeFile(file); } } } } } /** * Replaces the messages for the given resources.

* * @param descKeys the replacement mapping * @param resources the resources to consult * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replacesMessages(Map descKeys, List resources) throws CmsException, UnsupportedEncodingException { for (CmsResource resource : resources) { CmsFile file = getCmsObject().readFile(resource); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); for (Map.Entry entry : descKeys.entrySet()) { content = content.replaceAll(entry.getKey(), entry.getValue()); } file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } } >>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2

Solution content
            }
        }
    }

/*
 * File   : $Source$
 * Date   : $Date$
 * Version: $Revision$
 *
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (C) 2002 - 2009 Alkacon Software (http://www.alkacon.com)
 *
 * This library 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 library 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.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.workplace.tools.modules;

import org.opencms.ade.configuration.CmsADEManager;
import org.opencms.configuration.CmsConfigurationCopyResource;
import org.opencms.configuration.Messages;
import org.opencms.db.CmsExportPoint;
import org.opencms.file.CmsFile;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.types.A_CmsResourceType;
import org.opencms.file.types.CmsResourceTypeFolder;
import org.opencms.file.types.CmsResourceTypeUnknown;
import org.opencms.file.types.CmsResourceTypeXmlContainerPage;
import org.opencms.file.types.I_CmsResourceType;
import org.opencms.i18n.CmsLocaleManager;
import org.opencms.i18n.CmsVfsBundleManager;
import org.opencms.jsp.CmsJspActionElement;
import org.opencms.loader.CmsLoaderException;
import org.opencms.lock.CmsLock;
import org.opencms.main.CmsException;
import org.opencms.main.CmsLog;
import org.opencms.main.I_CmsEventListener;
import org.opencms.main.OpenCms;
import org.opencms.module.CmsModule;
import org.opencms.report.CmsLogReport;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import org.opencms.workplace.CmsWorkplace;
import org.opencms.workplace.explorer.CmsExplorerTypeSettings;
import org.opencms.xml.CmsXmlException;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;

import org.apache.commons.logging.Log;

/**
 * Clones a module.

*/ public class CmsCloneModule extends CmsJspActionElement { /** The icon path. */ public static final String ICON_PATH = CmsWorkplace.VFS_PATH_RESOURCES + CmsWorkplace.RES_PATH_FILETYPES; /** Classes folder within the module. */ public static final String PATH_CLASSES = "classes/"; /** The log object for this class. */ private static final Log LOG = CmsLog.getLog(CmsCloneModule.class); /** The action class used for the clone. */ private String m_actionClass; /** The author's email used for the clone. */ private String m_authorEmail = "sales@alkacon.com"; /** The author's name used for the clone. */ private String m_authorName = "Alkacon Software GmbH"; /** Option to change the resource types (optional flag). */ private String m_changeResourceTypes; /** If 'true' resource types in all sites will be adjusted. */ private String m_changeResourceTypesEverywhere; /** Option to delete the source module after cloning (optional flag). */ private String m_deleteModule; /** The description used for the clone. */ private String m_description = "This module provides the template layout."; /** A module name where the formatters are located that are referenced within the XSDs of the module to clone. */ private String m_formatterSourceModule = "com.alkacon.bootstrap.formatters"; /** A module name where the formatters are located that should be referenced by the XSDs of the clone. */ private String m_formatterTargetModule; /** The module group used for the clone. */ private String m_group; /** The nice name used for the clone. */ private String m_niceName = "My new template module."; /** The new module name used for the clone. */ private String m_packageName = "my.company.template"; /** The name of the source module to be cloned. */ private String m_sourceModuleName = "com.alkacon.bootstrap.formatters"; /** The prefix that is used by the source module. */ private String m_sourceNamePrefix = "bs"; /** The prefix that is used by the target module. */ private String m_targetNamePrefix = "my"; /** * Public constructor.

*/ public CmsCloneModule() { // NOOP } /** * Constructor, with parameters.

* * @param context the JSP page context object * @param req the JSP request * @param res the JSP response */ public CmsCloneModule(PageContext context, HttpServletRequest req, HttpServletResponse res) { super(context, req, res); } /** * Bean constructor.

* * @param actionClass action class * @param authorEmail author email * @param authorName author name * @param changeResourceTypes change resource type flags * @param description module description * @param formatterSourceModule formatter source module * @param formatterTargetModule formatter target module * @param group module group * @param niceName nice name * @param packageName package/module name * @param sourceModuleName source module package/name * @param sourceNamePrefix source name prefix * @param targetNamePrefix source name prefix */ public CmsCloneModule( String actionClass, String authorEmail, String authorName, String changeResourceTypes, String description, String formatterSourceModule, String formatterTargetModule, String group, String niceName, String packageName, String sourceModuleName, String sourceNamePrefix, String targetNamePrefix) { super(); m_actionClass = actionClass; m_authorEmail = authorEmail; m_authorName = authorName; m_changeResourceTypes = changeResourceTypes; m_description = description; m_formatterSourceModule = formatterSourceModule; m_formatterTargetModule = formatterTargetModule; m_group = group; m_niceName = niceName; m_packageName = packageName; m_sourceModuleName = sourceModuleName; m_sourceNamePrefix = sourceNamePrefix; m_targetNamePrefix = targetNamePrefix; } /** * Executes the module clone and returns the new module.

* * @throws Throwable if anything goes wrong */ public void executeModuleClone() throws Throwable { CmsModule sourceModule = OpenCms.getModuleManager().getModule(m_sourceModuleName); // clone the module object CmsModule targetModule = (CmsModule)sourceModule.clone(); targetModule.setName(m_packageName); targetModule.setNiceName(m_niceName); targetModule.setDescription(m_description); targetModule.setAuthorEmail(m_authorEmail); targetModule.setAuthorName(m_authorName); targetModule.setGroup(m_group); targetModule.setActionClass(m_actionClass); try { // store the module paths String sourceModulePath = CmsWorkplace.VFS_PATH_MODULES + sourceModule.getName() + "/"; String targetModulePath = CmsWorkplace.VFS_PATH_MODULES + targetModule.getName() + "/"; // store the package name as path part String sourcePathPart = sourceModule.getName().replaceAll("\\.", "/"); String targetPathPart = targetModule.getName().replaceAll("\\.", "/"); // store the classes folder paths String sourceClassesPath = targetModulePath + PATH_CLASSES + sourcePathPart + "/"; String targetClassesPath = targetModulePath + PATH_CLASSES + targetPathPart + "/"; // copy the resources getCmsObject().copyResource(sourceModulePath, targetModulePath); // check if we have to create the classes folder if (getCmsObject().existsResource(sourceClassesPath)) { // in the source module a classes folder was defined, // now create all sub-folders for the package structure in the new module folder createTargetClassesFolder(targetModule, sourceClassesPath, targetModulePath + PATH_CLASSES); // delete the origin classes folder deleteSourceClassesFolder(targetModulePath, sourcePathPart, targetPathPart); } // TODO: clone module dependencies // adjust the export points cloneExportPoints(sourceModule, targetModule, sourcePathPart, targetPathPart); // adjust the resource type names and IDs Map descKeys = new HashMap(); Map resTypeMap = cloneResourceTypes( sourceModule, targetModule, sourcePathPart, targetPathPart, descKeys); // adjust the explorer type names and store referred icons and message keys Map iconPaths = new HashMap(); cloneExplorerTypes(targetModule, iconPaths, descKeys); // rename the icon file names cloneExplorerTypeIcons(iconPaths); // adjust the module resources adjustModuleResources(sourceModule, targetModule, sourcePathPart, targetPathPart, iconPaths); // search and replace the localization keys if (getCmsObject().existsResource(targetClassesPath)) { List props = getCmsObject().readResources( targetClassesPath, CmsResourceFilter.DEFAULT_FILES); replacesMessages(descKeys, props); } int type = OpenCms.getResourceManager().getResourceType(CmsVfsBundleManager.TYPE_XML_BUNDLE).getTypeId(); CmsResourceFilter filter = CmsResourceFilter.requireType(type); List resources = getCmsObject().readResources(targetModulePath, filter); replacesMessages(descKeys, resources); */ renameXmlVfsBundles(resources, targetModule, sourceModule.getName()); List allModuleResources = getCmsObject().readResources(targetModulePath, CmsResourceFilter.ALL); replacePath(sourceModulePath, targetModulePath, allModuleResources); // search and replace paths replaceModuleName(); // replace formatter paths if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_formatterTargetModule) && !targetModule.getResourceTypes().isEmpty()) { replaceFormatterPaths(targetModule); } adjustModuleConfig(targetModule, resTypeMap); // publish the new module for (String res : targetModule.getResources()) { OpenCms.getPublishManager().publishResource(getCmsObject(), res); OpenCms.getPublishManager().waitWhileRunning(); } // add the imported module to the module manager OpenCms.getModuleManager().addModule(getCmsObject(), targetModule); // reinitialize the resource manager with additional module resource types if necessary if (targetModule.getResourceTypes() != Collections.EMPTY_LIST) { OpenCms.getResourceManager().initialize(getCmsObject()); } // reinitialize the workplace manager with additional module explorer types if necessary if (targetModule.getExplorerTypes() != Collections.EMPTY_LIST) { OpenCms.getWorkplaceManager().addExplorerTypeSettings(targetModule); } // re-initialize the workplace OpenCms.getWorkplaceManager().initialize(getCmsObject()); // fire "clear caches" event to reload all cached resource bundles OpenCms.fireCmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, new HashMap()); // change resource types and schema locations if (isTrue(m_changeResourceTypes)) { changeResourceTypes(resTypeMap); } // adjust container pages CmsObject cms = OpenCms.initCmsObject(getCmsObject()); if (isTrue(m_changeResourceTypesEverywhere)) { cms.getRequestContext().setSiteRoot("/"); } CmsResourceFilter f = CmsResourceFilter.requireType(CmsResourceTypeXmlContainerPage.getContainerPageTypeId()); List allContainerPages = cms.readResources("/", f); replacePath(sourceModulePath, targetModulePath, allContainerPages); // delete the old module if (isTrue(m_deleteModule)) { OpenCms.getModuleManager().deleteModule( getCmsObject(), sourceModule.getName(), false, new CmsLogReport(getCmsObject().getRequestContext().getLocale(), CmsCloneModule.class)); } } catch (Throwable t) { LOG.error(t.getMessage(), t); throw t; } } /** * Returns the action class.

* * @return the action class */ public String getActionClass() { return m_actionClass; } /** * Returns a list of all module names.

* * @return a list of all module names */ public List getAllModuleNames() { List sortedModuleNames = new ArrayList(OpenCms.getModuleManager().getModuleNames()); java.util.Collections.sort(sortedModuleNames); return sortedModuleNames; } /** * Returns the author email.

* * @return the author email public String getAuthorEmail() { return m_authorEmail; } /** * Returns the author name.

* * @return the author name */ public String getAuthorName() { return m_authorName; } /** * Returns the change resource types flag as String.

* * @return the change resource types flag as String */ public String getChangeResourceTypes() { return m_changeResourceTypes; } /** * Returns the changeResourceTypesEverywhere.

* * @return the changeResourceTypesEverywhere */ public String getChangeResourceTypesEverywhere() { return m_changeResourceTypesEverywhere; } /** * Returns the delete module flag String.

* * @return the delete module flag as String */ public String getDeleteModule() { return m_deleteModule; } /** * Returns the description.

* * @return the description */ public String getDescription() { return m_description; } /** * Returns the formatter source module package/name.

* * @return the formatter source module package/name */ public String getFormatterSourceModule() { return m_formatterSourceModule; } /** * Returns the formatter target module package/name.

* * @return the formatter target module package/name */ public String getFormatterTargetModule() { return m_formatterTargetModule; } /** * Returns the group.

* * @return the group */ public String getGroup() { return m_group; } /** * Returns the nice name.

* * @return the nice name */ public String getNiceName() { return m_niceName; } /** * Returns the package/module name for the clone/target.

* * @return the package/module name for the clone/target */ public String getPackageName() { return m_packageName; } /** * Returns the source module package/name (the module to clone).

* * @return the source module package/name (the module to clone) */ public String getSourceModuleName() { return m_sourceModuleName; } /** * Returns the source name prefix.

* * @return the source name prefix */ public String getSourceNamePrefix() { return m_sourceNamePrefix; } /** * Returns the target name prefix.

* * @return the target name prefix */ public String getTargetNamePrefix() { return m_targetNamePrefix; } /** * Sets the action class.

* * @param actionClass the action class */ public void setActionClass(String actionClass) { m_actionClass = actionClass; } /** * Sets the author email.

* * @param authorEmail the author email to set */ public void setAuthorEmail(String authorEmail) { m_authorEmail = authorEmail; } /** * Sets the author name.

* * @param authorName the author name to set */ public void setAuthorName(String authorName) { m_authorName = authorName; } /** * Sets the change resource types flag.

* * @param changeResourceTypes the change resource types falg to set */ public void setChangeResourceTypes(String changeResourceTypes) { m_changeResourceTypes = changeResourceTypes; } /** * Sets the changeResourceTypesEverywhere.

* * @param changeResourceTypesEverywhere the changeResourceTypesEverywhere to set */ public void setChangeResourceTypesEverywhere(String changeResourceTypesEverywhere) { m_changeResourceTypesEverywhere = changeResourceTypesEverywhere; } /** * Sets the delete module flag.

* * @param deleteModule the delete module flag to set */ public void setDeleteModule(String deleteModule) { m_deleteModule = deleteModule; } /** * Sets the description.

* * @param description the description to set */ public void setDescription(String description) { m_description = description; } /** * Sets the formatter source module name.

* * @param formatterSourceModule the formatter source module name to set */ public void setFormatterSourceModule(String formatterSourceModule) { m_formatterSourceModule = formatterSourceModule; } /** * Sets the formatter target module name.

* * @param formatterTargetModule the formatter target module name to set */ public void setFormatterTargetModule(String formatterTargetModule) { m_formatterTargetModule = formatterTargetModule; } /** * Sets the group.

* * @param group the group to set */ public void setGroup(String group) { m_group = group; } /** * Sets the nice name.

* * @param niceName the nice name to set */ public void setNiceName(String niceName) { m_niceName = niceName; } /** * Sets the package name.

* * @param packageName the package name to set */ public void setPackageName(String packageName) { m_packageName = packageName; } /** * Sets the source module name.

* * @param sourceModuleName the source module name to set */ public void setSourceModuleName(String sourceModuleName) { m_sourceModuleName = sourceModuleName; } /** * Sets the source name prefix.

* * @param sourceNamePrefix the source name prefix to set */ public void setSourceNamePrefix(String sourceNamePrefix) { m_sourceNamePrefix = sourceNamePrefix; } /** * Sets the target name prefix.

* * @param targetNamePrefix the target name prefix to set */ public void setTargetNamePrefix(String targetNamePrefix) { m_targetNamePrefix = targetNamePrefix; } /** * Returns true if the module has been created successful.

* * @return true if the module has been created successful */ public boolean success() { return OpenCms.getModuleManager().getModule(m_packageName) != null; } /** * Adjusts the module configuration file.

* * @param targetModule the target moodule * @param resTypeMap the resource type mapping * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void adjustModuleConfig(CmsModule targetModule, Map resTypeMap) throws CmsException, UnsupportedEncodingException { String modPath = CmsWorkplace.VFS_PATH_MODULES + targetModule.getName() + "/" + CmsADEManager.CONFIG_FILE_NAME; CmsResource config = getCmsObject().readResource( modPath, CmsResourceFilter.requireType(OpenCms.getResourceManager().getResourceType(CmsADEManager.MODULE_CONFIG_TYPE).getTypeId())); CmsFile file = getCmsObject().readFile(config); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); for (Map.Entry mapping : resTypeMap.entrySet()) { content = content.replaceAll(mapping.getKey().getTypeName(), mapping.getValue().getTypeName()); file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } /** * Adjusts the paths of the module resources from the source path to the target path.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the path part of the source module * @param targetPathPart the path part of the target module * @param iconPaths the path where resource type icons are located */ private void adjustModuleResources( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart, Map iconPaths) { List newTargetResources = new ArrayList(); } List targetResources = targetModule.getResources(); for (String modRes : targetResources) { String nIcon = iconPaths.get(modRes.substring(modRes.lastIndexOf('/') + 1)); if (nIcon != null) { // the referenced resource is an resource type icon, add the new icon path newTargetResources.add(ICON_PATH + nIcon); } else if (modRes.contains(sourceModule.getName())) { // there is the name in it newTargetResources.add(modRes.replaceAll(sourceModule.getName(), targetModule.getName())); } else if (modRes.contains(sourcePathPart)) { // there is a path in it newTargetResources.add(modRes.replaceAll(sourcePathPart, targetPathPart)); } else { // there is whether the path nor the name in it newTargetResources.add(modRes); } } targetModule.setResources(newTargetResources); } /** * Changes the resource types and the schema locations of existing content.

* * @param resTypeMap a map containing the source types as keys and the target types as values * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void changeResourceTypes(Map resTypeMap) throws CmsException, UnsupportedEncodingException { CmsObject clone = OpenCms.initCmsObject(getCmsObject()); if (isTrue(m_changeResourceTypesEverywhere)) { clone.getRequestContext().setSiteRoot("/"); } for (Map.Entry mapping : resTypeMap.entrySet()) { CmsResourceFilter filter = CmsResourceFilter.requireType(mapping.getKey().getTypeId()); List resources = clone.readResources("/", filter); String sourceSchemaPath = mapping.getKey().getConfiguration().get("schema"); String targetSchemaPath = mapping.getValue().getConfiguration().get("schema"); for (CmsResource res : resources) { if (lockResource(getCmsObject(), res)) { CmsFile file = getCmsObject().readFile(res); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); content = content.replaceAll(sourceSchemaPath, targetSchemaPath); file.setContents(content.getBytes(encoding)); try { getCmsObject().writeFile(file); } catch (CmsXmlException e) { LOG.error(e.getMessage(), e); } res.setType(mapping.getValue().getTypeId()); getCmsObject().writeResource(res); } } } } /** * Copies the explorer type icons.

* * @param iconPaths the path to the location where the icons are located * * @throws CmsException if something goes wrong */ private void cloneExplorerTypeIcons(Map iconPaths) throws CmsException { for (Map.Entry entry : iconPaths.entrySet()) { String source = ICON_PATH + entry.getKey(); String target = ICON_PATH + entry.getValue(); if (!getCmsObject().existsResource(target)) { getCmsObject().copyResource(source, target); } } } /** * Copies the explorer type definitions.

* * @param targetModule the target module * @param iconPaths the path to the location where the icons are located * @param descKeys a map that contains a mapping of the explorer type definitions messages */ } while (exists); private void cloneExplorerTypes(CmsModule targetModule, Map iconPaths, Map descKeys) { List targetExplorerTypes = targetModule.getExplorerTypes(); for (CmsExplorerTypeSettings expSetting : targetExplorerTypes) { descKeys.put(expSetting.getKey(), expSetting.getKey().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); String newIcon = expSetting.getIcon().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix); String newBigIcon = expSetting.getBigIconIfAvailable().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix); iconPaths.put(expSetting.getIcon(), newIcon); iconPaths.put(expSetting.getBigIconIfAvailable(), newBigIcon); expSetting.setName(expSetting.getName().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setKey(expSetting.getKey().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setIcon(expSetting.getIcon().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setBigIcon(expSetting.getBigIconIfAvailable().replaceFirst( m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setNewResourceUri(expSetting.getNewResourceUri().replaceFirst( m_sourceNamePrefix, m_targetNamePrefix)); expSetting.setInfo(expSetting.getInfo().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix)); } } /** * Clones the export points of the module and adjusts its paths.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the source path part * @param targetPathPart the target path part */ private void cloneExportPoints( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart) { for (CmsExportPoint exp : targetModule.getExportPoints()) { if (exp.getUri().contains(sourceModule.getName())) { exp.setUri(exp.getUri().replaceAll(sourceModule.getName(), targetModule.getName())); } if (exp.getUri().contains(sourcePathPart)) { exp.setUri(exp.getUri().replaceAll(sourcePathPart, targetPathPart)); } } } /** * Clones/copies the resource types.

* * @param sourceModule the source module * @param targetModule the target module * @param sourcePathPart the source path part * @param targetPathPart the target path part * @param keys the map where to put in the messages of the resource type * * @return a map with source resource types as key and the taregt resource types as value */ private Map cloneResourceTypes( CmsModule sourceModule, CmsModule targetModule, String sourcePathPart, String targetPathPart, Map keys) { Map resourceTypeMapping = new HashMap(); List targetResourceTypes = new ArrayList(); for (I_CmsResourceType sourceResType : targetModule.getResourceTypes()) { // get the class name attribute String className = sourceResType.getClassName(); // create the class instance I_CmsResourceType targetResType; try { if (className != null) { className = className.trim(); } int newId = -1; boolean exists = true; do { newId = new Random().nextInt((99999)) + 10000; try { OpenCms.getResourceManager().getResourceType(newId); } catch (CmsLoaderException e) { exists = false; targetResType = (I_CmsResourceType)Class.forName(className).newInstance(); for (String mapping : sourceResType.getConfiguredMappings()) { targetResType.addMappingType(mapping); } targetResType.setAdjustLinksFolder(sourceResType.getAdjustLinksFolder()); if (targetResType instanceof A_CmsResourceType) { A_CmsResourceType concreteTargetResType = (A_CmsResourceType)targetResType; for (CmsProperty prop : sourceResType.getConfiguredDefaultProperties()) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(prop.getValue())) { prop.setStructureValue(prop.getStructureValue().replaceAll( sourceModule.getName(), targetModule.getName()).replaceAll(sourcePathPart, targetPathPart)); prop.setResourceValue(prop.getResourceValue().replaceAll( sourceModule.getName(), targetModule.getName()).replaceAll(sourcePathPart, targetPathPart)); } concreteTargetResType.addDefaultProperty(prop); } for (CmsConfigurationCopyResource conres : sourceResType.getConfiguredCopyResources()) { concreteTargetResType.addCopyResource( conres.getSource(), conres.getTarget(), conres.getTypeString()); } } for (Map.Entry entry : sourceResType.getConfiguration().entrySet()) { targetResType.addConfigurationParameter( entry.getKey(), entry.getValue().replaceAll(sourceModule.getName(), targetModule.getName())); } targetResType.setAdditionalModuleResourceType(true); targetResType.initConfiguration( sourceResType.getTypeName().replaceFirst(m_sourceNamePrefix, m_targetNamePrefix), newId + "", sourceResType.getClassName()); keys.put(sourceResType.getTypeName(), targetResType.getTypeName()); targetResourceTypes.add(targetResType); resourceTypeMapping.put(sourceResType, targetResType); } catch (Exception e) { // resource type is unknown, use dummy class to import the module resources targetResType = new CmsResourceTypeUnknown(); // write an error to the log LOG.error( Messages.get().getBundle().key( Messages.ERR_UNKNOWN_RESTYPE_CLASS_2, className, targetResType.getClass().getName()), e); } } targetModule.setResourceTypes(targetResourceTypes); return resourceTypeMapping; } /** * Creates the target folder for the module clone.

* * @param targetModule the target module * @param sourceClassesPath the source module class path * @param targetBaseClassesPath the 'classes' folder of the target module * * @throws CmsException if something goes wrong */ private void createTargetClassesFolder( CmsModule targetModule, String sourceClassesPath, String targetBaseClassesPath) throws CmsException { StringTokenizer tok = new StringTokenizer(targetModule.getName(), "."); int folderId = CmsResourceTypeFolder.getStaticTypeId(); String targetClassesPath = targetBaseClassesPath; while (tok.hasMoreTokens()) { String folder = tok.nextToken(); targetClassesPath += folder + "/"; if (!getCmsObject().existsResource(targetClassesPath)) { getCmsObject().createResource(targetClassesPath, folderId); // move exiting content into new classes sub-folder List propertyFiles = getCmsObject().readResources(sourceClassesPath, CmsResourceFilter.ALL); for (CmsResource res : propertyFiles) { if (!getCmsObject().existsResource(targetClassesPath + res.getName())) { getCmsObject().copyResource(res.getRootPath(), targetClassesPath + res.getName()); } } } /** * Deletes the temporarily copied classes files.

* * @param targetModulePath the target module path * @param sourcePathPart the path part of the source module * @param targetPathPart the target path part * * @throws CmsException if something goes wrong */ private void deleteSourceClassesFolder(String targetModulePath, String sourcePathPart, String targetPathPart) throws CmsException { String sourceFirstFolder = sourcePathPart.substring(0, sourcePathPart.indexOf('/')); String targetFirstFolder = sourcePathPart.substring(0, sourcePathPart.indexOf('/')); if (!sourceFirstFolder.equals(targetFirstFolder)) { getCmsObject().deleteResource( targetModulePath + PATH_CLASSES + sourceFirstFolder, CmsResource.DELETE_PRESERVE_SIBLINGS); return; } String[] targetPathParts = CmsStringUtil.splitAsArray(targetPathPart, '/'); String[] sourcePathParts = CmsStringUtil.splitAsArray(sourcePathPart, '/'); int sourceLength = sourcePathParts.length; int diff = 0; for (int i = 0; i < targetPathParts.length; i++) { if (sourceLength >= i) { if (!targetPathParts[i].equals(sourcePathParts[i])) { diff = i + 1; } } } String topSourceClassesPath = targetModulePath + PATH_CLASSES + sourcePathPart.substring(0, sourcePathPart.indexOf('/')) + "/"; if (diff != 0) { topSourceClassesPath = targetModulePath + PATH_CLASSES; for (int i = 0; i < diff; i++) { topSourceClassesPath += sourcePathParts[i] + "/"; } } getCmsObject().deleteResource(topSourceClassesPath, CmsResource.DELETE_PRESERVE_SIBLINGS); } /** * Returns true if form imput is selected, checked, on or yes.

* * @param value the value to check * * @return true if form imput is selected, checked, on or yes */ private boolean isTrue(String value) { if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(value)) { if (Boolean.valueOf(value.toLowerCase()).booleanValue() || value.toLowerCase().equals("on") || value.toLowerCase().equals("yes") || value.toLowerCase().equals("checked") || value.toLowerCase().equals("selected")) { return true; } } return false; } /** * Locks the current resource.

* * @param cms the current CmsObject * @param cmsResource the resource to lock * * @return true if the given resource was locked was successfully * * @throws CmsException if some goes wrong */ private boolean lockResource(CmsObject cms, CmsResource cmsResource) throws CmsException { CmsLock lock = cms.getLock(cms.getSitePath(cmsResource)); // check the lock if ((lock != null) && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // prove is current lock from current user in current project return true; } else if ((lock != null) && !lock.isUnlocked() && !lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { // the resource is not locked by the current user, so can not lock it return false; } else if ((lock != null) && !lock.isUnlocked() && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && !lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // prove is current lock from current user but not in current project // file is locked by current user but not in current project // change the lock cms.changeLock(cms.getSitePath(cmsResource)); } else if ((lock != null) && lock.isUnlocked()) { // lock resource from current user in current project cms.lockResource(cms.getSitePath(cmsResource)); } lock = cms.getLock(cms.getSitePath(cmsResource)); if ((lock != null) && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) && !lock.isOwnedInProjectBy( cms.getRequestContext().getCurrentUser(), cms.getRequestContext().getCurrentProject())) { // resource could not be locked return false; } // resource is locked successfully return true; } /** * Renames the vfs resource bundle files within the target module according to the new module's name.

* * @param resources the vfs resource bundle files * @param targetModule the target module * @param name the package name of the source module * * @return a list of all xml vfs bundles within the given module * * @throws CmsException if something gows wrong */ private List renameXmlVfsBundles(List resources, CmsModule targetModule, String name) throws CmsException { for (CmsResource res : resources) { String newName = res.getName().replaceAll(name, targetModule.getName()); String targetRootPath = CmsResource.getFolderPath(res.getRootPath()) + newName; if (!getCmsObject().existsResource(targetRootPath)) { getCmsObject().moveResource(res.getRootPath(), targetRootPath); } } return resources; } /** * Replaces the referenced formatters within the new XSD files with the new formatter paths.

* * @param targetModule the target module * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replaceFormatterPaths(CmsModule targetModule) throws CmsException, UnsupportedEncodingException { CmsResource formatterSourceFolder = getCmsObject().readResource( "/system/modules/" + m_formatterSourceModule + "/"); CmsResource formatterTargetFolder = getCmsObject().readResource( "/system/modules/" + m_formatterTargetModule + "/"); for (I_CmsResourceType type : targetModule.getResourceTypes()) { String schemaPath = type.getConfiguration().get("schema"); CmsResource res = getCmsObject().readResource(schemaPath); CmsFile file = getCmsObject().readFile(res); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); content = content.replaceAll(formatterSourceFolder.getRootPath(), formatterTargetFolder.getRootPath()); file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } } /** * Initializes a thread to find and replace all occurrence of the module's path.

* * @throws CmsException * @throws UnsupportedEncodingException */ private void replaceModuleName() throws CmsException, UnsupportedEncodingException { CmsResourceFilter filter = CmsResourceFilter.ALL.addRequireFile().addExcludeState(CmsResource.STATE_DELETED).addRequireTimerange().addRequireVisible(); List resources = getCmsObject().readResources( CmsWorkplace.VFS_PATH_MODULES + m_packageName + "/", filter); for (CmsResource resource : resources) { CmsFile file = getCmsObject().readFile(resource); byte[] contents = file.getContents(); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(contents, encoding); Matcher matcher = Pattern.compile(m_sourceModuleName).matcher(content); if (matcher.find()) { contents = matcher.replaceAll(m_packageName).getBytes(encoding); if (lockResource(getCmsObject(), file)) { file.setContents(contents); getCmsObject().writeFile(file); } } } } /** * Replaces the paths within all the given resources and removes all UUIDs by an regex.

* * @param sourceModulePath the search path * @param targetModulePath the replace path * @param allModuleResources the resources * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replacePath(String sourceModulePath, String targetModulePath, List allModuleResources) throws CmsException, UnsupportedEncodingException { for (CmsResource resource : allModuleResources) { if (resource.isFile()) { CmsFile file = getCmsObject().readFile(resource); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String oldContent = new String(file.getContents(), encoding); String newContent = oldContent.replaceAll(sourceModulePath, targetModulePath); Matcher matcher = Pattern.compile(CmsUUID.UUID_REGEX).matcher(newContent); newContent = matcher.replaceAll(""); newContent = newContent.replaceAll("", ""); if (!oldContent.equals(newContent)) { file.setContents(newContent.getBytes(encoding)); if (!resource.getRootPath().startsWith(CmsWorkplace.VFS_PATH_SYSTEM)) { if (lockResource(getCmsObject(), resource)) { getCmsObject().writeFile(file); } } else { getCmsObject().writeFile(file); } } } } } /** * Replaces the messages for the given resources.

* * @param descKeys the replacement mapping * @param resources the resources to consult * * @throws CmsException if something goes wrong * @throws UnsupportedEncodingException if the file content could not be read with the determined encoding */ private void replacesMessages(Map descKeys, List resources) throws CmsException, UnsupportedEncodingException { for (CmsResource resource : resources) { CmsFile file = getCmsObject().readFile(resource); String encoding = CmsLocaleManager.getResourceEncoding(getCmsObject(), file); String content = new String(file.getContents(), encoding); for (Map.Entry entry : descKeys.entrySet()) { content = content.replaceAll(entry.getKey(), entry.getValue()); } file.setContents(content.getBytes(encoding)); getCmsObject().writeFile(file); } }

File
CmsCloneModule.java
Developer's decision
Version 1
Kind of conflict
Class declaration
Comment
Import
Package declaration
Chunk
Conflicting content
    @Override
    public CmsSolrQuery clone() {

<<<<<<< HEAD
        CmsSolrQuery sq = new CmsSolrQuery(null, CmsRequestUtil.createParameterMap(toString()));
        sq.m_ignoreExpiration = m_ignoreExpiration;
        return sq;
=======
        return new CmsSolrQuery(null, CmsRequestUtil.createParameterMap(toString()));
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2
    }

    /**
Solution content
    }
        sq.m_ignoreExpiration = m_ignoreExpiration;
    @Override
    public CmsSolrQuery clone() {

        CmsSolrQuery sq = new CmsSolrQuery(null, CmsRequestUtil.createParameterMap(toString()));
        return sq;

    /**
File
CmsSolrQuery.java
Developer's decision
Version 1
Kind of conflict
Attribute
Method invocation
Return statement
Variable
Chunk
Conflicting content
    }

    /**
<<<<<<< HEAD
     * Removes the expiration flag.
     */
    public void removeExpiration() {

        if (getFilterQueries() != null) {
            for (String fq : getFilterQueries()) {
                if (fq.startsWith(CmsSearchField.FIELD_DATE_EXPIRED + ":")
                    || fq.startsWith(CmsSearchField.FIELD_DATE_RELEASED + ":")) {
                    removeFilterQuery(fq);
                }
            }
        }
        m_ignoreExpiration = true;
    }

    /**
=======
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2
     * Sets the categories only if not set in the query parameters.

* * @param categories the categories to set

Solution content
    }

    /**
    <<<<<<< HEAD
     * Removes the expiration flag.
     */
    public void removeExpiration() {

        if (getFilterQueries() != null) {
            for (String fq : getFilterQueries()) {
                if (fq.startsWith(CmsSearchField.FIELD_DATE_EXPIRED + ":")
                    || fq.startsWith(CmsSearchField.FIELD_DATE_RELEASED + ":")) {
                    removeFilterQuery(fq);
                }
            }
        }
        m_ignoreExpiration = true;
    }

    /**
    =======
    >>>>>>> branch_9_future
     * Sets the categories only if not set in the query parameters.

* * @param categories the categories to set

File
CmsSolrQuery.java
Developer's decision
Manual
Kind of conflict
Comment
Method declaration
Chunk
Conflicting content
     * Creates a filter query on the given field name.

* * Creates and adds a filter query.

<<<<<<< HEAD * * @param fieldName the field name to create a filter query on * @param vals the values that should match for the given field * @param all true to combine the given values with 'AND', false for 'OR' * @param useQuotes true to surround the given values with double quotes, false otherwise * ======= * * @param fieldName the field name to create a filter query on * @param vals the values that should match for the given field * @param all true to combine the given values with 'AND', false for 'OR' * @param useQuotes true to surround the given values with double quotes, false otherwise * >>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2 * @return a filter query String e.g. fq=fieldname:val1 */ private String createFilterQuery(String fieldName, List vals, boolean all, boolean useQuotes) {

Solution content
     * Creates a filter query on the given field name.

* * Creates and adds a filter query.

<<<<<<< HEAD * * @param fieldName the field name to create a filter query on * @param vals the values that should match for the given field * @param all true to combine the given values with 'AND', false for 'OR' * @param useQuotes true to surround the given values with double quotes, false otherwise * * @return a filter query String e.g. fq=fieldname:val1 */ private String createFilterQuery(String fieldName, List vals, boolean all, boolean useQuotes) {

File
CmsSolrQuery.java
Developer's decision
Manual
Kind of conflict
Comment
Chunk
Conflicting content
        assertEquals(defaultQuery, query.toString());

        // test creating default query by String
<<<<<<< HEAD
        String defaultContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/sites/default/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]";
=======
        String defaultContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/sites/default/\"";
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2
        query = new CmsSolrQuery(getCmsObject(), null);
        assertEquals(defaultContextQuery, query.toString());
Solution content
        assertEquals(defaultQuery, query.toString());

        // test creating default query by String
        String defaultContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/sites/default/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]";
        query = new CmsSolrQuery(getCmsObject(), null);
        assertEquals(defaultContextQuery, query.toString());
File
TestSolrSearch.java
Developer's decision
Version 1
Kind of conflict
Variable
Chunk
Conflicting content
     */
    public void testQueryParameterStrength() throws Throwable {

<<<<<<< HEAD
        String defaultContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/sites/default/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]";
        String modifiedContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]";
=======
        String defaultContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/sites/default/\"";
        String modifiedContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/\"";
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2

        // members should be stronger than request context
        CmsSolrQuery query = new CmsSolrQuery(getCmsObject(), null);
Solution content
     */
    public void testQueryParameterStrength() throws Throwable {

        String defaultContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/sites/default/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]";
        String modifiedContextQuery = "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]";

        // members should be stronger than request context
        CmsSolrQuery query = new CmsSolrQuery(getCmsObject(), null);
File
TestSolrSearch.java
Developer's decision
Version 1
Kind of conflict
Variable
Chunk
Conflicting content
        query.setSearchRoots("/");
        assertEquals(
            modifiedContextQuery,
<<<<<<< HEAD
            "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]");
        query.setLocales(Locale.GERMAN, Locale.FRENCH, Locale.ENGLISH);
        query.setLocales(Locale.GERMAN, Locale.FRENCH);
        assertEquals(
            "q=*:*&fl=*,score&qt=edismax&rows=10&fq=expired:[NOW TO *]&fq=released:[* TO NOW]&fq=parent-folders:\"/\"&fq=con_locales:(de OR fr)",
=======
            "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/\"");
        query.setLocales(Locale.GERMAN, Locale.FRENCH, Locale.ENGLISH);
        query.setLocales(Locale.GERMAN, Locale.FRENCH);
        assertEquals(
            "q=*:*&fl=*,score&qt=edismax&rows=10&fq=parent-folders:\"/\"&fq=con_locales:(de OR fr)",
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2
            query.toString());

        // parameters should be stronger than request context
Solution content
        query.setSearchRoots("/");
        assertEquals(
            modifiedContextQuery,

            "q=*:*&fl=*,score&qt=edismax&rows=10&fq=con_locales:en&fq=parent-folders:\"/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]");
        query.setLocales(Locale.GERMAN, Locale.FRENCH, Locale.ENGLISH);
        query.setLocales(Locale.GERMAN, Locale.FRENCH);
        assertEquals(
            "q=*:*&fl=*,score&qt=edismax&rows=10&fq=expired:[NOW TO *]&fq=released:[* TO NOW]&fq=parent-folders:\"/\"&fq=con_locales:(de OR fr)",
            query.toString());

        // parameters should be stronger than request context
File
TestSolrSearch.java
Developer's decision
Version 1
Kind of conflict
Method invocation
Chunk
Conflicting content
        // parameters should be stronger than request context and members
        query = new CmsSolrQuery(
            getCmsObject(),
<<<<<<< HEAD
            CmsRequestUtil.createParameterMap("q=test&fq=parent-folders:\"/\"&fq=con_locales:fr&fl=content_fr&rows=50&qt=edismax&fq=type:v8news&fq=expired:[NOW TO *]&fq=released:[* TO NOW]"));
=======
            CmsRequestUtil.createParameterMap("q=test&fq=parent-folders:\"/\"&fq=con_locales:fr&fl=content_fr&rows=50&qt=edismax&fq=type:v8news"));
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2
        query.setText("test");
        query.setTextSearchFields("pla");
        query.setLocales(Locale.GERMAN);
Solution content
        // parameters should be stronger than request context and members
        query = new CmsSolrQuery(
            getCmsObject(),
            CmsRequestUtil.createParameterMap("q=test&fq=parent-folders:\"/\"&fq=con_locales:fr&fl=content_fr&rows=50&qt=edismax&fq=type:v8news&fq=expired:[NOW TO *]&fq=released:[* TO NOW]"));
        query.setText("test");
        query.setTextSearchFields("pla");
        query.setLocales(Locale.GERMAN);
File
TestSolrSearch.java
Developer's decision
Version 1
Kind of conflict
Method invocation
Chunk
Conflicting content
        query.setRows(new Integer(1000));
        query.setRequestHandler("lucene");
        query.setResourceTypes("article");
<<<<<<< HEAD
        String ex = "q={!q.op=OR qf=text_en}test&fl=pla,plub&qt=lucene&rows=1000&fq=parent-folders:\"/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]&fq=con_locales:de&fq=type:article";
=======
        String ex = "q={!q.op=OR qf=text_en}test&fl=pla,plub&qt=lucene&rows=1000&fq=parent-folders:\"/\"&fq=con_locales:de&fq=type:article";
>>>>>>> 74216aa2c97726b89df5a6d2f943a0bb9f721be2
        assertEquals(ex, query.toString());

        assertEquals("article", CmsSolrQuery.getResourceType(query.getFilterQueries()));
Solution content
        query.setRows(new Integer(1000));
        query.setRequestHandler("lucene");
        query.setResourceTypes("article");
        String ex = "q={!q.op=OR qf=text_en}test&fl=pla,plub&qt=lucene&rows=1000&fq=parent-folders:\"/\"&fq=expired:[NOW TO *]&fq=released:[* TO NOW]&fq=con_locales:de&fq=type:article";
        assertEquals(ex, query.toString());
        assertEquals("article", CmsSolrQuery.getResourceType(query.getFilterQueries()));
File
TestSolrSearch.java
Developer's decision
Version 1
Kind of conflict
Variable