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, 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.ui.apps.dbmanager; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.file.CmsVfsResourceNotFoundException; 034import org.opencms.importexport.CmsExportParameters; 035import org.opencms.importexport.CmsVfsImportExportHandler; 036import org.opencms.main.CmsException; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.module.CmsModule.ExportMode; 040import org.opencms.report.A_CmsReportThread; 041import org.opencms.ui.A_CmsUI; 042import org.opencms.ui.CmsVaadinUtils; 043import org.opencms.ui.apps.Messages; 044import org.opencms.ui.components.CmsBasicDialog; 045import org.opencms.ui.components.CmsBasicDialog.DialogWidth; 046import org.opencms.ui.components.CmsDateField; 047import org.opencms.ui.components.editablegroup.CmsEditableGroup; 048import org.opencms.ui.components.editablegroup.I_CmsEditableGroupRow; 049import org.opencms.ui.components.fileselect.CmsPathSelectField; 050import org.opencms.util.CmsStringUtil; 051import org.opencms.util.CmsUUID; 052import org.opencms.workplace.threads.CmsExportThread; 053 054import java.io.File; 055import java.util.ArrayList; 056import java.util.Arrays; 057import java.util.List; 058import java.util.stream.Collectors; 059 060import org.apache.commons.logging.Log; 061 062import com.google.common.base.Supplier; 063import com.vaadin.ui.Button; 064import com.vaadin.ui.Button.ClickEvent; 065import com.vaadin.ui.Button.ClickListener; 066import com.vaadin.ui.Component; 067import com.vaadin.ui.FormLayout; 068import com.vaadin.ui.Window; 069import com.vaadin.v7.data.Property.ValueChangeEvent; 070import com.vaadin.v7.data.Property.ValueChangeListener; 071import com.vaadin.v7.data.Validator; 072import com.vaadin.v7.data.util.IndexedContainer; 073import com.vaadin.v7.shared.ui.combobox.FilteringMode; 074import com.vaadin.v7.ui.AbstractSelect.ItemCaptionMode; 075import com.vaadin.v7.ui.CheckBox; 076import com.vaadin.v7.ui.ComboBox; 077import com.vaadin.v7.ui.VerticalLayout; 078 079/** 080 * Class for the Export dialog.<p> 081 */ 082public class CmsDbExportView extends VerticalLayout { 083 084 /** 085 * Validator for entered resources.<p> 086 */ 087 class ResourceValidator implements Validator { 088 089 /**vaadin serial id.*/ 090 private static final long serialVersionUID = -4341247963641286345L; 091 092 /** 093 * @see com.vaadin.data.Validator#validate(java.lang.Object) 094 */ 095 public void validate(Object value) throws InvalidValueException { 096 097 String resourcePath = (String)value; 098 if ((value == null)) { 099 throw new InvalidValueException( 100 CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_INVALID_RESOURCE_EMPTY_0)); 101 } 102 103 if (resourcePath.isEmpty()) { 104 throw new InvalidValueException( 105 CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_INVALID_RESOURCE_EMPTY_0)); 106 } 107 108 if (!m_cms.existsResource(resourcePath, CmsResourceFilter.IGNORE_EXPIRATION)) { 109 throw new InvalidValueException( 110 CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_INVALID_RESOURCE_NOTFOUND_0)); 111 } 112 } 113 } 114 115 /** 116 * Validator for the target field.<p> 117 */ 118 class TargetValidator implements Validator { 119 120 /**vaadin serial id.*/ 121 private static final long serialVersionUID = 7530400504930612299L; 122 123 /** 124 * @see com.vaadin.data.Validator#validate(java.lang.Object) 125 */ 126 public void validate(Object value) throws InvalidValueException { 127 128 if (value == null) { 129 throw new InvalidValueException( 130 CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_INVALID_TARGET_0)); 131 } 132 } 133 } 134 135 /** The logger for this class. */ 136 private static final Log LOG = CmsLog.getLog(CmsDbExportView.class.getName()); 137 138 /**vaadin serial id.*/ 139 private static final long serialVersionUID = -2571459807662862053L; 140 141 /**Copy of current CmsObject.*/ 142 protected CmsObject m_cms; 143 144 /** Button to add a list of resources through a text area. */ 145 private Button m_addResources; 146 147 /**vaadin component.*/ 148 private CheckBox m_asFiles; 149 150 /**vaadin component.*/ 151 private CmsDateField m_changedSince; 152 153 /** The export parameters object that is edited on this dialog. */ 154 private CmsExportParameters m_exportParams; 155 156 /**vaadin component.*/ 157 private CheckBox m_includeAccount; 158 159 /**vaadin component.*/ 160 private CheckBox m_includeProject; 161 162 /**vaadin component.*/ 163 private CheckBox m_includeResource; 164 165 /**vaadin component.*/ 166 private CheckBox m_includeSystem; 167 168 /**vaadin component.*/ 169 private CheckBox m_includeUnchanged; 170 171 /**vaadin component.*/ 172 private CheckBox m_modified; 173 174 /**vaadin component.*/ 175 private Button m_ok; 176 177 private ComboBox m_project; 178 179 /**vaadin component.*/ 180 private CheckBox m_recursive; 181 182 /**Vaadin component. */ 183 private CheckBox m_reducedMetadata; 184 185 /**vaadin component.*/ 186 private VerticalLayout m_resources; 187 188 private CmsEditableGroup m_resourcesGroup; 189 190 /**vaadin component.*/ 191 private ComboBox m_site; 192 193 /**vaadin component.*/ 194 private CheckBox m_skipParentFolders; 195 196 /**vaadin component.*/ 197 private ComboBox m_target; 198 199 /** 200 * public constructor.<p> 201 */ 202 public CmsDbExportView() { 203 204 CmsVaadinUtils.readAndLocalizeDesign(this, CmsVaadinUtils.getWpMessagesForCurrentLocale(), null); 205 setHeightUndefined(); 206 try { 207 m_cms = OpenCms.initCmsObject(A_CmsUI.getCmsObject()); 208 } catch (CmsException e) { 209 LOG.error("Failed to clone CmsObject", e); 210 } 211 212 m_resourcesGroup = new CmsEditableGroup(m_resources, new Supplier<Component>() { 213 214 public Component get() { 215 216 return getResourceRow(""); 217 218 } 219 220 }, CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_ADD_RESOURCE_0)); 221 m_resourcesGroup.init(); 222 m_resourcesGroup.addRow(getResourceRow("")); 223 m_exportParams = new CmsExportParameters(); 224 225 setupCheckBoxes(); 226 setupComboBoxFile(); 227 setupComboBoxSite(); 228 229 m_ok.addClickListener(new ClickListener() { 230 231 private static final long serialVersionUID = -4224924796312615674L; 232 233 public void buttonClick(ClickEvent event) { 234 235 addResourceIfEmpty(); 236 addValidators(); 237 if (isFormValid()) { 238 startThread(); 239 } 240 } 241 }); 242 m_addResources.addClickListener(e -> openAddResourcesDialog()); 243 } 244 245 protected void addResourceIfEmpty() { 246 247 if (m_resourcesGroup.getRows().size() == 0) { 248 m_resourcesGroup.addRow(getResourceRow("")); 249 } 250 } 251 252 /** 253 * Adds all validators to the formular.<p> 254 */ 255 protected void addValidators() { 256 257 //Target file ComboBox 258 m_target.removeAllValidators(); 259 m_target.addValidator(new TargetValidator()); 260 261 for (I_CmsEditableGroupRow row : m_resourcesGroup.getRows()) { 262 FormLayout layout = (FormLayout)(row.getComponent()); 263 CmsPathSelectField field = (CmsPathSelectField)layout.getComponent(0); 264 field.removeAllValidators(); 265 field.addValidator(new ResourceValidator()); 266 } 267 } 268 269 /** 270 * Changes the site of the cms object.<p> 271 */ 272 protected void changeSite() { 273 274 m_cms.getRequestContext().setSiteRoot((String)m_site.getValue()); 275 } 276 277 protected Component getResourceRow(String path) { 278 279 FormLayout res = new FormLayout(); 280 CmsPathSelectField field = new CmsPathSelectField(); 281 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(path)) { 282 field.setValue(path); 283 } 284 field.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_RESOURCES_0)); 285 field.setDescription(CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_RESOURCES_HELP_0)); 286 field.setCmsObject(m_cms); 287 res.addComponent(field); 288 return res; 289 } 290 291 /** 292 * Checks if form is valid.<p> 293 * 294 * @return true if all fields are valid 295 */ 296 protected boolean isFormValid() { 297 298 return m_target.isValid() & allResourcesValid(); 299 } 300 301 /** 302 * Checks if resources exist in site. if not the row gets removed.<p> 303 */ 304 protected void removeUnvalidPathFields() { 305 306 int counter = 0; 307 List<I_CmsEditableGroupRow> rowsToRemove = new ArrayList<I_CmsEditableGroupRow>(); 308 for (I_CmsEditableGroupRow row : m_resourcesGroup.getRows()) { 309 FormLayout layout = (FormLayout)(row.getComponent()); 310 CmsPathSelectField field = (CmsPathSelectField)layout.getComponent(0); 311 if (!m_cms.existsResource(field.getValue(), CmsResourceFilter.IGNORE_EXPIRATION)) { 312 rowsToRemove.add(row); 313 } 314 } 315 316 for (I_CmsEditableGroupRow row : rowsToRemove) { 317 m_resourcesGroup.remove(row); 318 } 319 } 320 321 /** 322 * Starts the export thread and displays it's report.<p> 323 */ 324 protected void startThread() { 325 326 try { 327 m_cms.getRequestContext().setCurrentProject(m_cms.readProject((CmsUUID)m_project.getValue())); 328 } catch (CmsException e) { 329 LOG.error("Unable to set project", e); 330 } 331 updateExportParams(); 332 333 CmsVfsImportExportHandler handler = new CmsVfsImportExportHandler(); 334 handler.setExportParams(m_exportParams); 335 A_CmsReportThread exportThread = new CmsExportThread(m_cms, handler, false); 336 337 Window window = CmsBasicDialog.prepareWindow(DialogWidth.max); 338 window.setContent(new CmsExportThreadDialog(handler, exportThread, window)); 339 A_CmsUI.get().addWindow(window); 340 exportThread.start(); 341 } 342 343 /** 344 * Checks if all resources are valid.<p> 345 * 346 * @return true if resources are valid 347 */ 348 private boolean allResourcesValid() { 349 350 boolean valid = true; 351 352 for (I_CmsEditableGroupRow row : m_resourcesGroup.getRows()) { 353 FormLayout layout = (FormLayout)(row.getComponent()); 354 CmsPathSelectField field = (CmsPathSelectField)layout.getComponent(0); 355 if (!field.isValid()) { 356 valid = false; 357 } 358 } 359 360 return valid; 361 } 362 363 /** 364 * Reads out resources from form.<p> 365 * 366 * @return List with site-relative paths of resources 367 */ 368 private List<String> getResources() { 369 370 List<String> res = new ArrayList<String>(); 371 372 for (I_CmsEditableGroupRow row : m_resourcesGroup.getRows()) { 373 FormLayout layout = (FormLayout)(row.getComponent()); 374 CmsPathSelectField field = (CmsPathSelectField)layout.getComponent(0); 375 String value = field.getValue(); 376 if (!value.isEmpty()) { 377 if (!value.endsWith("/")) { 378 try { 379 CmsResource resource = m_cms.readResource(value, CmsResourceFilter.IGNORE_EXPIRATION); 380 if (resource.isFolder()) { 381 value = value + "/"; 382 } 383 } catch (CmsException e) { 384 if (!(e instanceof CmsVfsResourceNotFoundException)) { 385 LOG.error(e.getLocalizedMessage()); 386 } 387 } 388 } 389 if (!res.contains(value)) { 390 res.add(value); 391 } 392 } 393 } 394 395 return res; 396 } 397 398 /** 399 * Opens the dialog for adding new resources via a text area. 400 */ 401 private void openAddResourcesDialog() { 402 403 Window window = CmsBasicDialog.prepareWindow(DialogWidth.wide); 404 window.setCaption(CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_OPEN_ADD_RESOURCES_DIALOG_0)); 405 window.setContent(new CmsAddExportResourcesDialog(result -> updateExportResources(result))); 406 A_CmsUI.get().addWindow(window); 407 } 408 409 /** 410 * Sets the init values for check boxes.<p> 411 */ 412 private void setupCheckBoxes() { 413 414 m_includeResource.setValue(Boolean.valueOf(true)); 415 m_includeUnchanged.setValue(Boolean.valueOf(true)); 416 m_includeSystem.setValue(Boolean.valueOf(true)); 417 m_recursive.setValue(Boolean.valueOf(true)); 418 } 419 420 /** 421 * Sets up the combo box for the target file.<p> 422 */ 423 private void setupComboBoxFile() { 424 425 m_target.setInputPrompt(CmsVaadinUtils.getMessageText(Messages.GUI_DATABASEAPP_EXPORT_FILE_NAME_EMPTY_0)); 426 m_target.setNewItemsAllowed(true); 427 List<String> files = CmsDbManager.getFileListFromServer(true); 428 for (String file : files) { 429 m_target.addItem(file); 430 } 431 } 432 433 /** 434 * Sets up the combo box for the site choice.<p> 435 */ 436 private void setupComboBoxSite() { 437 438 IndexedContainer container = CmsVaadinUtils.getAvailableSitesContainer(A_CmsUI.getCmsObject(), "title"); 439 m_site.setContainerDataSource(container); 440 m_site.setItemCaptionMode(ItemCaptionMode.PROPERTY); 441 m_site.setItemCaptionPropertyId("title"); 442 m_site.setFilteringMode(FilteringMode.CONTAINS); 443 m_site.setNullSelectionAllowed(false); 444 m_site.setValue(A_CmsUI.getCmsObject().getRequestContext().getSiteRoot()); 445 m_site.addValueChangeListener(new ValueChangeListener() { 446 447 private static final long serialVersionUID = -1019243885633462477L; 448 449 public void valueChange(ValueChangeEvent event) { 450 451 changeSite(); 452 removeUnvalidPathFields(); 453 } 454 }); 455 456 m_project.setContainerDataSource(CmsVaadinUtils.getProjectsContainer(A_CmsUI.getCmsObject(), "caption")); 457 m_project.setItemCaptionPropertyId("caption"); 458 m_project.select(A_CmsUI.getCmsObject().getRequestContext().getCurrentProject().getUuid()); 459 m_project.setNewItemsAllowed(false); 460 m_project.setNullSelectionAllowed(false); 461 m_project.setTextInputAllowed(false); 462 } 463 464 /** 465 * Updates the Export parameter based on user input.<p> 466 */ 467 private void updateExportParams() { 468 469 m_exportParams.setExportAccountData(m_includeAccount.getValue().booleanValue()); 470 m_exportParams.setExportAsFiles(m_asFiles.getValue().booleanValue()); 471 m_exportParams.setExportProjectData(m_includeProject.getValue().booleanValue()); 472 m_exportParams.setExportResourceData(m_includeResource.getValue().booleanValue()); 473 m_exportParams.setInProject(m_modified.getValue().booleanValue()); 474 m_exportParams.setIncludeSystemFolder(m_includeSystem.getValue().booleanValue()); 475 m_exportParams.setIncludeUnchangedResources(m_includeUnchanged.getValue().booleanValue()); 476 m_exportParams.setSkipParentFolders(m_skipParentFolders.getValue().booleanValue()); 477 String exportFileName = OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf( 478 OpenCms.getSystemInfo().getPackagesRfsPath() + File.separator + (String)m_target.getValue()); 479 m_exportParams.setPath(exportFileName); 480 m_exportParams.setRecursive(m_recursive.getValue().booleanValue()); 481 m_exportParams.setResources(getResources()); 482 ExportMode exportMode = m_reducedMetadata.getValue().booleanValue() ? ExportMode.REDUCED : ExportMode.DEFAULT; 483 m_exportParams.setExportMode(exportMode); 484 if (m_changedSince.getValue() != null) { 485 m_exportParams.setContentAge(m_changedSince.getDate().getTime()); 486 } else { 487 m_exportParams.setContentAge(0); 488 } 489 } 490 491 /** 492 * Updates the export resource fields from a newline-separated list of paths. 493 * 494 * @param resourceListing a newline-separated list of paths 495 */ 496 private void updateExportResources(String resourceListing) { 497 498 List<String> exResources = getResources(); 499 List<String> lines = Arrays.stream(resourceListing.trim().split("\n")).filter( 500 r -> !CmsStringUtil.isEmptyOrWhitespaceOnly(r)).map(r -> r.trim()).collect(Collectors.toList()); 501 502 if ((exResources.size() == 0) && (lines.size() > 0)) { 503 // We have paths to add from the resource listing, but only empty fields in the form, 504 // so remove the existing form fields first, because they aren't needed anymore and would 505 // cause validation errors when clicking OK because they're empty. 506 507 m_resourcesGroup.init(); 508 } 509 510 for (String line : lines) { 511 if (!exResources.contains(line)) { 512 // folders may have been entered without trailing slashes, 513 // but to correct that, we have to read the resources 514 try { 515 CmsResource res = m_cms.readResource(line, CmsResourceFilter.IGNORE_EXPIRATION); 516 line = m_cms.getSitePath(res); 517 } catch (CmsException e) { 518 LOG.debug(e.getLocalizedMessage(), e); 519 } 520 m_resourcesGroup.addRow(getResourceRow(line)); 521 } 522 } 523 524 } 525 526}