1 17 package org.alfresco.repo.importer; 18 19 import java.io.BufferedReader ; 20 import java.io.InputStream ; 21 import java.io.InputStreamReader ; 22 import java.io.Reader ; 23 import java.io.UnsupportedEncodingException ; 24 import java.util.List ; 25 import java.util.Locale ; 26 import java.util.Properties ; 27 import java.util.ResourceBundle ; 28 import java.util.StringTokenizer ; 29 30 import javax.transaction.UserTransaction ; 31 32 import org.alfresco.error.AlfrescoRuntimeException; 33 import org.alfresco.i18n.I18NUtil; 34 import org.alfresco.repo.security.authentication.AuthenticationComponent; 35 import org.alfresco.service.cmr.repository.NodeService; 36 import org.alfresco.service.cmr.repository.StoreRef; 37 import org.alfresco.service.cmr.view.ImporterBinding; 38 import org.alfresco.service.cmr.view.ImporterException; 39 import org.alfresco.service.cmr.view.ImporterProgress; 40 import org.alfresco.service.cmr.view.ImporterService; 41 import org.alfresco.service.cmr.view.Location; 42 import org.alfresco.service.namespace.NamespaceService; 43 import org.alfresco.service.namespace.QName; 44 import org.alfresco.service.transaction.TransactionService; 45 import org.apache.commons.logging.Log; 46 import org.apache.commons.logging.LogFactory; 47 import org.apache.commons.logging.impl.Log4JLogger; 48 import org.apache.log4j.Level; 49 import org.apache.log4j.Logger; 50 import org.springframework.context.ApplicationEvent; 51 import org.springframework.context.ApplicationListener; 52 import org.springframework.context.event.ContextRefreshedEvent; 53 import org.springframework.core.io.ClassPathResource; 54 55 60 public class ImporterBootstrap implements ApplicationListener 61 { 62 public static final String VIEW_PATH_PROPERTY = "path"; 64 public static final String VIEW_CHILDASSOCTYPE_PROPERTY = "childAssocType"; 65 public static final String VIEW_MESSAGES_PROPERTY = "messages"; 66 public static final String VIEW_LOCATION_VIEW = "location"; 67 public static final String VIEW_ENCODING = "encoding"; 68 69 private static final Log logger = LogFactory.getLog(ImporterBootstrap.class); 71 private boolean logEnabled = false; 72 73 private boolean allowWrite = true; 75 private boolean useExistingStore = false; 76 private TransactionService transactionService; 77 private NamespaceService namespaceService; 78 private NodeService nodeService; 79 private ImporterService importerService; 80 private List <Properties > bootstrapViews; 81 private StoreRef storeRef = null; 82 private List <String > mustNotExistStoreUrls = null; 83 private Properties configuration = null; 84 private String strLocale = null; 85 private Locale locale = null; 86 private AuthenticationComponent authenticationComponent; 87 88 private boolean bootstrapPerformed = false; 90 91 92 97 public void setAllowWrite(boolean write) 98 { 99 this.allowWrite = write; 100 } 101 102 109 public void setUseExistingStore(boolean useExistingStore) 110 { 111 this.useExistingStore = useExistingStore; 112 } 113 114 119 public void setTransactionService(TransactionService transactionService) 120 { 121 this.transactionService = transactionService; 122 } 123 124 129 public void setNamespaceService(NamespaceService namespaceService) 130 { 131 this.namespaceService = namespaceService; 132 } 133 134 139 public void setNodeService(NodeService nodeService) 140 { 141 this.nodeService = nodeService; 142 } 143 144 149 public void setImporterService(ImporterService importerService) 150 { 151 this.importerService = importerService; 152 } 153 154 159 public void setAuthenticationComponent(AuthenticationComponent authenticationComponent) 160 { 161 this.authenticationComponent = authenticationComponent; 162 } 163 164 169 public void setBootstrapViews(List <Properties > bootstrapViews) 170 { 171 this.bootstrapViews = bootstrapViews; 172 } 173 174 179 public void setStoreUrl(String storeUrl) 180 { 181 this.storeRef = new StoreRef(storeUrl); 182 } 183 184 189 public void setMustNotExistStoreUrls(List <String > storeUrls) 190 { 191 this.mustNotExistStoreUrls = storeUrls; 192 } 193 194 199 public StoreRef getStoreRef() 200 { 201 return this.storeRef; 202 } 203 204 209 public void setConfiguration(Properties configuration) 210 { 211 this.configuration = configuration; 212 } 213 214 219 public Properties getConfiguration() 220 { 221 return configuration; 222 } 223 224 229 public void setLocale(String locale) 230 { 231 StringTokenizer t = new StringTokenizer (locale, "_"); 233 int tokens = t.countTokens(); 234 if (tokens == 1) 235 { 236 this.locale = new Locale (locale); 237 } 238 else if (tokens == 2) 239 { 240 this.locale = new Locale (t.nextToken(), t.nextToken()); 241 } 242 else if (tokens == 3) 243 { 244 this.locale = new Locale (t.nextToken(), t.nextToken(), t.nextToken()); 245 } 246 247 strLocale = locale; 249 } 250 251 256 public String getLocale() 257 { 258 return strLocale; 259 } 260 261 266 public void setLog(boolean logEnabled) 267 { 268 this.logEnabled = logEnabled; 269 } 270 271 276 public boolean hasPerformedBootstrap() 277 { 278 return bootstrapPerformed; 279 } 280 281 284 public void bootstrap() 285 { 286 if (transactionService == null) 287 { 288 throw new ImporterException("Transaction Service must be provided"); 289 } 290 if (namespaceService == null) 291 { 292 throw new ImporterException("Namespace Service must be provided"); 293 } 294 if (nodeService == null) 295 { 296 throw new ImporterException("Node Service must be provided"); 297 } 298 if (importerService == null) 299 { 300 throw new ImporterException("Importer Service must be provided"); 301 } 302 if (storeRef == null) 303 { 304 throw new ImporterException("Store URL must be provided"); 305 } 306 307 if (logEnabled && logger instanceof Log4JLogger) 310 { 311 Logger log4JLogger = ((Log4JLogger)logger).getLogger(); 312 log4JLogger.setLevel(Level.DEBUG); 313 } 314 315 UserTransaction userTransaction = transactionService.getUserTransaction(); 316 authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName()); 317 318 try 319 { 320 userTransaction.begin(); 321 322 if (!performBootstrap()) 324 { 325 if (logger.isDebugEnabled()) 326 logger.debug("Store exists - bootstrap ignored: " + storeRef); 327 } 328 else if (!allowWrite) 329 { 330 logger.warn("Store does not exist, but mode is read-only: " + storeRef); 332 } 333 else 334 { 335 if (!nodeService.exists(storeRef)) 337 { 338 storeRef = nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier()); 339 if (logger.isDebugEnabled()) 340 logger.debug("Created store: " + storeRef); 341 } 342 343 if (bootstrapViews != null) 345 { 346 for (Properties bootstrapView : bootstrapViews) 347 { 348 String view = bootstrapView.getProperty(VIEW_LOCATION_VIEW); 349 if (view == null || view.length() == 0) 350 { 351 throw new ImporterException("View file location must be provided"); 352 } 353 String encoding = bootstrapView.getProperty(VIEW_ENCODING); 354 355 Reader viewReader = null; 357 ACPImportPackageHandler acpHandler = null; 358 if (view.endsWith(".acp")) 359 { 360 ClassPathResource acpResource = new ClassPathResource(view); 361 acpHandler = new ACPImportPackageHandler(acpResource.getFile(), encoding); 362 } 363 else 364 { 365 viewReader = getReader(view, encoding); 366 } 367 368 Location importLocation = new Location(storeRef); 370 String path = bootstrapView.getProperty(VIEW_PATH_PROPERTY); 371 if (path != null && path.length() > 0) 372 { 373 importLocation.setPath(path); 374 } 375 String childAssocType = bootstrapView.getProperty(VIEW_CHILDASSOCTYPE_PROPERTY); 376 if (childAssocType != null && childAssocType.length() > 0) 377 { 378 importLocation.setChildAssocType(QName.createQName(childAssocType, namespaceService)); 379 } 380 381 BootstrapBinding binding = new BootstrapBinding(); 383 binding.setConfiguration(configuration); 384 binding.setLocation(importLocation); 385 String messages = bootstrapView.getProperty(VIEW_MESSAGES_PROPERTY); 386 if (messages != null && messages.length() > 0) 387 { 388 Locale bindingLocale = (locale == null) ? I18NUtil.getLocale() : locale; 389 ResourceBundle bundle = ResourceBundle.getBundle(messages, bindingLocale); 390 binding.setResourceBundle(bundle); 391 } 392 393 ImporterProgress importProgress = null; 395 if (logger.isDebugEnabled()) 396 { 397 importProgress = new ImportTimerProgress(logger); 398 logger.debug("Importing " + view); 399 } 400 401 if (viewReader != null) 402 { 403 importerService.importView(viewReader, importLocation, binding, importProgress); 404 } 405 else 406 { 407 importerService.importView(acpHandler, importLocation, binding, importProgress); 408 } 409 } 410 } 411 412 bootstrapPerformed = !useExistingStore; 414 } 415 userTransaction.commit(); 416 } 417 catch(Throwable e) 418 { 419 try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {} 421 try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {} 422 throw new AlfrescoRuntimeException("Bootstrap failed", e); 423 } 424 finally 425 { 426 authenticationComponent.clearCurrentSecurityContext(); 427 } 428 } 429 430 437 private Reader getReader(String view, String encoding) 438 { 439 InputStream viewStream = getClass().getClassLoader().getResourceAsStream(view); 441 if (viewStream == null) 442 { 443 throw new ImporterException("Could not find view file " + view); 444 } 445 446 try 448 { 449 InputStreamReader inputReader = (encoding == null) ? new InputStreamReader (viewStream) : new InputStreamReader (viewStream, encoding); 450 BufferedReader reader = new BufferedReader (inputReader); 451 return reader; 452 } 453 catch (UnsupportedEncodingException e) 454 { 455 throw new ImporterException("Could not create reader for view " + view + " as encoding " + encoding + " is not supported"); 456 } 457 } 458 459 462 private static class BootstrapBinding implements ImporterBinding 463 { 464 private Properties configuration = null; 465 private ResourceBundle resourceBundle = null; 466 private Location bootstrapLocation = null; 467 468 private static final String IMPORT_LOCATION_UUID = "bootstrap.location.uuid"; 469 private static final String IMPORT_LOCATION_NODEREF = "bootstrap.location.noderef"; 470 private static final String IMPORT_LOCATION_PATH = "bootstrap.location.path"; 471 472 473 478 public void setConfiguration(Properties configuration) 479 { 480 this.configuration = configuration; 481 } 482 483 488 public Properties getConfiguration() 489 { 490 return this.configuration; 491 } 492 493 498 public void setResourceBundle(ResourceBundle resourceBundle) 499 { 500 this.resourceBundle = resourceBundle; 501 } 502 503 508 public void setLocation(Location location) 509 { 510 this.bootstrapLocation = location; 511 } 512 513 516 public String getValue(String key) 517 { 518 String value = null; 519 if (configuration != null) 520 { 521 value = configuration.getProperty(key); 522 } 523 if (value == null && resourceBundle != null) 524 { 525 value = resourceBundle.getString(key); 526 } 527 if (value == null && bootstrapLocation != null) 528 { 529 if (key.equals(IMPORT_LOCATION_UUID)) 530 { 531 value = bootstrapLocation.getNodeRef().getId(); 532 } 533 else if (key.equals(IMPORT_LOCATION_NODEREF)) 534 { 535 value = bootstrapLocation.getNodeRef().toString(); 536 } 537 else if (key.equals(IMPORT_LOCATION_PATH)) 538 { 539 value = bootstrapLocation.getPath(); 540 } 541 } 542 543 return value; 544 } 545 546 550 public UUID_BINDING getUUIDBinding() 551 { 552 return UUID_BINDING.CREATE_NEW; 554 } 555 556 560 public boolean allowReferenceWithinTransaction() 561 { 562 return true; 563 } 564 } 565 566 571 private boolean performBootstrap() 572 { 573 if (useExistingStore) 574 { 575 return true; 577 } 578 else if (nodeService.exists(storeRef)) 579 { 580 return false; 581 } 582 else if (mustNotExistStoreUrls != null) 583 { 584 for (String storeUrl : mustNotExistStoreUrls) 585 { 586 StoreRef storeRef = new StoreRef(storeUrl); 587 if (nodeService.exists(storeRef)) 588 { 589 return false; 590 } 591 } 592 } 593 594 return true; 595 } 596 597 601 public void onApplicationEvent(ApplicationEvent event) 602 { 603 if (event instanceof ContextRefreshedEvent) 604 { 605 bootstrap(); 606 } 607 } 608 609 } 610 | Popular Tags |