001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.importexport;
029
030import org.opencms.configuration.CmsConfigurationException;
031import org.opencms.db.CmsExportPoint;
032import org.opencms.db.CmsExportPointDriver;
033import org.opencms.db.CmsTempFolderExportPointDriver;
034import org.opencms.db.CmsUserExportSettings;
035import org.opencms.db.I_CmsExportPointDriver;
036import org.opencms.file.CmsObject;
037import org.opencms.i18n.CmsMessageContainer;
038import org.opencms.main.CmsEvent;
039import org.opencms.main.CmsException;
040import org.opencms.main.CmsLog;
041import org.opencms.main.I_CmsEventListener;
042import org.opencms.main.OpenCms;
043import org.opencms.report.I_CmsReport;
044import org.opencms.security.CmsRole;
045import org.opencms.security.CmsRoleViolationException;
046import org.opencms.security.I_CmsPrincipal;
047import org.opencms.util.CmsStringUtil;
048import org.opencms.xml.CmsXmlException;
049
050import java.io.InputStream;
051import java.util.ArrayList;
052import java.util.Collections;
053import java.util.HashMap;
054import java.util.List;
055import java.util.Map;
056import java.util.Set;
057
058import org.apache.commons.logging.Log;
059
060import org.dom4j.Document;
061import org.dom4j.io.SAXReader;
062
063import com.google.common.collect.Lists;
064
065/**
066 * Provides information about how to handle imported resources.<p>
067 *
068 * @since 6.0.0
069 *
070 * @see OpenCms#getImportExportManager()
071 */
072public class CmsImportExportManager {
073
074    /** Time modes to specify how time stamps should be handled. */
075    public static enum TimestampMode {
076        /** Use the timestamp of the imported file. */
077        FILETIME,
078        /** Use the time of import for the timestamp. */
079        IMPORTTIME,
080        /** The timestamp is explicitly given. */
081        VFSTIME;
082
083        /** Returns the default timestamp mode.
084         * @return the default timestamp mode
085         */
086        public static TimestampMode getDefaultTimeStampMode() {
087
088            return VFSTIME;
089        }
090
091        /** More robust version of {@link java.lang.Enum#valueOf(java.lang.Class, String)} that is case insensitive
092         * and defaults for all "unreadable" arguments to the default timestamp mode.
093         * @param value the TimeMode value as String
094         * @return <code>value</code> as TimeMode object, or the default time mode, if <code>value</code> can't be converted to a TimeMode object.
095         */
096        public static TimestampMode getEnum(String value) {
097
098            if (null == value) {
099                return getDefaultTimeStampMode();
100            } else {
101                try {
102                    return TimestampMode.valueOf(value.toUpperCase());
103                } catch (IllegalArgumentException e) {
104                    return getDefaultTimeStampMode();
105                }
106            }
107        }
108    }
109
110    /** Tag in the {@link #EXPORT_MANIFEST} for the "userinfo/entry@name" attribute, contains the additional user info entry name.
111     * @deprecated Use the appropriate tag from latest import class instead*/
112    @Deprecated
113    public static final String A_NAME = A_CmsImport.A_NAME;
114
115    /** Tag in the {@link #EXPORT_MANIFEST} for the "userinfo/entry@type" attribute, contains the additional user info entry data type name.
116     * @deprecated Use the appropriate tag from latest import class instead*/
117    @Deprecated
118    public static final String A_TYPE = A_CmsImport.A_TYPE;
119
120    /** The name of the XML manifest file used for the description of exported OpenCms VFS properties and attributes. */
121    public static final String EXPORT_MANIFEST = "manifest.xml";
122
123    /** The current version of the OpenCms export (appears in the {@link #EXPORT_MANIFEST} header). */
124    public static final String EXPORT_VERSION = "" + CmsImportVersion10.IMPORT_VERSION10; //TODO: when changing this to a newer import version, need to refactor the module updater so it dynamically uses the correct import version
125
126    /**
127     * The name of the XML manifest file used for the description of exported OpenCms VFS properties and attributes.<p>
128     *
129     * @deprecated use {@link #EXPORT_MANIFEST} instead
130     */
131    @Deprecated
132    public static final String EXPORT_XMLFILENAME = EXPORT_MANIFEST;
133
134    /** Tag in the {@link #EXPORT_MANIFEST} for the "access" node.
135     * @deprecated Use the appropriate tag from latest import class instead*/
136    @Deprecated
137    public static final String N_ACCESS = A_CmsImport.N_ACCESS;
138
139    /** Tag in the {@link #EXPORT_MANIFEST} for the "allowed" node, to identify allowed user permissions.
140     * @deprecated Use the appropriate tag from latest import class instead*/
141    @Deprecated
142    public static final String N_ACCESSCONTROL_ALLOWEDPERMISSIONS = A_CmsImport.N_ACCESSCONTROL_ALLOWEDPERMISSIONS;
143
144    /** Tag in the {@link #EXPORT_MANIFEST} for the "denied" node, to identify denied user permissions.
145     * @deprecated Use the appropriate tag from latest import class instead*/
146    @Deprecated
147    public static final String N_ACCESSCONTROL_DENIEDPERMISSIONS = A_CmsImport.N_ACCESSCONTROL_DENIEDPERMISSIONS;
148
149    /** Tag in the {@link #EXPORT_MANIFEST} for the "accesscontrol" node, to identify access control entries.
150     * @deprecated Use the appropriate tag from latest import class instead*/
151    @Deprecated
152    public static final String N_ACCESSCONTROL_ENTRIES = A_CmsImport.N_ACCESSCONTROL_ENTRIES;
153
154    /** Tag in the {@link #EXPORT_MANIFEST} for the "accessentry" node, to identify a single access control entry.
155     * @deprecated Use the appropriate tag from latest import class instead*/
156    @Deprecated
157    public static final String N_ACCESSCONTROL_ENTRY = A_CmsImport.N_ACCESSCONTROL_ENTRY;
158
159    /** Tag in the {@link #EXPORT_MANIFEST} for the "permissionset" node, to identify a permission set.
160     * @deprecated Use the appropriate tag from latest import class instead*/
161    @Deprecated
162    public static final String N_ACCESSCONTROL_PERMISSIONSET = A_CmsImport.N_ACCESSCONTROL_PERMISSIONSET;
163
164    /** Tag in the {@link #EXPORT_MANIFEST} for the "uuidprincipal" node, to identify a principal UUID.
165     * @deprecated Use the appropriate tag from latest import class instead*/
166    @Deprecated
167    public static final String N_ACCESSCONTROL_PRINCIPAL = A_CmsImport.N_ACCESSCONTROL_PRINCIPAL;
168
169    /** Tag for the "creator" node (appears in the {@link #EXPORT_MANIFEST} header). */
170    public static final String N_CREATOR = "creator";
171
172    /** Tag for the "createdate" node (appears in the {@link #EXPORT_MANIFEST} header). */
173    public static final String N_DATE = "createdate";
174
175    /** Tag in the {@link #EXPORT_MANIFEST} for the "datecreated" node, contains the date created VFS file attribute.
176     * @deprecated Use the appropriate tag from latest import class instead*/
177    @Deprecated
178    public static final String N_DATECREATED = A_CmsImport.N_DATECREATED;
179
180    /** Tag in the {@link #EXPORT_MANIFEST} for the "dateexpired" node, contains the expiration date VFS file attribute.
181     * @deprecated Use the appropriate tag from latest import class instead*/
182    @Deprecated
183    public static final String N_DATEEXPIRED = A_CmsImport.N_DATEEXPIRED;
184
185    /** Tag in the {@link #EXPORT_MANIFEST} for the "datelastmodified" node, contains the date last modified VFS file attribute.
186     * @deprecated Use the appropriate tag from latest import class instead*/
187    @Deprecated
188    public static final String N_DATELASTMODIFIED = A_CmsImport.N_DATELASTMODIFIED;
189
190    /** Tag in the {@link #EXPORT_MANIFEST} for the "datereleased" node, contains the release date VFS file attribute.
191     * @deprecated Use the appropriate tag from latest import class instead*/
192    @Deprecated
193    public static final String N_DATERELEASED = A_CmsImport.N_DATERELEASED;
194
195    /** Tag in the {@link #EXPORT_MANIFEST} for the "defaultgroup" node, for backward compatibility with OpenCms 5.x.
196     * @deprecated Use the appropriate tag from latest import class instead*/
197    @Deprecated
198    public static final String N_DEFAULTGROUP = A_CmsImport.N_DEFAULTGROUP;
199
200    /** Tag in the {@link #EXPORT_MANIFEST} for the "description" node, contains a users description test.
201     * @deprecated Use the appropriate tag from latest import class instead*/
202    @Deprecated
203    public static final String N_DESCRIPTION = A_CmsImport.N_DESCRIPTION;
204
205    /** Tag in the {@link #EXPORT_MANIFEST} for the "destination" node, contains target VFS file name.
206     * @deprecated Use the appropriate tag from latest import class instead*/
207    @Deprecated
208    public static final String N_DESTINATION = A_CmsImport.N_DESTINATION;
209
210    /** Tag in the {@link #EXPORT_MANIFEST} for the "email" node, contains a users email.
211     * @deprecated Use the appropriate tag from latest import class instead*/
212    @Deprecated
213    public static final String N_EMAIL = A_CmsImport.N_EMAIL;
214
215    /** Tag in the {@link #EXPORT_MANIFEST} for the "export" node. */
216    public static final String N_EXPORT = "export";
217
218    /** Tag in the {@link #EXPORT_MANIFEST} for the "file" node, container node for all VFS resources.
219     * @deprecated Use the appropriate tag from latest import class instead*/
220    @Deprecated
221    public static final String N_FILE = A_CmsImport.N_FILE;
222
223    /** Tag in the {@link #EXPORT_MANIFEST} for the "firstname" node, contains a users first name.
224     * @deprecated Use the appropriate tag from latest import class instead*/
225    @Deprecated
226    public static final String N_FIRSTNAME = A_CmsImport.N_FIRSTNAME;
227
228    /** Tag in the {@link #EXPORT_MANIFEST} for the "flags" node, contains the flags of a VFS resource.
229     * @deprecated Use the appropriate tag from latest import class instead*/
230    @Deprecated
231    public static final String N_FLAGS = A_CmsImport.N_FLAGS;
232
233    /** Tag in the {@link #EXPORT_MANIFEST} for the "groupdata" node, contains a users group data.
234     * @deprecated Use the appropriate tag from latest import class instead*/
235    @Deprecated
236    public static final String N_GROUPDATA = A_CmsImport.N_GROUPDATA;
237
238    /** Tag in the {@link #EXPORT_MANIFEST} for the "groupname" node, contains a groups name.
239     * @deprecated Use the appropriate tag from latest import class instead*/
240    @Deprecated
241    public static final String N_GROUPNAME = A_CmsImport.N_GROUPNAME;
242
243    /** Tag in the {@link #EXPORT_MANIFEST} for the "id" node, only required for backward compatibility with import version 2.
244     * @deprecated Use the appropriate tag from latest import class instead*/
245    @Deprecated
246    public static final String N_ID = A_CmsImport.N_ID;
247
248    /** Tag in the {@link #EXPORT_MANIFEST}, starts the manifest info header. */
249    public static final String N_INFO = "info";
250
251    /** Tag in the {@link #EXPORT_MANIFEST} for the "infoproject" node, appears in the manifest info header. */
252    public static final String N_INFO_PROJECT = "infoproject";
253
254    /** Tag in the {@link #EXPORT_MANIFEST} for the "lastmodified" node, only required for backward compatibility with import version 2.
255     * @deprecated Use the appropriate tag from latest import class instead*/
256    @Deprecated
257    public static final String N_LASTMODIFIED = A_CmsImport.N_LASTMODIFIED;
258
259    /** Tag in the {@link #EXPORT_MANIFEST} for the "lastname" node, contains a users last name.
260     * @deprecated Use the appropriate tag from latest import class instead*/
261    @Deprecated
262    public static final String N_LASTNAME = A_CmsImport.N_LASTNAME;
263
264    /** Tag in the {@link #EXPORT_MANIFEST} for the "name" node, contains a users login name.
265     * @deprecated Use the appropriate tag from latest import class instead*/
266    @Deprecated
267    public static final String N_NAME = A_CmsImport.N_NAME;
268
269    /** Tag in the {@link #EXPORT_MANIFEST} for the "opencms_version" node, appears in the manifest info header. */
270    public static final String N_OC_VERSION = "opencms_version";
271
272    /** Tag in the {@link #EXPORT_MANIFEST} for the "orgunitdatas" node, starts the organizational unit data.
273     * @deprecated Use the appropriate tag from latest import class instead*/
274    @Deprecated
275    public static final String N_ORGUNITDATA = A_CmsImport.N_ORGUNITDATA;
276
277    /** Tag in the {@link #EXPORT_MANIFEST} for the "parentgroup" node, contains a groups parent group name.
278     * @deprecated Use the appropriate tag from latest import class instead*/
279    @Deprecated
280    public static final String N_PARENTGROUP = A_CmsImport.N_PARENTGROUP;
281
282    /** Tag in the {@link #EXPORT_MANIFEST} for the "password" node, contains a users encrypted password.
283     * @deprecated Use the appropriate tag from latest import class instead*/
284    @Deprecated
285    public static final String N_PASSWORD = A_CmsImport.N_PASSWORD;
286
287    /** Tag in the {@link #EXPORT_MANIFEST} for the "properties" node, starts the list of properties of a VFS resource.
288     * @deprecated Use the appropriate tag from latest import class instead*/
289    @Deprecated
290    public static final String N_PROPERTIES = A_CmsImport.N_PROPERTIES;
291
292    /** Tag in the {@link #EXPORT_MANIFEST} for the "property" node, starts a property for a VFS resource.
293     * @deprecated Use the appropriate tag from latest import class instead*/
294    @Deprecated
295    public static final String N_PROPERTY = A_CmsImport.N_PROPERTY;
296
297    /** Tag in the {@link #EXPORT_MANIFEST} for the "type" property attribute, contains a property type.
298     * @deprecated Use the appropriate tag from latest import class instead*/
299    @Deprecated
300    public static final String N_PROPERTY_ATTRIB_TYPE = A_CmsImport.N_PROPERTY_ATTRIB_TYPE;
301
302    /** Tag in the {@link #EXPORT_MANIFEST} for the "shared" property type attribute value.
303     * @deprecated Use the appropriate tag from latest import class instead*/
304    @Deprecated
305    public static final String N_PROPERTY_ATTRIB_TYPE_SHARED = A_CmsImport.N_PROPERTY_ATTRIB_TYPE_SHARED;
306
307    /** Tag in the {@link #EXPORT_MANIFEST} for the "relation" node, starts a relation for a VFS resource.
308     * @deprecated Use the appropriate tag from latest import class instead*/
309    @Deprecated
310    public static final String N_RELATION = A_CmsImport.N_RELATION;
311
312    /** Tag in the {@link #EXPORT_MANIFEST} for the "id" relation attribute, contains the structure id of the target resource of the relation.
313     * @deprecated Use the appropriate tag from latest import class instead*/
314    @Deprecated
315    public static final String N_RELATION_ATTRIBUTE_ID = A_CmsImport.N_RELATION_ATTRIBUTE_ID;
316
317    /** Tag in the {@link #EXPORT_MANIFEST} for the "path" relation attribute, contains the path to the target resource of the relation.
318     * @deprecated Use the appropriate tag from latest import class instead*/
319    @Deprecated
320    public static final String N_RELATION_ATTRIBUTE_PATH = A_CmsImport.N_RELATION_ATTRIBUTE_PATH;
321
322    /** Tag in the {@link #EXPORT_MANIFEST} for the "type" relation attribute, contains the type of relation.
323     * @deprecated Use the appropriate tag from latest import class instead*/
324    @Deprecated
325    public static final String N_RELATION_ATTRIBUTE_TYPE = A_CmsImport.N_RELATION_ATTRIBUTE_TYPE;
326
327    /** Tag in the {@link #EXPORT_MANIFEST} for the "relations" node, starts the list of relations of a VFS resources.
328     * @deprecated Use the appropriate tag from latest import class instead*/
329    @Deprecated
330    public static final String N_RELATIONS = A_CmsImport.N_RELATIONS;
331
332    /** Tag in the {@link #EXPORT_MANIFEST} for the "source" node, contains the source path of a VFS resource in the import zip (or folder).
333     * @deprecated Use the appropriate tag from latest import class instead*/
334    @Deprecated
335    public static final String N_SOURCE = A_CmsImport.N_SOURCE;
336
337    /** Tag in the {@link #EXPORT_MANIFEST} for the "address" node, contains a users address.
338     * @deprecated Use the appropriate tag from latest import class instead*/
339    @Deprecated
340    public static final String N_TAG_ADDRESS = A_CmsImport.N_TAG_ADDRESS;
341
342    /** Tag in the {@link #EXPORT_MANIFEST} for the "type" node, the resource type name of a VFS resource.
343     * @deprecated Use the appropriate tag from latest import class instead*/
344    @Deprecated
345    public static final String N_TYPE = A_CmsImport.N_TYPE;
346
347    /** Tag in the {@link #EXPORT_MANIFEST} for the "user" node, starts the user data.
348     * @deprecated Use the appropriate tag from latest import class instead*/
349    @Deprecated
350    public static final String N_USER = A_CmsImport.N_USER;
351
352    /** Tag in the {@link #EXPORT_MANIFEST} for the "usercreated" node, contains the name of the user who created the VFS resource.
353     * @deprecated Use the appropriate tag from latest import class instead*/
354    @Deprecated
355    public static final String N_USERCREATED = A_CmsImport.N_USERCREATED;
356
357    /** Tag in the {@link #EXPORT_MANIFEST} for the "userdata" node, starts the list of users.
358     * @deprecated Use the appropriate tag from latest import class instead*/
359    @Deprecated
360    public static final String N_USERDATA = A_CmsImport.N_USERDATA;
361
362    /** Tag in the {@link #EXPORT_MANIFEST} for the "usergroupdatas" node, starts the users group data.
363     * @deprecated Use the appropriate tag from latest import class instead*/
364    @Deprecated
365    public static final String N_USERGROUPDATA = A_CmsImport.N_USERGROUPDATA;
366
367    /** Tag in the {@link #EXPORT_MANIFEST} for the "usergroups" node, starts the users group data.
368     * @deprecated Use the appropriate tag from latest import class instead*/
369    @Deprecated
370    public static final String N_USERGROUPS = A_CmsImport.N_USERGROUPS;
371
372    /** Tag in the {@link #EXPORT_MANIFEST} for the "userinfo" node, contains the additional user info.
373     * @deprecated Use the appropriate tag from latest import class instead*/
374    @Deprecated
375    public static final String N_USERINFO = A_CmsImport.N_USERINFO;
376
377    /** Tag in the {@link #EXPORT_MANIFEST} for the "userinfo/entry" node, contains the additional user info entry value.
378     * @deprecated Use the appropriate tag from latest import class instead*/
379    @Deprecated
380    public static final String N_USERINFO_ENTRY = A_CmsImport.N_USERINFO_ENTRY;
381
382    /** Tag in the {@link #EXPORT_MANIFEST} for the "userlastmodified" node, contains the name of the user who last modified the VFS resource.
383     * @deprecated Use the appropriate tag from latest import class instead*/
384    @Deprecated
385    public static final String N_USERLASTMODIFIED = A_CmsImport.N_USERLASTMODIFIED;
386
387    /** Tag in the {@link #EXPORT_MANIFEST} for the "uuidresource" node, contains a the resource UUID of a VFS resource.
388     * @deprecated Use the appropriate tag from latest import class instead*/
389    @Deprecated
390    public static final String N_UUIDRESOURCE = A_CmsImport.N_UUIDRESOURCE;
391
392    /** Tag in the {@link #EXPORT_MANIFEST} for the "uuidstructure" node, only required for backward compatibility with import version 2.
393     * @deprecated Use the appropriate tag from latest import class instead*/
394    @Deprecated
395    public static final String N_UUIDSTRUCTURE = A_CmsImport.N_UUIDSTRUCTURE;
396
397    /** Tag in the {@link #EXPORT_MANIFEST} for the "value" node, contains the value of a property.
398     * @deprecated Use the appropriate tag from latest import class instead*/
399    @Deprecated
400    public static final String N_VALUE = A_CmsImport.N_VALUE;
401
402    /** Tag in the {@link #EXPORT_MANIFEST} for the "export_version" node, appears in the manifest info header. */
403    public static final String N_VERSION = "export_version";
404
405    /** Property to specify the export time written for a resource's date last modified. */
406    public static final String PROP_EXPORT_TIMESTAMP = "export.timestamp";
407
408    /** The log object for this class. */
409    private static final Log LOG = CmsLog.getLog(CmsImportExportManager.class);
410
411    /** Boolean flag whether imported pages should be converted into XML pages. */
412    private boolean m_convertToXmlPage;
413
414    /** Map from resource types to default timestamp modes. */
415    private Map<String, TimestampMode> m_defaultTimestampModes;
416
417    /** The default values of the HTML->OpenCms Template converter. */
418    private CmsExtendedHtmlImportDefault m_extendedHtmlImportDefault;
419
420    /** List of property keys that should be removed from imported resources. */
421    private List<String> m_ignoredProperties;
422
423    /** List of immutable resources that should remain unchanged when resources are imported. */
424    private List<String> m_immutableResources;
425
426    /** The initialized import/export handlers. */
427    private List<I_CmsImportExportHandler> m_importExportHandlers;
428
429    /** Import principal group translations. */
430    private Map<String, String> m_importGroupTranslations;
431
432    /** Import principal user translations. */
433    private Map<String, String> m_importUserTranslations;
434
435    /** The configured import versions class names. */
436    private List<I_CmsImport> m_importVersionClasses;
437
438    /** Boolean flag whether colliding resources should be overwritten during the import. */
439    private boolean m_overwriteCollidingResources;
440
441    /** List of resourcetypes. Only used as helper for initializing the default timestamp modes. */
442    private List<String> m_resourcetypes;
443
444    /** The configured temporary export point paths. */
445    private List<String> m_tempExportpointPaths = Lists.newArrayList();
446
447    /** The user export settings. */
448    private CmsUserExportSettings m_userExportSettings;
449
450    /** The URL of a 4.x OpenCms application to import content correct into 5.x OpenCms application. */
451    private String m_webAppUrl;
452
453    /**
454     * Creates a new instance for the import/export manager, will be called by the import/export configuration manager.
455     */
456    public CmsImportExportManager() {
457
458        if (LOG.isInfoEnabled()) {
459            LOG.info(Messages.get().getBundle().key(Messages.INIT_IMPORTEXPORT_INITIALIZING_0));
460        }
461
462        m_importExportHandlers = new ArrayList<I_CmsImportExportHandler>();
463        m_immutableResources = new ArrayList<String>();
464        m_ignoredProperties = new ArrayList<String>();
465        m_convertToXmlPage = true;
466        m_importGroupTranslations = new HashMap<String, String>();
467        m_importUserTranslations = new HashMap<String, String>();
468        m_overwriteCollidingResources = true;
469        m_importVersionClasses = new ArrayList<I_CmsImport>();
470        m_defaultTimestampModes = new HashMap<String, TimestampMode>();
471        m_resourcetypes = new ArrayList<String>();
472    }
473
474    /** Adds the provided default timestamp mode for the resourcetypes in list {@link #m_resourcetypes}.
475     * The method is called by the digester.
476     * @param timestampMode the timestamp mode to add as default.
477     */
478    public void addDefaultTimestampMode(String timestampMode) {
479
480        if (null != timestampMode) {
481            try {
482                TimestampMode mode = TimestampMode.valueOf(timestampMode.toUpperCase());
483                for (String resourcetype : m_resourcetypes) {
484                    m_defaultTimestampModes.put(resourcetype, mode);
485
486                    if (LOG.isDebugEnabled()) {
487                        LOG.debug(
488                            Messages.get().getBundle().key(
489                                Messages.LOG_IMPORTEXPORT_EXPORT_SETTIMESTAMPMODE_2,
490                                timestampMode,
491                                resourcetype));
492                    }
493                }
494            } catch (IllegalArgumentException e) {
495                LOG.error(
496                    Messages.get().getBundle().key(
497                        Messages.ERR_IMPORTEXPORT_EXPORT_INVALID_TIMESTAMPMODE_2,
498                        timestampMode,
499                        m_resourcetypes.toString()),
500                    e);
501            }
502        } else {
503            LOG.error(
504                Messages.get().getBundle().key(
505                    Messages.ERR_IMPORTEXPORT_EXPORT_MISSING_TIMESTAMPMODE_1,
506                    m_resourcetypes.toString()));
507        }
508        m_resourcetypes.clear();
509    }
510
511    /**
512     * Adds a property name to the list of properties that should be removed from imported resources.<p>
513     *
514     * @param propertyName a property name
515     */
516    public void addIgnoredProperty(String propertyName) {
517
518        if (LOG.isDebugEnabled()) {
519            LOG.debug(Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_IGNORING_PROPERTY_1, propertyName));
520        }
521        m_ignoredProperties.add(propertyName);
522    }
523
524    /**
525     * Adds a resource to the list of immutable resources that should remain
526     * unchanged when resources are imported.<p>
527     *
528     * @param immutableResource a resources uri in the OpenCms VFS
529     */
530    public void addImmutableResource(String immutableResource) {
531
532        if (LOG.isDebugEnabled()) {
533            LOG.debug(
534                Messages.get().getBundle().key(
535                    Messages.LOG_IMPORTEXPORT_ADDED_IMMUTABLE_RESOURCE_1,
536                    immutableResource));
537        }
538        m_immutableResources.add(immutableResource);
539    }
540
541    /**
542     * Adds an import/export handler to the list of configured handlers.<p>
543     *
544     * @param handler the import/export handler to add
545     */
546    public void addImportExportHandler(I_CmsImportExportHandler handler) {
547
548        if (LOG.isDebugEnabled()) {
549            LOG.debug(Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_ADDED_IMPORTEXPORT_HANDLER_1, handler));
550        }
551        m_importExportHandlers.add(handler);
552    }
553
554    /**
555     * Adds an import princial translation to the configuration.<p>
556     *
557     * @param type the princial type ("USER" or "GROUP")
558     * @param from the "from" translation source
559     * @param to the "to" translation target
560     */
561    public void addImportPrincipalTranslation(String type, String from, String to) {
562
563        if (LOG.isDebugEnabled()) {
564            LOG.debug(
565                Messages.get().getBundle().key(
566                    Messages.LOG_IMPORTEXPORT_ADDED_PRINCIPAL_TRANSLATION_3,
567                    type,
568                    from,
569                    to));
570        }
571        if (I_CmsPrincipal.PRINCIPAL_GROUP.equalsIgnoreCase(type)) {
572            m_importGroupTranslations.put(from, to);
573            if (LOG.isInfoEnabled()) {
574                LOG.info(
575                    Messages.get().getBundle().key(Messages.INIT_IMPORTEXPORT_ADDED_GROUP_TRANSLATION_2, from, to));
576            }
577        } else if (I_CmsPrincipal.PRINCIPAL_USER.equalsIgnoreCase(type)) {
578            m_importUserTranslations.put(from, to);
579            if (LOG.isInfoEnabled()) {
580                LOG.info(Messages.get().getBundle().key(Messages.INIT_IMPORTEXPORT_ADDED_USER_TRANSLATION_2, from, to));
581            }
582        }
583    }
584
585    /**
586     * Adds a import version class name to the configuration.<p>
587     *
588     * @param importVersionClass the import version class name to add
589     */
590    public void addImportVersionClass(I_CmsImport importVersionClass) {
591
592        if (LOG.isDebugEnabled()) {
593            LOG.debug(
594                Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_ADDED_IMPORT_VERSION_1, importVersionClass));
595        }
596        m_importVersionClasses.add(importVersionClass);
597    }
598
599    /** Adds a resourcetype name to the list of resourcetypes that obtain a default timestamp mode in {@link #addDefaultTimestampMode(String)}.
600     * The method is called only by the digester.
601     *
602     * @param resourcetypeName name of the resourcetype
603     */
604    public void addResourceTypeForDefaultTimestampMode(String resourcetypeName) {
605
606        m_resourcetypes.add(resourcetypeName);
607
608    }
609
610    /**
611     * Adds a temporary export point path.<p>
612     *
613     * @param path the new temporary export point path
614     */
615    public void addTempExportpointPath(String path) {
616
617        m_tempExportpointPaths.add(path);
618    }
619
620    /**
621     * Checks if imported pages should be converted into XML pages.<p>
622     *
623     * @return true, if imported pages should be converted into XML pages
624     */
625    public boolean convertToXmlPage() {
626
627        return m_convertToXmlPage;
628    }
629
630    /**
631     * Creates a new export point driver based on the import/export configuration.<p>
632     *
633     * @param exportPoints the export points
634     *
635     * @return the export point driver instance
636     */
637    public I_CmsExportPointDriver createExportPointDriver(Set<CmsExportPoint> exportPoints) {
638
639        if (m_tempExportpointPaths.isEmpty()) {
640            return new CmsExportPointDriver(exportPoints);
641        } else {
642            return new CmsTempFolderExportPointDriver(exportPoints, getTempExportPointPaths());
643        }
644
645    }
646
647    /**
648     * Checks if the current user has permissions to export Cms data of a specified export handler,
649     * and if so, triggers the handler to write the export.<p>
650     *
651     * @param cms the cms context
652     * @param handler handler containing the export data
653     * @param report the output report
654     *
655     * @throws CmsRoleViolationException if the current user is not a allowed to export the OpenCms database
656     * @throws CmsImportExportException if operation was not successful
657     * @throws CmsConfigurationException if something goes wrong
658     *
659     * @see I_CmsImportExportHandler
660     */
661    public void exportData(CmsObject cms, I_CmsImportExportHandler handler, I_CmsReport report)
662    throws CmsConfigurationException, CmsImportExportException, CmsRoleViolationException {
663
664        OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
665        handler.exportData(cms, report);
666    }
667
668    /** Returns the default timestamp mode for the resourcetype - or <code>null</code> if no default mode is set.
669     * @param resourcetypeName name of the resourcetype to get the timestamp mode for
670     * @return if set, the default timestamp mode for the resourcetype, otherwise <code>null</code>
671     */
672    public TimestampMode getDefaultTimestampMode(String resourcetypeName) {
673
674        return m_defaultTimestampModes.get(resourcetypeName);
675    }
676
677    /** Returns the map from resourcetype names to default timestamp modes.
678     * @return the map from resourcetype names to default timestamp modes.
679     */
680    public Map<TimestampMode, List<String>> getDefaultTimestampModes() {
681
682        Map<TimestampMode, List<String>> result = new HashMap<TimestampMode, List<String>>();
683        for (String resourcetype : m_defaultTimestampModes.keySet()) {
684            TimestampMode mode = m_defaultTimestampModes.get(resourcetype);
685            if (result.containsKey(mode)) {
686                result.get(mode).add(resourcetype);
687            } else {
688                List<String> list = new ArrayList<String>();
689                list.add(resourcetype);
690                result.put(mode, list);
691            }
692        }
693        return result;
694    }
695
696    /**
697     * Returns the extendedHtmlImportDefault.<p>
698     *
699     * @return the extendedHtmlImportDefault
700     */
701    public CmsExtendedHtmlImportDefault getExtendedHtmlImportDefault() {
702
703        return getExtendedHtmlImportDefault(false);
704    }
705
706    /**
707     * Returns the extendedHtmlImportDefault.<p>
708     *
709     *@param withNull returns the extendenHtmlImport as null if its null,
710     *                otherwise a new CmsExtendedHtmlImportDefault Object is generated
711     *
712     * @return the extendedHtmlImportDefault
713     */
714    public CmsExtendedHtmlImportDefault getExtendedHtmlImportDefault(boolean withNull) {
715
716        return (withNull || (m_extendedHtmlImportDefault != null)
717        ? m_extendedHtmlImportDefault
718        : new CmsExtendedHtmlImportDefault());
719    }
720
721    /**
722     * Returns the list of property keys that should be removed from imported resources.<p>
723     *
724     * @return the list of property keys that should be removed from imported resources, or Collections.EMPTY_LIST
725     */
726    public List<String> getIgnoredProperties() {
727
728        return m_ignoredProperties;
729    }
730
731    /**
732     * Returns the list of immutable resources that should remain unchanged when resources are
733     * imported.<p>
734     *
735     * Certain system resources should not be changed during import. This is the case for the main
736     * folders in the /system/ folder. Changes to these folders usually should not be imported to
737     * another system.<p>
738     *
739     * @return the list of immutable resources, or {@link Collections#EMPTY_LIST}
740     */
741    public List<String> getImmutableResources() {
742
743        return m_immutableResources;
744    }
745
746    /**
747     * Returns an instance of an import/export handler implementation that is able to import
748     * a specified resource.<p>
749     *
750     * @param parameters the import parameters
751     *
752     * @return an instance of an import/export handler implementation
753     *
754     * @throws CmsImportExportException if something goes wrong
755     */
756    @SuppressWarnings("resource")
757    public I_CmsImportExportHandler getImportExportHandler(CmsImportParameters parameters)
758    throws CmsImportExportException {
759
760        Document manifest;
761        InputStream stream = null;
762        CmsImportHelper helper = new CmsImportHelper(parameters);
763        try {
764            helper.openFile();
765            stream = helper.getFileStream(CmsImportExportManager.EXPORT_MANIFEST);
766            SAXReader reader = new SAXReader(false);
767            reader.setValidation(false);
768            reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
769            manifest = reader.read(stream);
770        } catch (Throwable e) {
771            throw new CmsImportExportException(
772                Messages.get().container(Messages.ERR_IMPORTEXPORT_FILE_NOT_FOUND_1, EXPORT_MANIFEST),
773                e);
774        } finally {
775            try {
776                if (stream != null) {
777                    stream.close();
778                }
779            } catch (Exception e) {
780                // noop
781            }
782            helper.closeFile();
783        }
784        for (int i = 0; i < m_importExportHandlers.size(); i++) {
785            I_CmsImportExportHandler handler = m_importExportHandlers.get(i);
786            if (handler.matches(manifest)) {
787                return handler;
788            }
789        }
790
791        CmsMessageContainer message = Messages.get().container(
792            Messages.ERR_IMPORTEXPORT_ERROR_NO_HANDLER_FOUND_1,
793            EXPORT_MANIFEST);
794        if (LOG.isDebugEnabled()) {
795            LOG.debug(message.key());
796        }
797
798        throw new CmsImportExportException(message);
799    }
800
801    /**
802     * Returns the list of configured import/export handlers.<p>
803     *
804     * @return the list of configured import/export handlers
805     */
806    public List<I_CmsImportExportHandler> getImportExportHandlers() {
807
808        return m_importExportHandlers;
809    }
810
811    /**
812     * Returns the configured principal group translations.<p>
813     *
814     * @return the configured principal group translations
815     */
816    public Map<String, String> getImportGroupTranslations() {
817
818        return m_importGroupTranslations;
819    }
820
821    /**
822     * Returns the configured principal user translations.<p>
823     *
824     * @return the configured principal user translations
825     */
826    public Map<String, String> getImportUserTranslations() {
827
828        return m_importUserTranslations;
829    }
830
831    /**
832     * Returns the configured import version class names.<p>
833     *
834     * @return the configured import version class names
835     */
836    public List<I_CmsImport> getImportVersionClasses() {
837
838        return m_importVersionClasses;
839    }
840
841    /**
842     * Returns the URL of a 4.x OpenCms app. (e.g. http://localhost:8080/opencms/opencms/)
843     * from which content was exported.<p>
844     *
845     * This setting is required to import content of 4.x OpenCms apps. correct into 5.x OpenCms apps.<p>
846     *
847     * @return the webAppUrl.
848     */
849    public String getOldWebAppUrl() {
850
851        return m_webAppUrl;
852    }
853
854    /**
855     * Gets the configured list of temporary export point paths.<p>
856     *
857     * If any temporary export point paths are configured, then export points writing to these paths will write to a temporary folder instead.
858     *
859     * @return the list of temporary export point paths
860     */
861    public List<String> getTempExportPointPaths() {
862
863        return Collections.unmodifiableList(m_tempExportpointPaths);
864    }
865
866    /**
867     * Returns the user settings for export.<p>
868     *
869     * @return the user settings for export
870     */
871    public CmsUserExportSettings getUserExportSettings() {
872
873        return m_userExportSettings;
874    }
875
876    /**
877     * Checks if the current user has permissions to import data into the Cms,
878     * and if so, creates a new import handler instance that imports the data.<p>
879     *
880     * @param cms the current OpenCms context object
881     * @param report a Cms report to print log messages
882     * @param parameters the import parameters
883     *
884     * @throws CmsRoleViolationException if the current user is not allowed to import the OpenCms database
885     * @throws CmsImportExportException if operation was not successful
886     * @throws CmsXmlException if the manifest of the import could not be unmarshalled
887     * @throws CmsException in case of errors accessing the VFS
888     *
889     * @see I_CmsImportExportHandler
890     * @see #importData(CmsObject, String, String, I_CmsReport)
891     */
892    public void importData(CmsObject cms, I_CmsReport report, CmsImportParameters parameters)
893    throws CmsImportExportException, CmsXmlException, CmsRoleViolationException, CmsException {
894
895        // check the required role permissions
896        OpenCms.getRoleManager().checkRole(cms, CmsRole.DATABASE_MANAGER);
897
898        try {
899            OpenCms.fireCmsEvent(
900                new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap()));
901            I_CmsImportExportHandler handler = getImportExportHandler(parameters);
902            synchronized (handler) {
903                handler.setImportParameters(parameters);
904                handler.importData(cms, report);
905            }
906        } finally {
907            OpenCms.fireCmsEvent(
908                new CmsEvent(I_CmsEventListener.EVENT_CLEAR_CACHES, Collections.<String, Object> emptyMap()));
909        }
910    }
911
912    /**
913     * Checks if the current user has permissions to import data into the Cms,
914     * and if so, creates a new import handler instance that imports the data.<p>
915     *
916     * @param cms the current OpenCms context object
917     * @param importFile the name (absolute path) of the resource (zipfile or folder) to be imported
918     * @param importPath the name (absolute path) of the destination folder in the Cms if required, or null
919     * @param report a Cms report to print log messages
920     *
921     * @throws CmsRoleViolationException if the current user is not allowed to import the OpenCms database
922     * @throws CmsImportExportException if operation was not successful
923     * @throws CmsXmlException if the manifest of the import could not be unmarshalled
924     * @throws CmsException in case of errors accessing the VFS
925     *
926     * @see I_CmsImportExportHandler
927     * @see #importData(CmsObject, I_CmsReport, CmsImportParameters)
928     *
929     * @deprecated use {@link #importData(CmsObject, I_CmsReport, CmsImportParameters)} instead
930     */
931    @Deprecated
932    public void importData(CmsObject cms, String importFile, String importPath, I_CmsReport report)
933    throws CmsImportExportException, CmsXmlException, CmsRoleViolationException, CmsException {
934
935        CmsImportParameters parameters = new CmsImportParameters(importFile, importPath, false);
936        importData(cms, report, parameters);
937    }
938
939    /**
940     * Checks if the given root path belongs to an immutable resource.
941     *
942     * @param rootPath the root path to check
943     * @return true if the path is the path of an immutable resource
944     */
945    public boolean isImmutable(String rootPath) {
946
947        rootPath = CmsStringUtil.joinPaths("/", rootPath, "/");
948        for (String immutable : getImmutableResources()) {
949            immutable = CmsStringUtil.joinPaths("/", immutable, "/");
950            if (immutable.equals(rootPath)) {
951                return true;
952            }
953        }
954        return false;
955
956    }
957
958    /**
959     * Checks if colliding resources should be overwritten during the import.<p>
960     *
961     * @return true, if colliding resources should be overwritten during the import
962     * @see #setOverwriteCollidingResources(boolean)
963     */
964    public boolean overwriteCollidingResources() {
965
966        return m_overwriteCollidingResources;
967    }
968
969    /**
970     * Sets if imported pages should be converted into XML pages.<p>
971     *
972     * @param convertToXmlPage true, if imported pages should be converted into XML pages.
973     */
974    public void setConvertToXmlPage(boolean convertToXmlPage) {
975
976        if (LOG.isDebugEnabled()) {
977            LOG.debug(
978                Messages.get().getBundle().key(
979                    Messages.LOG_IMPORTEXPORT_SET_CONVERT_PARAMETER_1,
980                    Boolean.toString(convertToXmlPage)));
981        }
982        m_convertToXmlPage = convertToXmlPage;
983    }
984
985    /**
986     * Sets if imported pages should be converted into XML pages.<p>
987     *
988     * @param convertToXmlPage <code>"true"</code>, if imported pages should be converted into XML pages.
989     */
990    public void setConvertToXmlPage(String convertToXmlPage) {
991
992        setConvertToXmlPage(Boolean.valueOf(convertToXmlPage).booleanValue());
993    }
994
995    /**
996     * Sets the extendedHtmlImportDefault.<p>
997     *
998     * @param extendedHtmlImportDefault the extendedHtmlImportDefault to set
999     */
1000    public void setExtendedHtmlImportDefault(CmsExtendedHtmlImportDefault extendedHtmlImportDefault) {
1001
1002        m_extendedHtmlImportDefault = extendedHtmlImportDefault;
1003    }
1004
1005    /**
1006     * Sets the URL of a 4.x OpenCms app. (e.g. http://localhost:8080/opencms/opencms/)
1007     * from which content was exported.<p>
1008     *
1009     * This setting is required to import content of 4.x OpenCms apps. correct into 5.x OpenCms apps.<p>
1010     *
1011     * @param webAppUrl a URL of the a OpenCms app. (e.g. http://localhost:8080/opencms/opencms/)
1012     */
1013    public void setOldWebAppUrl(String webAppUrl) {
1014
1015        if (LOG.isDebugEnabled()) {
1016            LOG.debug(Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_SET_OLD_WEBAPP_URL_1, webAppUrl));
1017        }
1018        m_webAppUrl = webAppUrl;
1019    }
1020
1021    /**
1022     * Sets whether colliding resources should be overwritten during the import for a
1023     * specified import implementation.<p>
1024     *
1025     * v1 and v2 imports (without resource UUIDs in the manifest) *MUST* overwrite colliding
1026     * resources. Don't forget to set this flag back to it's original value in v1 and v2
1027     * import implementations!<p>
1028     *
1029     * This flag must be set to false to force imports > v2 to move colliding resources to
1030     * /system/lost-found/.<p>
1031     *
1032     * The import implementation has to take care to set this flag correct!<p>
1033     *
1034     * @param overwriteCollidingResources true if colliding resources should be overwritten during the import
1035     */
1036    public void setOverwriteCollidingResources(boolean overwriteCollidingResources) {
1037
1038        if (LOG.isDebugEnabled()) {
1039            LOG.debug(
1040                Messages.get().getBundle().key(
1041                    Messages.LOG_IMPORTEXPORT_SET_OVERWRITE_PARAMETER_1,
1042                    Boolean.toString(overwriteCollidingResources)));
1043        }
1044        m_overwriteCollidingResources = overwriteCollidingResources;
1045    }
1046
1047    /**
1048     * @see CmsImportExportManager#setOverwriteCollidingResources(boolean)
1049     *
1050     * @param overwriteCollidingResources <code>"true"</code> if colliding resources should be overwritten during the import
1051     */
1052    public void setOverwriteCollidingResources(String overwriteCollidingResources) {
1053
1054        setOverwriteCollidingResources(Boolean.valueOf(overwriteCollidingResources).booleanValue());
1055    }
1056
1057    /**
1058     * Sets the user export settings.<p>
1059     *
1060     * @param userExportSettings the user export settings to set
1061     */
1062    public void setUserExportSettings(CmsUserExportSettings userExportSettings) {
1063
1064        m_userExportSettings = userExportSettings;
1065    }
1066
1067    /**
1068     * Returns the translated name for the given group name.<p>
1069     *
1070     * If no matching name is found, the given group name is returned.<p>
1071     *
1072     * @param name the group name to translate
1073     * @return the translated name for the given group name
1074     */
1075    public String translateGroup(String name) {
1076
1077        if (m_importGroupTranslations == null) {
1078            return name;
1079        }
1080        String match = m_importGroupTranslations.get(name);
1081        if (match != null) {
1082            return match;
1083        } else {
1084            return name;
1085        }
1086    }
1087
1088    /**
1089     * Returns the translated name for the given user name.<p>
1090     *
1091     * If no matching name is found, the given user name is returned.<p>
1092     *
1093     * @param name the user name to translate
1094     * @return the translated name for the given user name
1095     */
1096    public String translateUser(String name) {
1097
1098        if (m_importUserTranslations == null) {
1099            return name;
1100        }
1101        String match = m_importUserTranslations.get(name);
1102        if (match != null) {
1103            return match;
1104        } else {
1105            return name;
1106        }
1107    }
1108}