0001: /*
0002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/importexport/CmsImportVersion2.java,v $
0003: * Date : $Date: 2008-02-27 12:05:48 $
0004: * Version: $Revision: 1.118 $
0005: *
0006: * This library is part of OpenCms -
0007: * the Open Source Content Management System
0008: *
0009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
0010: *
0011: * This library is free software; you can redistribute it and/or
0012: * modify it under the terms of the GNU Lesser General Public
0013: * License as published by the Free Software Foundation; either
0014: * version 2.1 of the License, or (at your option) any later version.
0015: *
0016: * This library is distributed in the hope that it will be useful,
0017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0019: * Lesser General Public License for more details.
0020: *
0021: * For further information about Alkacon Software GmbH, please see the
0022: * company website: http://www.alkacon.com
0023: *
0024: * For further information about OpenCms, please see the
0025: * project website: http://www.opencms.org
0026: *
0027: * You should have received a copy of the GNU Lesser General Public
0028: * License along with this library; if not, write to the Free Software
0029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0030: */
0031:
0032: package org.opencms.importexport;
0033:
0034: import org.opencms.file.CmsFile;
0035: import org.opencms.file.CmsFolder;
0036: import org.opencms.file.CmsObject;
0037: import org.opencms.file.CmsProperty;
0038: import org.opencms.file.CmsPropertyDefinition;
0039: import org.opencms.file.CmsResource;
0040: import org.opencms.file.CmsResourceFilter;
0041: import org.opencms.file.types.CmsResourceTypeFolder;
0042: import org.opencms.file.types.CmsResourceTypePlain;
0043: import org.opencms.file.types.CmsResourceTypeXmlPage;
0044: import org.opencms.file.types.I_CmsResourceType;
0045: import org.opencms.i18n.CmsMessageContainer;
0046: import org.opencms.lock.CmsLockException;
0047: import org.opencms.main.CmsException;
0048: import org.opencms.main.CmsLog;
0049: import org.opencms.main.OpenCms;
0050: import org.opencms.report.I_CmsReport;
0051: import org.opencms.security.CmsRole;
0052: import org.opencms.security.I_CmsPasswordHandler;
0053: import org.opencms.util.CmsStringUtil;
0054: import org.opencms.util.CmsUUID;
0055: import org.opencms.xml.CmsXmlException;
0056: import org.opencms.xml.CmsXmlUtils;
0057: import org.opencms.xml.page.CmsXmlPage;
0058:
0059: import java.io.File;
0060: import java.io.IOException;
0061: import java.util.ArrayList;
0062: import java.util.Collections;
0063: import java.util.HashMap;
0064: import java.util.Iterator;
0065: import java.util.List;
0066: import java.util.Map;
0067: import java.util.StringTokenizer;
0068: import java.util.zip.ZipFile;
0069:
0070: import org.apache.commons.logging.Log;
0071:
0072: import org.dom4j.Document;
0073: import org.dom4j.Element;
0074: import org.dom4j.Node;
0075:
0076: /**
0077: * Implementation of the OpenCms Import Interface ({@link org.opencms.importexport.I_CmsImport}) for
0078: * the import version 2.<p>
0079: *
0080: * This import format was used in OpenCms 5.0.0 - 5.1.2.<p>
0081: *
0082: * @author Michael Emmerich
0083: * @author Thomas Weckert
0084: *
0085: * @version $Revision: 1.118 $
0086: *
0087: * @since 6.0.0
0088: *
0089: * @see org.opencms.importexport.A_CmsImport
0090: *
0091: * @deprecated this import class is no longer in use and should only be used to import old export files
0092: */
0093: public class CmsImportVersion2 extends A_CmsImport {
0094:
0095: /** Parameter for content body folder. */
0096: public static final String VFS_PATH_BODIES = "/system/bodies/";
0097:
0098: /** The runtime property name for old webapp names. */
0099: private static final String COMPATIBILITY_WEBAPPNAMES = "compatibility.support.webAppNames";
0100:
0101: /** The version number of this import implementation. */
0102: private static final int IMPORT_VERSION = 2;
0103:
0104: /** The log object for this class. */
0105: private static final Log LOG = CmsLog
0106: .getLog(CmsImportVersion2.class);
0107:
0108: /** Web application names for conversion support. */
0109: protected List m_webAppNames;
0110:
0111: /** Old webapp URL for import conversion. */
0112: protected String m_webappUrl;
0113:
0114: /** folder storage for page file and body conversion. */
0115: private List m_folderStorage;
0116:
0117: /** page file storage for page file and body co.version. */
0118: private List m_pageStorage;
0119:
0120: /**
0121: * Translates directory Strings from OpenCms 4.x structure to new 5.0 structure.<p>
0122: *
0123: * @param content the filecontent
0124: * @param rules the translation rules
0125: * @return String the manipulated file content
0126: */
0127: public static String setDirectories(String content, String[] rules) {
0128:
0129: // get translation rules
0130: for (int i = 0; i < rules.length; i++) {
0131: String actRule = rules[i];
0132: // cut String "/default/vfs/" from rule
0133: actRule = CmsStringUtil.substitute(actRule, "/default/vfs",
0134: "");
0135: // divide rule into search and replace parts and delete regular expressions
0136: StringTokenizer ruleT = new StringTokenizer(actRule, "#");
0137: ruleT.nextToken();
0138: String search = ruleT.nextToken();
0139: int pos = search.lastIndexOf("(.*)");
0140: if (pos >= 0) {
0141: search = search.substring(0, pos);
0142: }
0143: String replace = ruleT.nextToken();
0144: if (pos >= 0) {
0145: replace = replace.substring(0, replace
0146: .lastIndexOf("$1"));
0147: }
0148: // scan content for paths if the replace String is not present
0149: if ((content.indexOf(replace) == -1)
0150: && (content.indexOf(search) != -1)) {
0151: // ensure subdirectories of the same name are not replaced
0152: search = "([}>\"'\\[]\\s*)" + search;
0153: replace = "$1" + replace;
0154: content = CmsStringUtil.substitutePerl(content, search,
0155: replace, "g");
0156: }
0157: }
0158: return content;
0159: }
0160:
0161: /**
0162: * @see org.opencms.importexport.I_CmsImport#getVersion()
0163: * @return the version number of this import implementation
0164: */
0165: public int getVersion() {
0166:
0167: return CmsImportVersion2.IMPORT_VERSION;
0168: }
0169:
0170: /**
0171: * @see org.opencms.importexport.I_CmsImport#importData(CmsObject, I_CmsReport, CmsImportParameters)
0172: */
0173: public void importData(CmsObject cms, I_CmsReport report,
0174: CmsImportParameters params)
0175: throws CmsImportExportException, CmsXmlException {
0176:
0177: // initialize the import
0178: initialize();
0179: m_cms = cms;
0180: m_importPath = params.getDestinationPath();
0181: m_report = report;
0182:
0183: m_folderStorage = new ArrayList();
0184: m_pageStorage = new ArrayList();
0185: m_linkStorage = new HashMap();
0186: m_linkPropertyStorage = new HashMap();
0187:
0188: if (OpenCms.getRunLevel() >= OpenCms.RUNLEVEL_3_SHELL_ACCESS) {
0189: OpenCms.getMemoryMonitor().register(
0190: this .getClass().getName() + ".m_folderStorage",
0191: m_folderStorage);
0192: OpenCms.getMemoryMonitor().register(
0193: this .getClass().getName() + ".m_pageStorage",
0194: m_pageStorage);
0195: OpenCms.getMemoryMonitor().register(
0196: this .getClass().getName() + ".m_linkStorage",
0197: m_linkStorage);
0198: OpenCms.getMemoryMonitor().register(
0199: this .getClass().getName()
0200: + ".m_linkPropertyStorage",
0201: m_linkPropertyStorage);
0202: }
0203:
0204: CmsImportHelper helper = new CmsImportHelper(params);
0205: try {
0206: helper.openFile();
0207: m_importResource = helper.getFolder();
0208: m_importZip = helper.getZipFile();
0209: m_docXml = CmsXmlUtils
0210: .unmarshalHelper(
0211: helper
0212: .getFileBytes(CmsImportExportManager.EXPORT_MANIFEST),
0213: null);
0214: // first import the user information
0215: if (OpenCms.getRoleManager().hasRole(m_cms,
0216: CmsRole.ACCOUNT_MANAGER)) {
0217: importGroups();
0218: importUsers();
0219: }
0220: // now import the VFS resources
0221: importAllResources();
0222: convertPointerToSiblings();
0223: } catch (IOException e) {
0224: CmsMessageContainer msg = Messages.get().container(
0225: Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1,
0226: CmsImportExportManager.EXPORT_MANIFEST);
0227: if (LOG.isErrorEnabled()) {
0228: LOG.error(msg.key(), e);
0229: }
0230: throw new CmsImportExportException(msg, e);
0231: } finally {
0232: helper.closeFile();
0233: cleanUp();
0234: }
0235: }
0236:
0237: /**
0238: * @see org.opencms.importexport.I_CmsImport#importResources(org.opencms.file.CmsObject, java.lang.String, org.opencms.report.I_CmsReport, java.io.File, java.util.zip.ZipFile, org.dom4j.Document)
0239: *
0240: * @deprecated use {@link #importData(CmsObject, I_CmsReport, CmsImportParameters)} instead
0241: */
0242: public void importResources(CmsObject cms, String importPath,
0243: I_CmsReport report, File importResource, ZipFile importZip,
0244: Document docXml) throws CmsImportExportException {
0245:
0246: CmsImportParameters params = new CmsImportParameters(
0247: importResource != null ? importResource
0248: .getAbsolutePath() : importZip.getName(),
0249: importPath, true);
0250:
0251: try {
0252: importData(cms, report, params);
0253: } catch (CmsXmlException e) {
0254: throw new CmsImportExportException(e.getMessageContainer(),
0255: e);
0256: }
0257: }
0258:
0259: /**
0260: * Cleans up member variables after the import is finished.<p>
0261: *
0262: * This is required since there is only one instance for
0263: * each import version that is kept in memory and reused.<p>
0264: */
0265: protected void cleanUp() {
0266:
0267: m_pageStorage = null;
0268: m_folderStorage = null;
0269: m_webAppNames = null;
0270: m_webappUrl = null;
0271: super .cleanUp();
0272: }
0273:
0274: /**
0275: * Performs all required pre-import steps.<p>
0276: *
0277: * The content is *NOT* changed in the implementation of this class.<p>
0278: *
0279: * @param source the source path of the resource
0280: * @param destination the destination path of the resource
0281: * @param content the content of the resource
0282: * @param resType the type of the resource
0283: * @return the (prepared) content of the resource
0284: */
0285: protected byte[] convertContent(String source, String destination,
0286: byte[] content, String resType) {
0287:
0288: // if the import is older than version 3, some additional conversions must be made
0289: if (getVersion() < 3) {
0290: if ("page".equals(resType)) {
0291: if (DEBUG > 0) {
0292: System.err.println("#########################");
0293: System.err.println("[" + this .getClass().getName()
0294: + ".convertContent()]: storing resource "
0295: + source + '.');
0296: }
0297: // if the imported resource is a page, store its path inside the VFS for later
0298: // integration with its body
0299: m_pageStorage.add(destination);
0300: } else if ("folder".equals(resType)) {
0301: // check if the imported resource is a folder. Folders created in the /system/bodies/ folder
0302: if (destination
0303: .startsWith(VFS_PATH_BODIES.substring(1))) {
0304: // must be removed since we do not use body files anymore.
0305: m_folderStorage.add(destination);
0306: }
0307: }
0308: }
0309:
0310: return content;
0311: }
0312:
0313: /**
0314: * Gets the encoding from the <?XML ...> tag if present.<p>
0315: *
0316: * @param content the file content
0317: * @return String the found encoding
0318: */
0319: protected String getEncoding(String content) {
0320:
0321: String encoding = content;
0322: int index = encoding.toLowerCase().indexOf("encoding=\"");
0323: // encoding attribute found, get the value
0324: if (index != -1) {
0325: encoding = encoding.substring(index + 10);
0326: index = encoding.indexOf("\"");
0327: if (index != -1) {
0328: encoding = encoding.substring(0, index);
0329: return encoding.toUpperCase();
0330: }
0331: }
0332: // no encoding attribute found
0333: return "";
0334: }
0335:
0336: /**
0337: * @see org.opencms.importexport.A_CmsImport#importUser(String, String, String, String, String, String, long, Map, List)
0338: */
0339: protected void importUser(String name, String flags,
0340: String password, String firstname, String lastname,
0341: String email, long dateCreated, Map userInfo,
0342: List userGroups) throws CmsImportExportException {
0343:
0344: boolean convert = false;
0345:
0346: Map config = OpenCms.getPasswordHandler().getConfiguration();
0347: if ((config != null)
0348: && config
0349: .containsKey(I_CmsPasswordHandler.CONVERT_DIGEST_ENCODING)) {
0350: convert = Boolean
0351: .valueOf(
0352: (String) config
0353: .get(I_CmsPasswordHandler.CONVERT_DIGEST_ENCODING))
0354: .booleanValue();
0355: }
0356:
0357: if (convert) {
0358: password = convertDigestEncoding(password);
0359: }
0360:
0361: super .importUser(name, flags, password, firstname, lastname,
0362: email, dateCreated, userInfo, userGroups);
0363: }
0364:
0365: /**
0366: * Initializes all member variables before the import is started.<p>
0367: *
0368: * This is required since there is only one instance for
0369: * each import version that is kept in memory and reused.<p>
0370: */
0371: protected void initialize() {
0372:
0373: m_convertToXmlPage = true;
0374: m_webAppNames = new ArrayList();
0375: super .initialize();
0376: }
0377:
0378: /**
0379: * Sets the right encoding and returns the result.<p>
0380: *
0381: * @param content the filecontent
0382: * @param encoding the encoding to use
0383: * @return modified content
0384: */
0385: protected String setEncoding(String content, String encoding) {
0386:
0387: if (content.toLowerCase().indexOf("<?xml") == -1) {
0388: return content;
0389: } else {
0390: // XML information present, replace encoding
0391: // set the encoding only if it does not exist
0392: String xmlTag = content.substring(0,
0393: content.indexOf(">") + 1);
0394: if (xmlTag.toLowerCase().indexOf("encoding") == -1) {
0395: content = content.substring(content.indexOf(">") + 1);
0396: content = "<?xml version=\"1.0\" encoding=\""
0397: + encoding + "\"?>" + content;
0398: }
0399: }
0400: return content;
0401: }
0402:
0403: /**
0404: * Returns the compatibility web app names.<p>
0405: *
0406: * @return the compatibility web app names
0407: */
0408: private List getCompatibilityWebAppNames() {
0409:
0410: List webAppNamesOri = new ArrayList();
0411:
0412: String configuredWebAppNames = (String) OpenCms
0413: .getRuntimeProperty(COMPATIBILITY_WEBAPPNAMES);
0414: if ((configuredWebAppNames != null)
0415: && (configuredWebAppNames.length() != 0)) {
0416: // split the comma separated list of web app names
0417: StringTokenizer tokenizer = new StringTokenizer(
0418: configuredWebAppNames, ",;");
0419: while (tokenizer.hasMoreTokens()) {
0420: webAppNamesOri.add(tokenizer.nextToken());
0421: }
0422: }
0423:
0424: List webAppNames = new ArrayList();
0425: for (int i = 0; i < webAppNamesOri.size(); i++) {
0426: // remove possible white space
0427: String name = ((String) webAppNamesOri.get(i)).trim();
0428: if (CmsStringUtil.isNotEmpty(name)) {
0429: webAppNames.add(name);
0430: if (LOG.isInfoEnabled()) {
0431: LOG
0432: .info(Messages
0433: .get()
0434: .getBundle()
0435: .key(
0436: Messages.INIT_IMPORTEXPORT_OLD_CONTEXT_PATH_2,
0437: Integer.toString((i + 1)),
0438: name));
0439: }
0440: }
0441: }
0442:
0443: String key = (webAppNames.size() > 0) ? Messages.INIT_IMPORTEXPORT_OLD_CONTEXT_SUPPORT_ENABLED_0
0444: : Messages.INIT_IMPORTEXPORT_OLD_CONTEXT_SUPPORT_DISABLED_0;
0445: if (LOG.isInfoEnabled()) {
0446: LOG.info(Messages.get().getBundle().key(key));
0447: }
0448:
0449: // add current context to webapp names list
0450: if (!webAppNames.contains(OpenCms.getSystemInfo()
0451: .getOpenCmsContext())) {
0452: webAppNames
0453: .add(OpenCms.getSystemInfo().getOpenCmsContext());
0454: }
0455:
0456: return webAppNames;
0457: }
0458:
0459: /**
0460: * Imports the resources and writes them to the cms.<p>
0461: *
0462: * @throws CmsImportExportException if something goes wrong
0463: */
0464: private void importAllResources() throws CmsImportExportException {
0465:
0466: List fileNodes = null, acentryNodes = null;
0467: Element currentElement = null, currentEntry = null;
0468: String source = null, destination = null, resourceTypeName = null, timestamp = null, uuid = null, uuidresource = null;
0469: long lastmodified = 0;
0470: int resourceTypeId = CmsResourceTypePlain.getStaticTypeId();
0471: List properties = null;
0472: boolean old_overwriteCollidingResources = false;
0473: try {
0474: m_webAppNames = getCompatibilityWebAppNames();
0475: } catch (Exception e) {
0476: if (LOG.isDebugEnabled()) {
0477: LOG
0478: .debug(
0479: Messages
0480: .get()
0481: .getBundle()
0482: .key(
0483: Messages.LOG_IMPORTEXPORT_ERROR_GETTING_WEBAPP_COMPATIBILITY_NAMES_0),
0484: e);
0485: }
0486: m_report.println(e);
0487: }
0488: if (m_webAppNames == null) {
0489: m_webAppNames = Collections.EMPTY_LIST;
0490: }
0491:
0492: // get the old webapp url from the OpenCms properties
0493: m_webappUrl = OpenCms.getImportExportManager()
0494: .getOldWebAppUrl();
0495: if (m_webappUrl == null) {
0496: // use a default value
0497: m_webappUrl = "http://localhost:8080/opencms/opencms";
0498: }
0499: // cut last "/" from webappUrl if present
0500: if (m_webappUrl.endsWith("/")) {
0501: m_webappUrl = m_webappUrl.substring(0, m_webappUrl
0502: .lastIndexOf("/"));
0503: }
0504:
0505: // get list of unwanted properties
0506: List deleteProperties = OpenCms.getImportExportManager()
0507: .getIgnoredProperties();
0508:
0509: // get list of immutable resources
0510: List immutableResources = OpenCms.getImportExportManager()
0511: .getImmutableResources();
0512: if (immutableResources == null) {
0513: immutableResources = Collections.EMPTY_LIST;
0514: }
0515: if (LOG.isDebugEnabled()) {
0516: LOG
0517: .debug(Messages
0518: .get()
0519: .getBundle()
0520: .key(
0521: Messages.LOG_IMPORTEXPORT_IMMUTABLE_RESOURCES_SIZE_1,
0522: Integer.toString(immutableResources
0523: .size())));
0524: }
0525:
0526: // save the value of the boolean flag whether colliding resources should be overwritten
0527: old_overwriteCollidingResources = OpenCms
0528: .getImportExportManager().overwriteCollidingResources();
0529:
0530: // force v1 and v2 imports to overwrite colliding resources, because they dont have resource
0531: // UUIDs in their manifest anyway
0532: OpenCms.getImportExportManager()
0533: .setOverwriteCollidingResources(true);
0534:
0535: try {
0536: // get all file-nodes
0537: fileNodes = m_docXml.selectNodes("//" + A_CmsImport.N_FILE);
0538: int importSize = fileNodes.size();
0539:
0540: // walk through all files in manifest
0541: for (int i = 0; i < importSize; i++) {
0542:
0543: m_report
0544: .print(
0545: org.opencms.report.Messages
0546: .get()
0547: .container(
0548: org.opencms.report.Messages.RPT_SUCCESSION_2,
0549: String.valueOf(i + 1),
0550: String
0551: .valueOf(importSize)),
0552: I_CmsReport.FORMAT_NOTE);
0553: currentElement = (Element) fileNodes.get(i);
0554:
0555: // get all information for a file-import
0556: source = getChildElementTextValue(currentElement,
0557: A_CmsImport.N_SOURCE);
0558: destination = getChildElementTextValue(currentElement,
0559: A_CmsImport.N_DESTINATION);
0560:
0561: resourceTypeName = getChildElementTextValue(
0562: currentElement, A_CmsImport.N_TYPE);
0563: if (RESOURCE_TYPE_NEWPAGE_NAME.equals(resourceTypeName)) {
0564: resourceTypeId = RESOURCE_TYPE_NEWPAGE_ID;
0565: } else if (RESOURCE_TYPE_LEGACY_PAGE_NAME
0566: .equals(resourceTypeName)) {
0567: // resource with a "legacy" resource type are imported using the "plain" resource
0568: // type because you cannot import a resource without having the resource type object
0569: resourceTypeId = CmsResourceTypePlain
0570: .getStaticTypeId();
0571: } else if (RESOURCE_TYPE_LINK_NAME
0572: .equals(resourceTypeName)) {
0573: // set resource type of legacy "link" which is converted later
0574: resourceTypeId = RESOURCE_TYPE_LINK_ID;
0575: } else {
0576: I_CmsResourceType type = OpenCms
0577: .getResourceManager().getResourceType(
0578: resourceTypeName);
0579: resourceTypeId = type.getTypeId();
0580: }
0581:
0582: uuid = getChildElementTextValue(currentElement,
0583: A_CmsImport.N_UUIDSTRUCTURE);
0584: uuidresource = getChildElementTextValue(currentElement,
0585: A_CmsImport.N_UUIDRESOURCE);
0586:
0587: timestamp = getChildElementTextValue(currentElement,
0588: A_CmsImport.N_LASTMODIFIED);
0589: if (timestamp != null) {
0590: lastmodified = Long.parseLong(timestamp);
0591: } else {
0592: lastmodified = System.currentTimeMillis();
0593: }
0594:
0595: // if the type is "script" set it to plain
0596: if ("script".equals(resourceTypeName)) {
0597: resourceTypeName = CmsResourceTypePlain
0598: .getStaticTypeName();
0599: }
0600:
0601: if (LOG.isDebugEnabled()) {
0602: LOG
0603: .debug(Messages
0604: .get()
0605: .getBundle()
0606: .key(
0607: Messages.LOG_IMPORTEXPORT_ORIGINAL_RESOURCE_NAME_1,
0608: destination));
0609: }
0610:
0611: String translatedName = m_cms.getRequestContext()
0612: .addSiteRoot(m_importPath + destination);
0613: if (CmsResourceTypeFolder.RESOURCE_TYPE_NAME
0614: .equals(resourceTypeName)) {
0615: // ensure folders end with a "/"
0616: if (!CmsResource.isFolder(translatedName)) {
0617: translatedName += "/";
0618: }
0619: }
0620:
0621: if (LOG.isDebugEnabled()) {
0622: LOG
0623: .debug(Messages
0624: .get()
0625: .getBundle()
0626: .key(
0627: Messages.LOG_IMPORTEXPORT_TRANSLATED_RESOURCE_NAME_1,
0628: translatedName));
0629: }
0630:
0631: boolean resourceNotImmutable = checkImmutable(
0632: translatedName, immutableResources);
0633: translatedName = m_cms.getRequestContext()
0634: .removeSiteRoot(translatedName);
0635: if (resourceNotImmutable) {
0636:
0637: // print out the information to the report
0638: m_report.print(Messages.get().container(
0639: Messages.RPT_IMPORTING_0),
0640: I_CmsReport.FORMAT_NOTE);
0641: m_report
0642: .print(org.opencms.report.Messages
0643: .get()
0644: .container(
0645: org.opencms.report.Messages.RPT_ARGUMENT_1,
0646: translatedName));
0647: m_report
0648: .print(org.opencms.report.Messages
0649: .get()
0650: .container(
0651: org.opencms.report.Messages.RPT_DOTS_0));
0652:
0653: // get all properties
0654: properties = readPropertiesFromManifest(
0655: currentElement, deleteProperties);
0656:
0657: // import the specified file
0658: CmsResource res = importResource(source,
0659: destination, uuid, uuidresource,
0660: resourceTypeId, resourceTypeName,
0661: lastmodified, properties);
0662:
0663: if (res != null) {
0664:
0665: List aceList = new ArrayList();
0666: // write all imported access control entries for this file
0667: acentryNodes = currentElement.selectNodes("*/"
0668: + A_CmsImport.N_ACCESSCONTROL_ENTRY);
0669: // collect all access control entries
0670: for (int j = 0; j < acentryNodes.size(); j++) {
0671: currentEntry = (Element) acentryNodes
0672: .get(j);
0673: // get the data of the access control entry
0674: String id = getChildElementTextValue(
0675: currentEntry, A_CmsImport.N_ID);
0676: String acflags = getChildElementTextValue(
0677: currentEntry, A_CmsImport.N_FLAGS);
0678: String allowed = getChildElementTextValue(
0679: currentEntry,
0680: A_CmsImport.N_ACCESSCONTROL_ALLOWEDPERMISSIONS);
0681: String denied = getChildElementTextValue(
0682: currentEntry,
0683: A_CmsImport.N_ACCESSCONTROL_DENIEDPERMISSIONS);
0684:
0685: // add the entry to the list
0686: aceList.add(getImportAccessControlEntry(
0687: res, id, allowed, denied, acflags));
0688: }
0689: importAccessControlEntries(res, aceList);
0690: if (LOG.isInfoEnabled()) {
0691: LOG
0692: .info(Messages
0693: .get()
0694: .getBundle()
0695: .key(
0696: Messages.LOG_IMPORTING_4,
0697: new Object[] {
0698: String
0699: .valueOf(i + 1),
0700: String
0701: .valueOf(importSize),
0702: translatedName,
0703: destination }));
0704: }
0705:
0706: } else {
0707: // resource import failed, since no CmsResource was created
0708: m_report.print(Messages.get().container(
0709: Messages.RPT_SKIPPING_0),
0710: I_CmsReport.FORMAT_OK);
0711: m_report
0712: .println(org.opencms.report.Messages
0713: .get()
0714: .container(
0715: org.opencms.report.Messages.RPT_ARGUMENT_1,
0716: translatedName));
0717: if (LOG.isInfoEnabled()) {
0718: LOG.info(Messages.get().getBundle().key(
0719: Messages.LOG_SKIPPING_3,
0720: String.valueOf(i + 1),
0721: String.valueOf(importSize),
0722: translatedName));
0723: }
0724: }
0725: } else {
0726: // skip the file import, just print out the information to the report
0727: m_report.print(Messages.get().container(
0728: Messages.RPT_SKIPPING_0),
0729: I_CmsReport.FORMAT_NOTE);
0730: m_report
0731: .println(org.opencms.report.Messages
0732: .get()
0733: .container(
0734: org.opencms.report.Messages.RPT_ARGUMENT_1,
0735: translatedName));
0736:
0737: if (LOG.isInfoEnabled()) {
0738: LOG.info(Messages.get().getBundle().key(
0739: Messages.LOG_SKIPPING_3,
0740: String.valueOf(i + 1),
0741: String.valueOf(importSize),
0742: translatedName));
0743: }
0744: }
0745: }
0746:
0747: // now merge the body and page control files. this only has to be done if the import
0748: // version is below version 3
0749: if ((getVersion() < 3) && m_convertToXmlPage) {
0750: mergePageFiles();
0751: removeFolders();
0752: }
0753: } catch (Exception e) {
0754: m_report.println(e);
0755: m_report.addError(e);
0756:
0757: CmsMessageContainer message = Messages
0758: .get()
0759: .container(
0760: Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_RESOURCES_0);
0761: if (LOG.isDebugEnabled()) {
0762: LOG.debug(message.key(), e);
0763: }
0764:
0765: throw new CmsImportExportException(message, e);
0766: } finally {
0767: // set the flag to overwrite colliding resources back to its original value
0768: OpenCms.getImportExportManager()
0769: .setOverwriteCollidingResources(
0770: old_overwriteCollidingResources);
0771: }
0772: }
0773:
0774: /**
0775: * Imports a resource (file or folder) into the cms.<p>
0776: *
0777: * @param source the path to the source-file
0778: * @param destination the path to the destination-file in the cms
0779: * @param uuid the structure uuid of the resource
0780: * @param uuidresource the resource uuid of the resource
0781: * @param resourceTypeId the ID of the file's resource type
0782: * @param resourceTypeName the name of the file's resource type
0783: * @param lastmodified the timestamp of the file
0784: * @param properties a list with properties for this resource
0785: *
0786: * @return imported resource
0787: */
0788: private CmsResource importResource(String source,
0789: String destination, String uuid, String uuidresource,
0790: int resourceTypeId, String resourceTypeName,
0791: long lastmodified, List properties) {
0792:
0793: byte[] content = null;
0794: CmsResource res = null;
0795: String targetName = null;
0796:
0797: try {
0798: // get the file content
0799: if (source != null) {
0800: content = getFileBytes(source);
0801: }
0802:
0803: content = convertContent(source, destination, content,
0804: resourceTypeName);
0805:
0806: // get all required information to create a CmsResource
0807: int size = 0;
0808: if (content != null) {
0809: size = content.length;
0810: }
0811: // get the required UUIDs
0812: CmsUUID curUser = m_cms.getRequestContext().currentUser()
0813: .getId();
0814: CmsUUID newUuidstructure = new CmsUUID();
0815: CmsUUID newUuidresource = new CmsUUID();
0816: if (uuid != null) {
0817: newUuidstructure = new CmsUUID(uuid);
0818: }
0819: if (uuidresource != null) {
0820: newUuidresource = new CmsUUID(uuidresource);
0821: }
0822:
0823: // extract the name of the resource form the destination
0824: targetName = destination;
0825: if (targetName.endsWith("/")) {
0826: targetName = targetName.substring(0, targetName
0827: .length() - 1);
0828: }
0829:
0830: boolean isFolder = false;
0831: try {
0832: isFolder = CmsFolder.isFolderType(resourceTypeId);
0833: } catch (Throwable t) {
0834: // the specified resource type ID might be of an unknown resource type.
0835: // as another option, check the content length and resource type name
0836: // to determine if the resource is a folder or not.
0837: isFolder = ((size == 0) && CmsResourceTypeFolder.RESOURCE_TYPE_NAME
0838: .equalsIgnoreCase(resourceTypeName));
0839: }
0840:
0841: // create a new CmsResource
0842: CmsResource resource = new CmsResource(newUuidstructure,
0843: newUuidresource, targetName, resourceTypeId,
0844: isFolder, 0, m_cms.getRequestContext()
0845: .currentProject().getUuid(),
0846: CmsResource.STATE_NEW, lastmodified, curUser,
0847: lastmodified, curUser,
0848: CmsResource.DATE_RELEASED_DEFAULT,
0849: CmsResource.DATE_EXPIRED_DEFAULT, 1, size, System
0850: .currentTimeMillis(), 0);
0851:
0852: if (RESOURCE_TYPE_LINK_ID == resourceTypeId) {
0853: // store links for later conversion
0854: m_report.print(Messages.get().container(
0855: Messages.RPT_STORING_LINK_0),
0856: I_CmsReport.FORMAT_NOTE);
0857: m_linkStorage.put(m_importPath + destination,
0858: new String(content));
0859: m_linkPropertyStorage.put(m_importPath + destination,
0860: properties);
0861: res = resource;
0862: } else {
0863: // import this resource in the VFS
0864: String resName = m_importPath + destination;
0865: res = m_cms.importResource(resName, resource, content,
0866: properties);
0867: try {
0868: m_cms.unlockResource(resName);
0869: } catch (CmsLockException e) {
0870: if (LOG.isDebugEnabled()) {
0871: LOG
0872: .debug(
0873: Messages
0874: .get()
0875: .getBundle()
0876: .key(
0877: Messages.LOG_IMPORTEXPORT_UNABLE_TO_UNLOCK_RESOURCE_1,
0878: resName), e);
0879: }
0880: }
0881: }
0882:
0883: m_report.println(org.opencms.report.Messages.get()
0884: .container(org.opencms.report.Messages.RPT_DOTS_0));
0885:
0886: } catch (CmsException exc) {
0887: CmsMessageContainer message = Messages
0888: .get()
0889: .container(
0890: Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_RESOURCE_1,
0891: targetName);
0892: if (LOG.isDebugEnabled()) {
0893: LOG.debug(message.key(), exc);
0894: }
0895: // an error while importing the file
0896: m_report.println(exc);
0897: try {
0898: // Sleep some time after an error so that the report output has a chance to keep up
0899: Thread.sleep(1000);
0900: } catch (Exception e) {
0901: // ignore
0902: }
0903: }
0904: return res;
0905: }
0906:
0907: /**
0908: * Merges a single page.<p>
0909: *
0910: * @param resourcename the resource name of the page
0911: * @throws CmsImportExportException if something goes wrong
0912: * @throws CmsXmlException if the page file could not be unmarshalled
0913: */
0914: private void mergePageFile(String resourcename)
0915: throws CmsXmlException, CmsImportExportException {
0916:
0917: try {
0918:
0919: if (LOG.isDebugEnabled()) {
0920: LOG.debug(Messages.get().getBundle().key(
0921: Messages.LOG_IMPORTEXPORT_START_MERGING_1,
0922: resourcename));
0923: }
0924:
0925: // in OpenCms versions <5 node names have not been case sensitive. thus, nodes are read both in upper
0926: // and lower case letters, or have to be tested for equality ignoring upper/lower case...
0927:
0928: // get the header file
0929: CmsFile pagefile = m_cms.readFile(resourcename,
0930: CmsResourceFilter.ALL);
0931: Document contentXml = CmsXmlUtils.unmarshalHelper(pagefile
0932: .getContents(), null);
0933:
0934: // get the <masterTemplate> node to check the content. this node contains the name of the template file.
0935: String masterTemplateNodeName = "//masterTemplate";
0936: Node masterTemplateNode = contentXml
0937: .selectSingleNode(masterTemplateNodeName);
0938: if (masterTemplateNode == null) {
0939: masterTemplateNode = contentXml
0940: .selectSingleNode(masterTemplateNodeName
0941: .toLowerCase());
0942: }
0943: if (masterTemplateNode == null) {
0944: masterTemplateNode = contentXml
0945: .selectSingleNode(masterTemplateNodeName
0946: .toUpperCase());
0947: }
0948:
0949: // there is only one <masterTemplate> allowed
0950: String mastertemplate = null;
0951: if (masterTemplateNode != null) {
0952: // get the name of the mastertemplate
0953: mastertemplate = masterTemplateNode.getText().trim();
0954: }
0955:
0956: // get the <ELEMENTDEF> nodes to check the content.
0957: // this node contains the information for the body element.
0958: String elementDefNodeName = "//ELEMENTDEF";
0959: Node bodyNode = contentXml
0960: .selectSingleNode(elementDefNodeName);
0961: if (bodyNode == null) {
0962: bodyNode = contentXml
0963: .selectSingleNode(elementDefNodeName
0964: .toLowerCase());
0965: }
0966:
0967: // there is only one <ELEMENTDEF> allowed
0968: if (bodyNode != null) {
0969:
0970: String bodyclass = null;
0971: String bodyname = null;
0972: Map bodyparams = null;
0973:
0974: List nodes = ((Element) bodyNode).elements();
0975: for (int i = 0, n = nodes.size(); i < n; i++) {
0976:
0977: Node node = (Node) nodes.get(i);
0978:
0979: if ("CLASS".equalsIgnoreCase(node.getName())) {
0980: bodyclass = node.getText().trim();
0981: } else if ("TEMPLATE".equalsIgnoreCase(node
0982: .getName())) {
0983: bodyname = node.getText().trim();
0984: if (!bodyname.startsWith("/")) {
0985: bodyname = CmsResource
0986: .getFolderPath(resourcename)
0987: + bodyname;
0988: }
0989: } else if ("PARAMETER".equalsIgnoreCase(node
0990: .getName())) {
0991: Element paramElement = (Element) node;
0992: if (bodyparams == null) {
0993: bodyparams = new HashMap();
0994: }
0995: bodyparams.put((paramElement.attribute("name"))
0996: .getText(), paramElement.getTextTrim());
0997: }
0998: }
0999:
1000: if ((mastertemplate == null) || (bodyname == null)) {
1001:
1002: CmsMessageContainer message = Messages
1003: .get()
1004: .container(
1005: Messages.ERR_IMPORTEXPORT_ERROR_CANNOT_MERGE_PAGE_FILE_3,
1006: resourcename, mastertemplate,
1007: bodyname);
1008: if (LOG.isDebugEnabled()) {
1009: LOG.debug(message.key());
1010: }
1011:
1012: throw new CmsImportExportException(message);
1013: }
1014:
1015: // lock the resource, so that it can be manipulated
1016: m_cms.lockResource(resourcename);
1017:
1018: // get all properties
1019: List properties = m_cms.readPropertyObjects(
1020: resourcename, false);
1021:
1022: // now get the content of the bodyfile and insert it into the control file
1023: CmsFile bodyfile = m_cms.readFile(bodyname,
1024: CmsResourceFilter.IGNORE_EXPIRATION);
1025:
1026: //get the encoding
1027: String encoding = CmsProperty
1028: .get(
1029: CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING,
1030: properties).getValue();
1031: if (encoding == null) {
1032: encoding = OpenCms.getSystemInfo()
1033: .getDefaultEncoding();
1034: }
1035:
1036: if (m_convertToXmlPage) {
1037: if (LOG.isDebugEnabled()) {
1038: LOG
1039: .debug(Messages
1040: .get()
1041: .getBundle()
1042: .key(
1043: Messages.LOG_IMPORTEXPORT_START_CONVERTING_TO_XML_0));
1044: }
1045:
1046: CmsXmlPage xmlPage = CmsXmlPageConverter
1047: .convertToXmlPage(m_cms, bodyfile
1048: .getContents(), getLocale(
1049: resourcename, properties), encoding);
1050:
1051: if (LOG.isDebugEnabled()) {
1052: LOG
1053: .debug(Messages
1054: .get()
1055: .getBundle()
1056: .key(
1057: Messages.LOG_IMPORTEXPORT_END_CONVERTING_TO_XML_0));
1058: }
1059:
1060: if (xmlPage != null) {
1061: pagefile.setContents(xmlPage.marshal());
1062:
1063: // set the type to xml page
1064: pagefile.setType(CmsResourceTypeXmlPage
1065: .getStaticTypeId());
1066: }
1067: }
1068:
1069: // add the template and other required properties
1070: CmsProperty newProperty = new CmsProperty(
1071: CmsPropertyDefinition.PROPERTY_TEMPLATE,
1072: mastertemplate, null);
1073: // property lists must not contain equal properties
1074: properties.remove(newProperty);
1075: properties.add(newProperty);
1076:
1077: // if set, add the bodyclass as property
1078: if (CmsStringUtil.isNotEmpty(bodyclass)) {
1079: newProperty = new CmsProperty(
1080: CmsPropertyDefinition.PROPERTY_TEMPLATE,
1081: mastertemplate, null);
1082: newProperty.setAutoCreatePropertyDefinition(true);
1083: properties.remove(newProperty);
1084: properties.add(newProperty);
1085: }
1086: // if set, add bodyparams as properties
1087: if (bodyparams != null) {
1088: for (Iterator p = bodyparams.entrySet().iterator(); p
1089: .hasNext();) {
1090: Map.Entry entry = (Map.Entry) p.next();
1091: String key = (String) entry.getKey();
1092: String value = (String) entry.getValue();
1093: newProperty = new CmsProperty(key, value, null);
1094: newProperty
1095: .setAutoCreatePropertyDefinition(true);
1096: properties.remove(newProperty);
1097: properties.add(newProperty);
1098: }
1099: }
1100:
1101: if (LOG.isDebugEnabled()) {
1102: LOG
1103: .debug(Messages
1104: .get()
1105: .getBundle()
1106: .key(
1107: Messages.LOG_IMPORTEXPORT_START_IMPORTING_XML_PAGE_0));
1108: }
1109:
1110: // now import the resource
1111: m_cms.importResource(resourcename, pagefile, pagefile
1112: .getContents(), properties);
1113:
1114: // finally delete the old body file, it is not needed anymore
1115: m_cms.lockResource(bodyname);
1116: m_cms.deleteResource(bodyname,
1117: CmsResource.DELETE_PRESERVE_SIBLINGS);
1118:
1119: if (LOG.isDebugEnabled()) {
1120: LOG
1121: .debug(Messages
1122: .get()
1123: .getBundle()
1124: .key(
1125: Messages.LOG_IMPORTEXPORT_END_IMPORTING_XML_PAGE_0));
1126: }
1127:
1128: m_report.println(
1129: org.opencms.report.Messages.get().container(
1130: org.opencms.report.Messages.RPT_OK_0),
1131: I_CmsReport.FORMAT_OK);
1132:
1133: } else {
1134:
1135: // there are more than one template nodes in this control file
1136: // convert the resource into a plain text file
1137: // lock the resource, so that it can be manipulated
1138: m_cms.lockResource(resourcename);
1139: // set the type to plain
1140: pagefile
1141: .setType(CmsResourceTypePlain.getStaticTypeId());
1142: // write all changes
1143: m_cms.writeFile(pagefile);
1144: // done, unlock the resource
1145: m_cms.unlockResource(resourcename);
1146:
1147: if (LOG.isDebugEnabled()) {
1148: LOG
1149: .debug(Messages
1150: .get()
1151: .getBundle()
1152: .key(
1153: Messages.LOG_IMPORTEXPORT_CANNOT_CONVERT_XML_STRUCTURE_1,
1154: resourcename));
1155: }
1156:
1157: m_report.println(Messages.get().container(
1158: Messages.RPT_NOT_CONVERTED_0),
1159: I_CmsReport.FORMAT_OK);
1160:
1161: }
1162:
1163: if (LOG.isDebugEnabled()) {
1164: LOG.debug(Messages.get().getBundle().key(
1165: Messages.LOG_IMPORTEXPORT_END_MERGING_1,
1166: resourcename));
1167: }
1168: } catch (CmsXmlException e) {
1169:
1170: throw e;
1171: } catch (CmsException e) {
1172:
1173: m_report.println(e);
1174:
1175: CmsMessageContainer message = Messages
1176: .get()
1177: .container(
1178: Messages.ERR_IMPORTEXPORT_ERROR_MERGING_PAGE_FILE_1,
1179: resourcename);
1180: if (LOG.isDebugEnabled()) {
1181: LOG.debug(message.key(), e);
1182: }
1183:
1184: throw new CmsImportExportException(message, e);
1185: }
1186:
1187: }
1188:
1189: /**
1190: * Merges the page control files and their corresponding bodies into a single files.<p>
1191: *
1192: * @throws CmsImportExportException if something goes wrong
1193: * @throws CmsXmlException if the page file could not be unmarshalled
1194: */
1195: private void mergePageFiles() throws CmsXmlException,
1196: CmsImportExportException {
1197:
1198: try {
1199: // check if the template property exists. If not, create it.
1200: try {
1201: m_cms
1202: .readPropertyDefinition(CmsPropertyDefinition.PROPERTY_TEMPLATE);
1203: } catch (CmsException e) {
1204: // the template propertydefintion does not exist. So create it.
1205: m_cms
1206: .createPropertyDefinition(CmsPropertyDefinition.PROPERTY_TEMPLATE);
1207: }
1208:
1209: // copy all propertydefinitions of the old page to the new page
1210: List definitions = m_cms.readAllPropertyDefinitions();
1211:
1212: Iterator j = definitions.iterator();
1213: while (j.hasNext()) {
1214: CmsPropertyDefinition definition = (CmsPropertyDefinition) j
1215: .next();
1216: // check if this propertydef already exits
1217: try {
1218: m_cms.readPropertyDefinition(definition.getName());
1219: } catch (Exception e) {
1220: m_cms
1221: .createPropertyDefinition(definition
1222: .getName());
1223: }
1224: }
1225: } catch (CmsException e) {
1226:
1227: CmsMessageContainer message = Messages
1228: .get()
1229: .container(
1230: Messages.ERR_IMPORTEXPORT_ERROR_COPYING_PROPERTY_DEFINITIONS_0);
1231: if (LOG.isDebugEnabled()) {
1232: LOG.debug(message.key(), e);
1233: }
1234:
1235: throw new CmsImportExportException(message);
1236: }
1237:
1238: // iterate through the list of all page controlfiles found during the import process
1239: int size = m_pageStorage.size();
1240: m_report.println(Messages.get().container(
1241: Messages.RPT_MERGE_START_0),
1242: I_CmsReport.FORMAT_HEADLINE);
1243: Iterator i = m_pageStorage.iterator();
1244: int counter = 1;
1245: while (i.hasNext()) {
1246: String resname = (String) i.next();
1247: // adjust the resourcename if nescessary
1248: if (!resname.startsWith("/")) {
1249: resname = "/" + resname;
1250: }
1251:
1252: m_report.print(org.opencms.report.Messages.get().container(
1253: org.opencms.report.Messages.RPT_SUCCESSION_2,
1254: String.valueOf(counter), String.valueOf(size)),
1255: I_CmsReport.FORMAT_NOTE);
1256: m_report.print(Messages.get().container(
1257: Messages.RPT_MERGE_0), I_CmsReport.FORMAT_NOTE);
1258: m_report.print(org.opencms.report.Messages.get()
1259: .container(
1260: org.opencms.report.Messages.RPT_ARGUMENT_1,
1261: resname));
1262:
1263: mergePageFile(resname);
1264: if (LOG.isInfoEnabled()) {
1265: LOG.info(Messages.get().getBundle().key(
1266: Messages.LOG_MERGING_3,
1267: String.valueOf(counter), String.valueOf(size),
1268: resname));
1269: }
1270:
1271: counter++;
1272:
1273: }
1274: // free mem
1275: m_pageStorage.clear();
1276:
1277: }
1278:
1279: /**
1280: * Deletes the folder structure which has been creating while importing the body files..<p>
1281: *
1282: * @throws CmsImportExportException if something goes wrong
1283: */
1284: private void removeFolders() throws CmsImportExportException {
1285:
1286: try {
1287:
1288: int size = m_folderStorage.size();
1289:
1290: m_report.println(Messages.get().container(
1291: Messages.RPT_DELFOLDER_START_0),
1292: I_CmsReport.FORMAT_HEADLINE);
1293: // iterate though all collected folders. Iteration must start at the end of the list,
1294: // as folders habe to be deleted in the reverse order.
1295: int counter = 1;
1296: for (int j = (size - 1); j >= 0; j--) {
1297: String resname = (String) m_folderStorage.get(j);
1298: resname = (resname.startsWith("/") ? "" : "/")
1299: + resname + (resname.endsWith("/") ? "" : "/");
1300: // now check if the folder is really empty. Only delete empty folders
1301: List files = m_cms.getFilesInFolder(resname,
1302: CmsResourceFilter.IGNORE_EXPIRATION);
1303:
1304: if (files.size() == 0) {
1305: List folders = m_cms.getSubFolders(resname,
1306: CmsResourceFilter.IGNORE_EXPIRATION);
1307: if (folders.size() == 0) {
1308: m_report
1309: .print(
1310: org.opencms.report.Messages
1311: .get()
1312: .container(
1313: org.opencms.report.Messages.RPT_SUCCESSION_2,
1314: String
1315: .valueOf(counter),
1316: String
1317: .valueOf(size)),
1318: I_CmsReport.FORMAT_NOTE);
1319: m_report.print(Messages.get().container(
1320: Messages.RPT_DELFOLDER_0),
1321: I_CmsReport.FORMAT_NOTE);
1322: m_report
1323: .print(
1324: org.opencms.report.Messages
1325: .get()
1326: .container(
1327: org.opencms.report.Messages.RPT_ARGUMENT_1,
1328: resname),
1329: I_CmsReport.FORMAT_DEFAULT);
1330: m_cms.lockResource(resname);
1331: m_cms.deleteResource(resname,
1332: CmsResource.DELETE_PRESERVE_SIBLINGS);
1333: m_report
1334: .println(
1335: org.opencms.report.Messages
1336: .get()
1337: .container(
1338: org.opencms.report.Messages.RPT_OK_0),
1339: I_CmsReport.FORMAT_OK);
1340: counter++;
1341: }
1342: }
1343: }
1344: } catch (CmsException e) {
1345:
1346: CmsMessageContainer message = Messages
1347: .get()
1348: .container(
1349: Messages.ERR_IMPORTEXPORT_ERROR_REMOVING_FOLDERS_OF_IMPORTED_BODY_FILES_0);
1350: if (LOG.isDebugEnabled()) {
1351: LOG.debug(message.key(), e);
1352: }
1353:
1354: throw new CmsImportExportException(message, e);
1355: }
1356: }
1357: }
|