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.db.CmsUserSettings; 031import org.opencms.file.CmsGroup; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsProperty; 034import org.opencms.file.CmsPropertyDefinition; 035import org.opencms.file.CmsResource; 036import org.opencms.file.types.CmsResourceTypePointer; 037import org.opencms.i18n.CmsMessageContainer; 038import org.opencms.i18n.I_CmsMessageBundle; 039import org.opencms.main.CmsException; 040import org.opencms.main.CmsLog; 041import org.opencms.main.OpenCms; 042import org.opencms.report.I_CmsReport; 043import org.opencms.security.CmsAccessControlEntry; 044import org.opencms.security.CmsRole; 045import org.opencms.util.CmsFileUtil; 046import org.opencms.util.CmsStringUtil; 047import org.opencms.util.CmsUUID; 048import org.opencms.xml.CmsXmlUtils; 049 050import java.io.ByteArrayInputStream; 051import java.io.File; 052import java.io.FileNotFoundException; 053import java.io.IOException; 054import java.io.InputStream; 055import java.io.ObjectInputStream; 056import java.util.ArrayList; 057import java.util.HashMap; 058import java.util.Iterator; 059import java.util.List; 060import java.util.Locale; 061import java.util.Map; 062import java.util.Map.Entry; 063import java.util.Stack; 064import java.util.zip.ZipEntry; 065import java.util.zip.ZipException; 066import java.util.zip.ZipFile; 067 068import org.apache.commons.codec.binary.Base64; 069import org.apache.commons.logging.Log; 070 071import org.dom4j.Attribute; 072import org.dom4j.Document; 073import org.dom4j.Element; 074import org.dom4j.Node; 075 076/** 077 * Collection of common used methods for implementing OpenCms Import classes.<p> 078 * 079 * This class does not implement a real OpenCms import, real import implementation should be 080 * inherited form this class.<p> 081 * 082 * @since 6.0.0 083 * 084 * @see org.opencms.importexport.I_CmsImport 085 * 086 * @deprecated the import is done starting with {@link CmsImportVersion7} with the digester 087 */ 088@Deprecated 089public abstract class A_CmsImport implements I_CmsImport { 090 091 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "userinfo/entry@name" attribute, contains the additional user info entry name. */ 092 public static final String A_NAME = "name"; 093 094 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "userinfo/entry@type" attribute, contains the additional user info entry data type name. */ 095 public static final String A_TYPE = "type"; 096 097 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "access" node. */ 098 public static final String N_ACCESS = "access"; 099 100 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "allowed" node, to identify allowed user permissions. */ 101 public static final String N_ACCESSCONTROL_ALLOWEDPERMISSIONS = "allowed"; 102 103 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "denied" node, to identify denied user permissions. */ 104 public static final String N_ACCESSCONTROL_DENIEDPERMISSIONS = "denied"; 105 106 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "accesscontrol" node, to identify access control entries. */ 107 public static final String N_ACCESSCONTROL_ENTRIES = "accesscontrol"; 108 109 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "accessentry" node, to identify a single access control entry. */ 110 public static final String N_ACCESSCONTROL_ENTRY = "accessentry"; 111 112 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "permissionset" node, to identify a permission set. */ 113 public static final String N_ACCESSCONTROL_PERMISSIONSET = "permissionset"; 114 115 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "uuidprincipal" node, to identify a principal UUID. */ 116 public static final String N_ACCESSCONTROL_PRINCIPAL = "uuidprincipal"; 117 118 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "datecreated" node, contains the date created VFS file attribute. */ 119 public static final String N_DATECREATED = "datecreated"; 120 121 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "dateexpired" node, contains the expiration date VFS file attribute. */ 122 public static final String N_DATEEXPIRED = "dateexpired"; 123 124 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "datelastmodified" node, contains the date last modified VFS file attribute. */ 125 public static final String N_DATELASTMODIFIED = "datelastmodified"; 126 127 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "datereleased" node, contains the release date VFS file attribute. */ 128 public static final String N_DATERELEASED = "datereleased"; 129 130 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "defaultgroup" node, for backward compatibility with OpenCms 5.x. */ 131 public static final String N_DEFAULTGROUP = "defaultgroup"; 132 133 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "description" node, contains a users description test. */ 134 public static final String N_DESCRIPTION = "description"; 135 136 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "destination" node, contains target VFS file name. */ 137 public static final String N_DESTINATION = "destination"; 138 139 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "email" node, contains a users email. */ 140 public static final String N_EMAIL = "email"; 141 142 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "file" node, container node for all VFS resources. */ 143 public static final String N_FILE = "file"; 144 145 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "firstname" node, contains a users first name. */ 146 public static final String N_FIRSTNAME = "firstname"; 147 148 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "flags" node, contains the flags of a VFS resource. */ 149 public static final String N_FLAGS = "flags"; 150 151 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "groupdata" node, contains a users group data. */ 152 public static final String N_GROUPDATA = "groupdata"; 153 154 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "groupname" node, contains a groups name. */ 155 public static final String N_GROUPNAME = "groupname"; 156 157 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "id" node, only required for backward compatibility with import version 2. */ 158 public static final String N_ID = "id"; 159 160 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "lastmodified" node, only required for backward compatibility with import version 2. */ 161 public static final String N_LASTMODIFIED = "lastmodified"; 162 163 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "lastname" node, contains a users last name. */ 164 public static final String N_LASTNAME = "lastname"; 165 166 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "name" node, contains a users login name. */ 167 public static final String N_NAME = "name"; 168 169 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "orgunitdatas" node, starts the organizational unit data. */ 170 public static final String N_ORGUNITDATA = "orgunitdata"; 171 172 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "parentgroup" node, contains a groups parent group name. */ 173 public static final String N_PARENTGROUP = "parentgroup"; 174 175 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "password" node, contains a users encrypted password. */ 176 public static final String N_PASSWORD = "password"; 177 178 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "properties" node, starts the list of properties of a VFS resource. */ 179 public static final String N_PROPERTIES = "properties"; 180 181 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "property" node, starts a property for a VFS resource. */ 182 public static final String N_PROPERTY = "property"; 183 184 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "type" property attribute, contains a property type. */ 185 public static final String N_PROPERTY_ATTRIB_TYPE = "type"; 186 187 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "shared" property type attribute value. */ 188 public static final String N_PROPERTY_ATTRIB_TYPE_SHARED = "shared"; 189 190 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "relation" node, starts a relation for a VFS resource. */ 191 public static final String N_RELATION = "relation"; 192 193 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "id" relation attribute, contains the structure id of the target resource of the relation. */ 194 public static final String N_RELATION_ATTRIBUTE_ID = "id"; 195 196 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "path" relation attribute, contains the path to the target resource of the relation. */ 197 public static final String N_RELATION_ATTRIBUTE_PATH = "path"; 198 199 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "type" relation attribute, contains the type of relation. */ 200 public static final String N_RELATION_ATTRIBUTE_TYPE = "type"; 201 202 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "relations" node, starts the list of relations of a VFS resources. */ 203 public static final String N_RELATIONS = "relations"; 204 205 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "source" node, contains the source path of a VFS resource in the import zip (or folder). */ 206 public static final String N_SOURCE = "source"; 207 208 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "address" node, contains a users address. */ 209 public static final String N_TAG_ADDRESS = "address"; 210 211 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "type" node, the resource type name of a VFS resource. */ 212 public static final String N_TYPE = "type"; 213 214 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "user" node, starts the user data. */ 215 public static final String N_USER = "user"; 216 217 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "usercreated" node, contains the name of the user who created the VFS resource. */ 218 public static final String N_USERCREATED = "usercreated"; 219 220 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "userdata" node, starts the list of users. */ 221 public static final String N_USERDATA = "userdata"; 222 223 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "usergroupdatas" node, starts the users group data. */ 224 public static final String N_USERGROUPDATA = "usergroupdata"; 225 226 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "usergroups" node, starts the users group data. */ 227 public static final String N_USERGROUPS = "usergroups"; 228 229 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "userinfo" node, contains the additional user info. */ 230 public static final String N_USERINFO = "userinfo"; 231 232 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "userinfo/entry" node, contains the additional user info entry value. */ 233 public static final String N_USERINFO_ENTRY = "entry"; 234 235 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "userlastmodified" node, contains the name of the user who last modified the VFS resource. */ 236 public static final String N_USERLASTMODIFIED = "userlastmodified"; 237 238 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "uuidresource" node, contains a the resource UUID of a VFS resource. */ 239 public static final String N_UUIDRESOURCE = "uuidresource"; 240 241 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "uuidstructure" node, only required for backward compatibility with import version 2. */ 242 public static final String N_UUIDSTRUCTURE = "uuidstructure"; 243 244 /** Tag in the {@link CmsImportExportManager#EXPORT_MANIFEST} for the "value" node, contains the value of a property. */ 245 public static final String N_VALUE = "value"; 246 247 /** The name of the legacy resource type "page". */ 248 public static final String RESOURCE_TYPE_LEGACY_PAGE_NAME = "page"; 249 250 /** The id of the legacy resource type "link". */ 251 protected static final int RESOURCE_TYPE_LINK_ID = 1024; 252 253 /** The name of the legacy resource type "link". */ 254 protected static final String RESOURCE_TYPE_LINK_NAME = "link"; 255 256 /** The id of the legacy resource type "newpage". */ 257 protected static final int RESOURCE_TYPE_NEWPAGE_ID = 9; 258 259 /** The name of the legacy resource type "newpage". */ 260 protected static final String RESOURCE_TYPE_NEWPAGE_NAME = "newpage"; 261 262 /** The log object for this class. */ 263 private static final Log LOG = CmsLog.getLog(A_CmsImport.class); 264 265 /** The cms context to do the import operations with. */ 266 protected CmsObject m_cms; 267 268 /** Flag for conversion to xml pages. */ 269 protected boolean m_convertToXmlPage; 270 271 /** The xml manifest-file. */ 272 protected Document m_docXml; 273 274 /** Groups to create during import are stored here. */ 275 protected Stack<Map<String, String>> m_groupsToCreate; 276 277 /** The import-path to write resources into the cms. */ 278 protected String m_importPath; 279 280 /** The import-resource (folder) to load resources from. */ 281 protected File m_importResource; 282 283 /** The import-resource (zip) to load resources from. */ 284 protected ZipFile m_importZip; 285 286 /** Storage for all pointer properties which must be converted into links. */ 287 protected Map<String, List<CmsProperty>> m_linkPropertyStorage; 288 289 /** Storage for all pointers which must be converted into links. */ 290 protected Map<String, String> m_linkStorage; 291 292 /** The object to report the log messages. */ 293 protected I_CmsReport m_report; 294 295 /** Messages object with the locale of the current user. */ 296 protected I_CmsMessageBundle m_userMessages; 297 298 /** 299 * Converts a given digest to base64 encoding.<p> 300 * 301 * @param value the digest value in the legacy encoding 302 * @return the digest in the new encoding 303 */ 304 public String convertDigestEncoding(String value) { 305 306 byte[] data = new byte[value.length() / 2]; 307 308 for (int i = 0; i < data.length; i++) { 309 data[i] = (byte)(Integer.parseInt(value.substring(i * 2, (i * 2) + 2), 16) - 128); 310 } 311 312 return new String(Base64.encodeBase64(data)); 313 } 314 315 /** 316 * Returns the value of a child element with a specified name for a given parent element.<p> 317 * 318 * @param parentElement the parent element 319 * @param elementName the child element name 320 * 321 * @return the value of the child node, or null if something went wrong 322 */ 323 public String getChildElementTextValue(Element parentElement, String elementName) { 324 325 try { 326 // get the first child element matching the specified name 327 Element childElement = (Element)parentElement.selectNodes("./" + elementName).get(0); 328 // return the value of the child element 329 return childElement.getTextTrim(); 330 } catch (Exception e) { 331 return null; 332 } 333 } 334 335 /** 336 * @see org.opencms.importexport.I_CmsImport#matches(org.opencms.importexport.CmsImportParameters) 337 */ 338 public boolean matches(CmsImportParameters parameters) throws CmsImportExportException { 339 340 // try to read the export version number 341 CmsImportHelper helper = new CmsImportHelper(parameters); 342 try { 343 helper.openFile(); 344 // read the xml-config file 345 Document docXml = CmsXmlUtils.unmarshalHelper( 346 helper.getFileBytes(CmsImportExportManager.EXPORT_MANIFEST), 347 null, 348 false); 349 350 return getVersion() == Integer.parseInt( 351 ((Element)docXml.selectNodes("//" + CmsImportExportManager.N_VERSION).get(0)).getTextTrim()); 352 } catch (IOException e) { 353 CmsMessageContainer message = Messages.get().container( 354 Messages.ERR_IMPORTEXPORT_ERROR_OPENING_ZIP_ARCHIVE_1, 355 parameters.getPath()); 356 if (LOG.isDebugEnabled()) { 357 LOG.debug(message.key(), e); 358 } 359 360 throw new CmsImportExportException(message, e); 361 } catch (Exception e) { 362 // ignore the exception, the export file has no version number (version 0) 363 // should never happen 364 if (LOG.isErrorEnabled()) { 365 LOG.error(e.getLocalizedMessage(), e); 366 } 367 } finally { 368 helper.closeFile(); 369 } 370 return false; 371 } 372 373 /** 374 * Checks if the resources is in the list of immutalbe resources. <p> 375 * 376 * @param translatedName the name of the resource 377 * @param immutableResources the list of the immutable resources 378 * @return true or false 379 */ 380 protected boolean checkImmutable(String translatedName, List<String> immutableResources) { 381 382 boolean resourceNotImmutable = true; 383 if (immutableResources.contains(translatedName)) { 384 if (LOG.isDebugEnabled()) { 385 LOG.debug( 386 Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_RESOURCENAME_IMMUTABLE_1, translatedName)); 387 } 388 // this resource must not be modified by an import if it already exists 389 String storedSiteRoot = m_cms.getRequestContext().getSiteRoot(); 390 try { 391 m_cms.getRequestContext().setSiteRoot("/"); 392 m_cms.readResource(translatedName); 393 resourceNotImmutable = false; 394 if (LOG.isDebugEnabled()) { 395 LOG.debug( 396 Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_IMMUTABLE_FLAG_SET_1, translatedName)); 397 } 398 } catch (CmsException e) { 399 // resourceNotImmutable will be true 400 if (LOG.isDebugEnabled()) { 401 LOG.debug( 402 Messages.get().getBundle().key( 403 Messages.LOG_IMPORTEXPORT_ERROR_ON_TEST_IMMUTABLE_1, 404 translatedName), 405 e); 406 } 407 } finally { 408 m_cms.getRequestContext().setSiteRoot(storedSiteRoot); 409 } 410 } 411 return resourceNotImmutable; 412 } 413 414 /** 415 * Cleans up member variables after the import is finished.<p> 416 * 417 * This is required since there is only one instance for 418 * each import version that is kept in memory and reused.<p> 419 */ 420 protected void cleanUp() { 421 422 m_importResource = null; 423 m_importZip = null; 424 m_report = null; 425 m_linkStorage = null; 426 m_linkPropertyStorage = null; 427 m_groupsToCreate = null; 428 m_cms = null; 429 } 430 431 /** 432 * Converts old style pointers to siblings if possible.<p> 433 */ 434 protected void convertPointerToSiblings() { 435 436 try { 437 int linksSize = m_linkStorage.size(); 438 int i = 0; 439 Iterator<Entry<String, String>> itEntries = m_linkStorage.entrySet().iterator(); 440 // loop through all links to convert 441 while (itEntries.hasNext()) { 442 Entry<String, String> entry = itEntries.next(); 443 444 String key = entry.getKey(); 445 String link = entry.getValue(); 446 List<CmsProperty> properties = m_linkPropertyStorage.get(key); 447 CmsProperty.setAutoCreatePropertyDefinitions(properties, true); 448 449 i++; 450 m_report.print( 451 org.opencms.report.Messages.get().container( 452 org.opencms.report.Messages.RPT_SUCCESSION_2, 453 String.valueOf(i), 454 String.valueOf(linksSize)), 455 I_CmsReport.FORMAT_NOTE); 456 m_report.print(Messages.get().container(Messages.RPT_CONVERT_LINK_0), I_CmsReport.FORMAT_NOTE); 457 m_report.print( 458 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1, key + " ")); 459 m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 460 461 try { 462 // check if this is an internal pointer 463 if (link.startsWith("/")) { 464 // check if the pointer target is existing 465 CmsResource target = m_cms.readResource(link); 466 467 // create a new sibling as CmsResource 468 CmsResource resource = new CmsResource( 469 new CmsUUID(), // structure ID is always a new UUID 470 target.getResourceId(), 471 key, 472 target.getTypeId(), 473 target.isFolder(), 474 0, 475 m_cms.getRequestContext().getCurrentProject().getUuid(), // TODO: pass flags from import 476 CmsResource.STATE_NEW, 477 target.getDateCreated(), 478 target.getUserCreated(), 479 target.getDateLastModified(), 480 target.getUserLastModified(), 481 CmsResource.DATE_RELEASED_DEFAULT, 482 CmsResource.DATE_EXPIRED_DEFAULT, 483 1, 484 0, 485 target.getDateContent(), 486 0); 487 488 m_cms.importResource(key, resource, null, properties); 489 m_report.println( 490 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 491 I_CmsReport.FORMAT_OK); 492 493 if (LOG.isInfoEnabled()) { 494 LOG.info( 495 Messages.get().getBundle().key( 496 Messages.LOG_CONVERT_LINK_DOTS_OK_3, 497 String.valueOf(i), 498 String.valueOf(linksSize), 499 key)); 500 } 501 } else { 502 int pointerId = OpenCms.getResourceManager().getResourceType( 503 CmsResourceTypePointer.getStaticTypeName()).getTypeId(); 504 m_cms.createResource(key, pointerId, link.getBytes(), properties); 505 m_report.println( 506 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 507 I_CmsReport.FORMAT_OK); 508 509 if (LOG.isInfoEnabled()) { 510 LOG.info( 511 Messages.get().getBundle().key( 512 Messages.LOG_CONVERT_LINK_OK_3, 513 String.valueOf(i), 514 String.valueOf(linksSize), 515 key)); 516 } 517 } 518 } catch (CmsException e) { 519 m_report.println(); 520 m_report.print( 521 Messages.get().container(Messages.RPT_CONVERT_LINK_NOTFOUND_1, link), 522 I_CmsReport.FORMAT_WARNING); 523 524 if (LOG.isErrorEnabled()) { 525 LOG.error( 526 Messages.get().getBundle().key( 527 Messages.ERR_IMPORTEXPORT_LINK_CONVERSION_FAILED_2, 528 key, 529 link), 530 e); 531 } 532 } 533 } 534 } finally { 535 if (m_linkStorage != null) { 536 m_linkStorage.clear(); 537 } 538 m_linkStorage = null; 539 540 if (m_linkPropertyStorage != null) { 541 m_linkPropertyStorage.clear(); 542 } 543 m_linkPropertyStorage = null; 544 } 545 } 546 547 /** 548 * Returns a byte array containing the content of the file.<p> 549 * 550 * @param filename the name of the file to read 551 * @return a byte array containing the content of the file 552 */ 553 protected byte[] getFileBytes(String filename) { 554 555 try { 556 // is this a zip-file? 557 if (m_importZip != null) { 558 // yes 559 ZipEntry entry = m_importZip.getEntry(filename); 560 561 // path to file might be relative, too 562 if ((entry == null) && filename.startsWith("/")) { 563 entry = m_importZip.getEntry(filename.substring(1)); 564 } 565 if (entry == null) { 566 throw new ZipException( 567 Messages.get().getBundle().key(Messages.LOG_IMPORTEXPORT_FILE_NOT_FOUND_IN_ZIP_1, filename)); 568 } 569 570 InputStream stream = m_importZip.getInputStream(entry); 571 int size = Long.valueOf(entry.getSize()).intValue(); 572 return CmsFileUtil.readFully(stream, size); 573 } else { 574 // no - use directory 575 File file = new File(m_importResource, filename); 576 return CmsFileUtil.readFile(file); 577 } 578 } catch (FileNotFoundException fnfe) { 579 if (LOG.isErrorEnabled()) { 580 LOG.error(Messages.get().getBundle().key(Messages.ERR_IMPORTEXPORT_FILE_NOT_FOUND_1, filename), fnfe); 581 } 582 m_report.println(fnfe); 583 } catch (IOException ioe) { 584 if (LOG.isErrorEnabled()) { 585 LOG.error( 586 Messages.get().getBundle().key(Messages.ERR_IMPORTEXPORT_ERROR_READING_FILE_1, filename), 587 ioe); 588 } 589 m_report.println(ioe); 590 } 591 // this will only be returned in case there was an exception 592 return "".getBytes(); 593 } 594 595 /** 596 * Creates a new access control entry and stores it for later write out. 597 * 598 * @param res the resource 599 * @param id the id of the principal 600 * @param allowed the allowed permissions 601 * @param denied the denied permissions 602 * @param flags the flags 603 * 604 * @return the created ACE 605 */ 606 protected CmsAccessControlEntry getImportAccessControlEntry( 607 CmsResource res, 608 String id, 609 String allowed, 610 String denied, 611 String flags) { 612 613 return new CmsAccessControlEntry( 614 res.getResourceId(), 615 new CmsUUID(id), 616 Integer.parseInt(allowed), 617 Integer.parseInt(denied), 618 Integer.parseInt(flags)); 619 } 620 621 /** 622 * Returns the appropriate locale for the given destination.<p> 623 * 624 * @param destination the destination path (parent must exist) 625 * @param properties the properties to check at first 626 * 627 * @return the locale 628 */ 629 protected Locale getLocale(String destination, List<CmsProperty> properties) { 630 631 String localeName = CmsProperty.get(CmsPropertyDefinition.PROPERTY_LOCALE, properties).getValue(); 632 633 if (localeName != null) { 634 // locale was already set on the files properties 635 return OpenCms.getLocaleManager().getAvailableLocales(localeName).get(0); 636 } 637 // locale not set in properties, read default locales 638 return OpenCms.getLocaleManager().getDefaultLocales(m_cms, CmsResource.getParentFolder(destination)).get(0); 639 } 640 641 /** 642 * Writes already imported access control entries for a given resource.<p> 643 * 644 * @param resource the resource assigned to the access control entries 645 * @param aceList the access control entries to create 646 */ 647 protected void importAccessControlEntries(CmsResource resource, List<CmsAccessControlEntry> aceList) { 648 649 if (aceList.size() == 0) { 650 // no ACE in the list 651 return; 652 } 653 try { 654 m_cms.importAccessControlEntries(resource, aceList); 655 } catch (CmsException exc) { 656 m_report.println( 657 Messages.get().container(Messages.RPT_IMPORT_ACL_DATA_FAILED_0), 658 I_CmsReport.FORMAT_WARNING); 659 } 660 } 661 662 /** 663 * Imports a single group.<p> 664 * 665 * @param name the name of the group 666 * @param description group description 667 * @param flags group flags 668 * @param parentgroupName name of the parent group 669 * 670 * @throws CmsImportExportException if something goes wrong 671 */ 672 protected void importGroup(String name, String description, String flags, String parentgroupName) 673 throws CmsImportExportException { 674 675 if (description == null) { 676 description = ""; 677 } 678 679 CmsGroup parentGroup = null; 680 try { 681 if (CmsStringUtil.isNotEmpty(parentgroupName)) { 682 try { 683 parentGroup = m_cms.readGroup(parentgroupName); 684 } catch (CmsException exc) { 685 // parentGroup will be null 686 } 687 } 688 689 if (CmsStringUtil.isNotEmpty(parentgroupName) && (parentGroup == null)) { 690 // cannot create group, put on stack and try to create later 691 Map<String, String> groupData = new HashMap<String, String>(); 692 groupData.put(A_CmsImport.N_NAME, name); 693 groupData.put(A_CmsImport.N_DESCRIPTION, description); 694 groupData.put(A_CmsImport.N_FLAGS, flags); 695 groupData.put(A_CmsImport.N_PARENTGROUP, parentgroupName); 696 m_groupsToCreate.push(groupData); 697 } else { 698 try { 699 m_report.print(Messages.get().container(Messages.RPT_IMPORT_GROUP_0), I_CmsReport.FORMAT_NOTE); 700 m_report.print( 701 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1, name)); 702 m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 703 m_cms.createGroup(name, description, Integer.parseInt(flags), parentgroupName); 704 m_report.println( 705 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 706 I_CmsReport.FORMAT_OK); 707 } catch (CmsException exc) { 708 709 m_report.println(Messages.get().container(Messages.RPT_NOT_CREATED_0), I_CmsReport.FORMAT_OK); 710 } 711 } 712 713 } catch (Exception e) { 714 715 m_report.println(e); 716 717 CmsMessageContainer message = Messages.get().container( 718 Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_GROUP_1, 719 name); 720 if (LOG.isDebugEnabled()) { 721 LOG.debug(message.key(), e); 722 } 723 throw new CmsImportExportException(message, e); 724 } 725 } 726 727 /** 728 * Imports the OpenCms groups.<p> 729 * 730 * @throws CmsImportExportException if something goes wrong 731 */ 732 protected void importGroups() throws CmsImportExportException { 733 734 List<Node> groupNodes; 735 Element currentElement; 736 String name, description, flags, parentgroup; 737 try { 738 // getAll group nodes 739 groupNodes = m_docXml.selectNodes("//" + A_CmsImport.N_GROUPDATA); 740 // walk through all groups in manifest 741 for (int i = 0; i < groupNodes.size(); i++) { 742 currentElement = (Element)groupNodes.get(i); 743 name = getChildElementTextValue(currentElement, A_CmsImport.N_NAME); 744 name = OpenCms.getImportExportManager().translateGroup(name); 745 description = getChildElementTextValue(currentElement, A_CmsImport.N_DESCRIPTION); 746 flags = getChildElementTextValue(currentElement, A_CmsImport.N_FLAGS); 747 parentgroup = getChildElementTextValue(currentElement, A_CmsImport.N_PARENTGROUP); 748 if ((parentgroup != null) && (parentgroup.length() > 0)) { 749 parentgroup = OpenCms.getImportExportManager().translateGroup(parentgroup); 750 } 751 // import this group 752 753 importGroup(name, description, flags, parentgroup); 754 } 755 756 // now try to import the groups in the stack 757 while (!m_groupsToCreate.empty()) { 758 Stack<Map<String, String>> tempStack = m_groupsToCreate; 759 m_groupsToCreate = new Stack<Map<String, String>>(); 760 while (tempStack.size() > 0) { 761 Map<String, String> groupdata = tempStack.pop(); 762 name = groupdata.get(A_CmsImport.N_NAME); 763 description = groupdata.get(A_CmsImport.N_DESCRIPTION); 764 flags = groupdata.get(A_CmsImport.N_FLAGS); 765 parentgroup = groupdata.get(A_CmsImport.N_PARENTGROUP); 766 // try to import the group 767 importGroup(name, description, flags, parentgroup); 768 } 769 } 770 } catch (CmsImportExportException e) { 771 772 throw e; 773 } catch (Exception e) { 774 775 m_report.println(e); 776 777 CmsMessageContainer message = Messages.get().container(Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_GROUPS_0); 778 if (LOG.isDebugEnabled()) { 779 LOG.debug(message.key(), e); 780 } 781 782 throw new CmsImportExportException(message, e); 783 } 784 } 785 786 /** 787 * Imports a single user.<p> 788 * 789 * @param name user name 790 * @param flags user flags 791 * @param password user password 792 * @param firstname firstname of the user 793 * @param lastname lastname of the user 794 * @param email user email 795 * @param dateCreated creation date 796 * @param userInfo user info 797 * @param userGroups user groups 798 * 799 * @throws CmsImportExportException in case something goes wrong 800 */ 801 protected void importUser( 802 String name, 803 String flags, 804 String password, 805 String firstname, 806 String lastname, 807 String email, 808 long dateCreated, 809 Map<String, Object> userInfo, 810 List<String> userGroups) 811 throws CmsImportExportException { 812 813 // create a new user id 814 String id = new CmsUUID().toString(); 815 try { 816 try { 817 m_report.print(Messages.get().container(Messages.RPT_IMPORT_USER_0), I_CmsReport.FORMAT_NOTE); 818 m_report.print( 819 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1, name)); 820 m_report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 821 m_cms.importUser( 822 id, 823 name, 824 password, 825 firstname, 826 lastname, 827 email, 828 Integer.parseInt(flags), 829 dateCreated, 830 userInfo); 831 // add user to all groups list 832 for (int i = 0; i < userGroups.size(); i++) { 833 String groupName = userGroups.get(i); 834 try { 835 CmsGroup group = m_cms.readGroup(groupName); 836 if (group.isVirtual() || group.isRole()) { 837 CmsRole role = CmsRole.valueOf(group); 838 OpenCms.getRoleManager().addUserToRole(m_cms, role, name); 839 } else { 840 m_cms.addUserToGroup(name, groupName); 841 } 842 } catch (CmsException exc) { 843 m_report.println( 844 Messages.get().container(Messages.RPT_USER_COULDNT_BE_ADDED_TO_GROUP_2, name, groupName), 845 I_CmsReport.FORMAT_WARNING); 846 if (LOG.isDebugEnabled()) { 847 LOG.debug(exc.getLocalizedMessage(), exc); 848 } 849 } 850 } 851 m_report.println( 852 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 853 I_CmsReport.FORMAT_OK); 854 } catch (CmsException exc) { 855 m_report.println(Messages.get().container(Messages.RPT_NOT_CREATED_0), I_CmsReport.FORMAT_OK); 856 } 857 } catch (Exception e) { 858 859 m_report.println(e); 860 861 CmsMessageContainer message = Messages.get().container( 862 Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_USER_1, 863 name); 864 if (LOG.isDebugEnabled()) { 865 LOG.debug(message.key(), e); 866 } 867 throw new CmsImportExportException(message, e); 868 } 869 } 870 871 /** 872 * Imports the OpenCms users.<p> 873 * 874 * @throws CmsImportExportException if something goes wrong 875 */ 876 @SuppressWarnings("unchecked") 877 protected void importUsers() throws CmsImportExportException { 878 879 List<Node> userNodes; 880 List<Node> groupNodes; 881 List<String> userGroups; 882 Element currentElement, currentGroup; 883 Map<String, Object> userInfo = null; 884 String name, description, flags, password, firstname, lastname, email, address, pwd, infoNode, defaultGroup; 885 // try to get the import resource 886 //getImportResource(); 887 try { 888 // getAll user nodes 889 userNodes = m_docXml.selectNodes("//" + A_CmsImport.N_USERDATA); 890 // walk threw all groups in manifest 891 for (int i = 0; i < userNodes.size(); i++) { 892 currentElement = (Element)userNodes.get(i); 893 name = getChildElementTextValue(currentElement, A_CmsImport.N_NAME); 894 name = OpenCms.getImportExportManager().translateUser(name); 895 // decode passwords using base 64 decoder 896 pwd = getChildElementTextValue(currentElement, A_CmsImport.N_PASSWORD); 897 password = new String(Base64.decodeBase64(pwd.trim().getBytes())); 898 description = getChildElementTextValue(currentElement, A_CmsImport.N_DESCRIPTION); 899 flags = getChildElementTextValue(currentElement, A_CmsImport.N_FLAGS); 900 firstname = getChildElementTextValue(currentElement, A_CmsImport.N_FIRSTNAME); 901 lastname = getChildElementTextValue(currentElement, A_CmsImport.N_LASTNAME); 902 email = getChildElementTextValue(currentElement, A_CmsImport.N_EMAIL); 903 address = getChildElementTextValue(currentElement, A_CmsImport.N_TAG_ADDRESS); 904 defaultGroup = getChildElementTextValue(currentElement, A_CmsImport.N_DEFAULTGROUP); 905 // get the userinfo and put it into the additional info map 906 infoNode = getChildElementTextValue(currentElement, A_CmsImport.N_USERINFO); 907 try { 908 // read the userinfo from the dat-file 909 byte[] value = getFileBytes(infoNode); 910 // deserialize the object 911 ByteArrayInputStream bin = new ByteArrayInputStream(value); 912 ObjectInputStream oin = new ObjectInputStream(bin); 913 userInfo = (Map<String, Object>)oin.readObject(); 914 } catch (IOException ioex) { 915 m_report.println(ioex); 916 } catch (ClassCastException ccex) { 917 m_report.println(ccex); 918 } catch (ClassNotFoundException cnfex) { 919 m_report.println(cnfex); 920 } 921 // in case the user info could not be parsed create a new map 922 if (userInfo == null) { 923 userInfo = new HashMap<String, Object>(); 924 } 925 // get the groups of the user and put them into the list 926 groupNodes = currentElement.selectNodes("*/" + A_CmsImport.N_GROUPNAME); 927 userGroups = new ArrayList<String>(); 928 for (int j = 0; j < groupNodes.size(); j++) { 929 currentGroup = (Element)groupNodes.get(j); 930 String userInGroup = getChildElementTextValue(currentGroup, A_CmsImport.N_NAME); 931 userInGroup = OpenCms.getImportExportManager().translateGroup(userInGroup); 932 userGroups.add(userInGroup); 933 } 934 935 if (CmsStringUtil.isNotEmpty(defaultGroup)) { 936 userInfo.put(CmsUserSettings.ADDITIONAL_INFO_DEFAULTGROUP, defaultGroup); 937 } 938 939 if (description != null) { 940 userInfo.put(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION, description); 941 } 942 if (address != null) { 943 userInfo.put(CmsUserSettings.ADDITIONAL_INFO_ADDRESS, address); 944 } 945 // import this user 946 importUser(name, flags, password, firstname, lastname, email, 0, userInfo, userGroups); 947 } 948 } catch (CmsImportExportException e) { 949 throw e; 950 } catch (Exception e) { 951 m_report.println(e); 952 CmsMessageContainer message = Messages.get().container(Messages.ERR_IMPORTEXPORT_ERROR_IMPORTING_USERS_0); 953 if (LOG.isDebugEnabled()) { 954 LOG.debug(message.key(), e); 955 } 956 throw new CmsImportExportException(message, e); 957 } 958 } 959 960 /** 961 * Initializes all member variables before the import is started.<p> 962 * 963 * This is required since there is only one instance for 964 * each import version that is kept in memory and reused.<p> 965 */ 966 protected void initialize() { 967 968 m_groupsToCreate = new Stack<Map<String, String>>(); 969 } 970 971 /** 972 * Reads all properties below a specified parent element from the <code>manifest.xml</code>.<p> 973 * 974 * @param parentElement the current file node 975 * @param ignoredPropertyKeys a list of properties to be ignored 976 * 977 * @return a list with all properties 978 */ 979 protected List<CmsProperty> readPropertiesFromManifest(Element parentElement, List<String> ignoredPropertyKeys) { 980 981 // all imported Cms property objects are collected in map first forfaster access 982 Map<String, CmsProperty> properties = new HashMap<String, CmsProperty>(); 983 CmsProperty property = null; 984 List<Node> propertyElements = parentElement.selectNodes( 985 "./" + A_CmsImport.N_PROPERTIES + "/" + A_CmsImport.N_PROPERTY); 986 Element propertyElement = null; 987 String key = null, value = null; 988 Attribute attrib = null; 989 990 // iterate over all property elements 991 for (int i = 0, n = propertyElements.size(); i < n; i++) { 992 propertyElement = (Element)propertyElements.get(i); 993 key = getChildElementTextValue(propertyElement, A_CmsImport.N_NAME); 994 995 if ((key == null) || ignoredPropertyKeys.contains(key)) { 996 // continue if the current property (key) should be ignored or is null 997 continue; 998 } 999 1000 // all Cms properties are collected in a map keyed by their property keys 1001 property = properties.get(key); 1002 if (property == null) { 1003 property = new CmsProperty(); 1004 property.setName(key); 1005 property.setAutoCreatePropertyDefinition(true); 1006 properties.put(key, property); 1007 } 1008 1009 value = getChildElementTextValue(propertyElement, A_CmsImport.N_VALUE); 1010 if (value == null) { 1011 value = ""; 1012 } 1013 1014 attrib = propertyElement.attribute(A_CmsImport.N_PROPERTY_ATTRIB_TYPE); 1015 if ((attrib != null) && attrib.getValue().equals(A_CmsImport.N_PROPERTY_ATTRIB_TYPE_SHARED)) { 1016 // it is a shared/resource property value 1017 property.setResourceValue(value); 1018 } else { 1019 // it is an individual/structure value 1020 property.setStructureValue(value); 1021 } 1022 } 1023 1024 return new ArrayList<CmsProperty>(properties.values()); 1025 } 1026}