001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027 028package org.opends.guitools.controlpanel.ui; 029 030import static org.opends.messages.AdminToolMessages.*; 031 032import static org.opends.messages.QuickSetupMessages.INFO_NO_LDIF_PATH; 033 034import java.awt.Component; 035import java.awt.GridBagConstraints; 036import java.io.File; 037import java.util.ArrayList; 038import java.util.Collection; 039import java.util.HashSet; 040import java.util.LinkedHashSet; 041import java.util.Set; 042import java.util.TreeSet; 043 044import javax.swing.DefaultComboBoxModel; 045import javax.swing.JButton; 046import javax.swing.JCheckBox; 047import javax.swing.JComboBox; 048import javax.swing.JLabel; 049import javax.swing.JTextField; 050import javax.swing.SwingUtilities; 051import javax.swing.event.ChangeEvent; 052import javax.swing.event.ChangeListener; 053import javax.swing.event.DocumentEvent; 054import javax.swing.event.DocumentListener; 055 056import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 057import org.opends.guitools.controlpanel.datamodel.ScheduleType; 058import org.opends.guitools.controlpanel.datamodel.ServerDescriptor; 059import org.opends.guitools.controlpanel.event.BrowseActionListener; 060import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 061import org.opends.guitools.controlpanel.task.Task; 062import org.opends.guitools.controlpanel.ui.components.ScheduleSummaryPanel; 063import org.opends.guitools.controlpanel.util.Utilities; 064import org.forgerock.i18n.LocalizableMessage; 065import org.opends.server.tools.ExportLDIF; 066 067/** 068 * The panel where the user can export the contents of the server to an LDIF 069 * file. 070 * 071 */ 072public class ExportLDIFPanel extends InclusionExclusionPanel 073{ 074 private static final long serialVersionUID = 2256902594454214644L; 075 private JComboBox backends; 076 private JTextField file; 077 private JCheckBox overwrite; 078 private JCheckBox compressData; 079 private JCheckBox encryptData; 080 private JCheckBox generateSignedHash; 081 private JCheckBox wrapText; 082 private JTextField wrapColumn; 083 private JButton bBrowse; 084 085 private JLabel lBackend; 086 private JLabel lNoBackendsFound; 087 private JLabel lFile; 088 private JLabel lExportOptions; 089 private JLabel lRemoteFileHelp; 090 private JCheckBox excludeOperationalAttrs; 091 092 private DocumentListener documentListener; 093 094 private ScheduleSummaryPanel schedulePanel; 095 096 /** 097 * Default constructor. 098 * 099 */ 100 public ExportLDIFPanel() 101 { 102 super(); 103 createLayout(); 104 } 105 106 /** {@inheritDoc} */ 107 public LocalizableMessage getTitle() 108 { 109 return INFO_CTRL_PANEL_EXPORT_LDIF_TITLE.get(); 110 } 111 112 /** {@inheritDoc} */ 113 public Component getPreferredFocusComponent() 114 { 115 return file; 116 } 117 118 /** {@inheritDoc} */ 119 public void toBeDisplayed(boolean visible) 120 { 121 if (visible) 122 { 123 documentListener.changedUpdate(null); 124 } 125 } 126 127 /** 128 * Creates the layout of the panel (but the contents are not populated here). 129 */ 130 private void createLayout() 131 { 132 GridBagConstraints gbc = new GridBagConstraints(); 133 gbc.gridx = 0; 134 gbc.gridy = 0; 135 gbc.gridwidth = 4; 136 addErrorPane(gbc); 137 138 gbc.anchor = GridBagConstraints.WEST; 139 gbc.weightx = 0.0; 140 gbc.gridy ++; 141 gbc.gridwidth = 1; 142 gbc.fill = GridBagConstraints.NONE; 143 lBackend = Utilities.createPrimaryLabel( 144 INFO_CTRL_PANEL_BACKEND_LABEL.get()); 145 add(lBackend, gbc); 146 gbc.insets.left = 10; 147 gbc.gridx = 1; 148 backends = Utilities.createComboBox(); 149 backends.setModel(new DefaultComboBoxModel(new String[]{})); 150 gbc.gridwidth = 3; 151 add(backends, gbc); 152 lNoBackendsFound = Utilities.createDefaultLabel( 153 INFO_CTRL_PANEL_NO_BACKENDS_FOUND_LABEL.get()); 154 add(lNoBackendsFound, gbc); 155 lNoBackendsFound.setVisible(false); 156 gbc.insets.top = 10; 157 158 gbc.gridx = 0; 159 gbc.gridy ++; 160 gbc.insets.left = 0; 161 gbc.gridwidth = 1; 162 lFile = Utilities.createPrimaryLabel( 163 INFO_CTRL_PANEL_EXPORT_TO_FILE_LABEL.get()); 164 add(lFile, gbc); 165 166 gbc.gridx = 1; 167 gbc.insets.left = 10; 168 gbc.gridwidth = 2; 169 file = Utilities.createTextField(); 170 documentListener = new DocumentListener() 171 { 172 /** {@inheritDoc} */ 173 public void changedUpdate(DocumentEvent ev) 174 { 175 String text = file.getText().trim(); 176 setEnabledOK(text != null && text.length() > 0 && !errorPane.isVisible()); 177 } 178 /** {@inheritDoc} */ 179 public void removeUpdate(DocumentEvent ev) 180 { 181 changedUpdate(ev); 182 } 183 /** {@inheritDoc} */ 184 public void insertUpdate(DocumentEvent ev) 185 { 186 changedUpdate(ev); 187 } 188 }; 189 file.getDocument().addDocumentListener(documentListener); 190 gbc.weightx = 1.0; 191 gbc.fill = GridBagConstraints.HORIZONTAL; 192 add(file, gbc); 193 bBrowse = Utilities.createButton( 194 INFO_CTRL_PANEL_BROWSE_BUTTON_LABEL.get()); 195 bBrowse.addActionListener( 196 new BrowseActionListener(file, 197 BrowseActionListener.BrowseType.CREATE_LDIF_FILE, this)); 198 gbc.gridx = 3; 199 gbc.gridwidth = 1; 200 gbc.weightx = 0.0; 201 bBrowse.setOpaque(false); 202 add(bBrowse, gbc); 203 204 lRemoteFileHelp = Utilities.createInlineHelpLabel( 205 INFO_CTRL_PANEL_REMOTE_SERVER_PATH.get()); 206 gbc.gridx = 1; 207 gbc.insets.top = 3; 208 gbc.insets.left = 10; 209 gbc.gridy ++; 210 gbc.gridwidth = 3; 211 add(lRemoteFileHelp, gbc); 212 213 gbc.gridx = 1; 214 gbc.gridy ++; 215 gbc.insets.left = 30; 216 gbc.insets.top = 5; 217 gbc.gridwidth = 3; 218 overwrite = 219 Utilities.createCheckBox(INFO_CTRL_PANEL_EXPORT_OVERWRITE_LABEL.get()); 220 overwrite.setOpaque(false); 221 add(overwrite, gbc); 222 223 gbc.gridx = 0; 224 gbc.gridy ++; 225 gbc.insets.left = 0; 226 gbc.insets.top = 10; 227 gbc.gridwidth = 1; 228 lExportOptions = 229 Utilities.createPrimaryLabel(INFO_CTRL_PANEL_EXPORT_OPTIONS.get()); 230 add(lExportOptions, gbc); 231 232 schedulePanel = new ScheduleSummaryPanel( 233 INFO_CTRL_PANEL_EXPORT_LDIF_TITLE.get().toString()); 234 schedulePanel.setSchedule(ScheduleType.createLaunchNow()); 235 236 gbc.insets.left = 10; 237 gbc.gridx = 1; 238 gbc.gridwidth = 3; 239 add(schedulePanel, gbc); 240 241 compressData = Utilities.createCheckBox( 242 INFO_CTRL_PANEL_COMPRESS_DATA_LABEL.get()); 243 compressData.setSelected(false); 244 245 gbc.gridy ++; 246 gbc.insets.top = 5; 247 add(compressData, gbc); 248 249 encryptData = Utilities.createCheckBox( 250 INFO_CTRL_PANEL_ENCRYPT_DATA_LABEL.get()); 251 252 /* 253 gbc.gridy ++; 254 gbc.insets.top = 5; 255 add(encryptData, gbc); 256*/ 257 generateSignedHash = Utilities.createCheckBox( 258 INFO_CTRL_PANEL_EXPORT_GENERATE_SIGNED_HASH.get()); 259 260 encryptData.addChangeListener(new ChangeListener() 261 { 262 /** {@inheritDoc} */ 263 public void stateChanged(ChangeEvent ev) 264 { 265 generateSignedHash.setEnabled(encryptData.isSelected()); 266 } 267 }); 268 encryptData.setSelected(false); 269 generateSignedHash.setEnabled(false); 270 271 /* 272 gbc.gridy ++; 273 gbc.insets.left = 30; 274 add(generateSignedHash, gbc); 275*/ 276 wrapText = Utilities.createCheckBox(INFO_CTRL_PANEL_EXPORT_WRAP_TEXT.get()); 277 wrapText.setOpaque(false); 278 gbc.insets.left = 10; 279 gbc.insets.top = 10; 280 gbc.gridy ++; 281 gbc.gridwidth = 1; 282 add(wrapText, gbc); 283 284 gbc.insets.left = 5; 285 gbc.gridx = 2; 286 wrapColumn = Utilities.createTextField("80", 4); 287 gbc.fill = GridBagConstraints.NONE; 288 add(wrapColumn, gbc); 289 gbc.fill = GridBagConstraints.HORIZONTAL; 290 291 wrapText.addChangeListener(new ChangeListener() 292 { 293 /** {@inheritDoc} */ 294 public void stateChanged(ChangeEvent ev) 295 { 296 wrapColumn.setEnabled(wrapText.isSelected()); 297 } 298 }); 299 wrapColumn.setEnabled(false); 300 wrapText.setSelected(false); 301 302 gbc.insets.top = 10; 303 gbc.insets.left = 0; 304 gbc.gridy ++; 305 gbc.gridx = 0; 306 gbc.gridwidth = 4; 307 gbc.fill = GridBagConstraints.HORIZONTAL; 308 excludeOperationalAttrs = Utilities.createCheckBox( 309 INFO_CTRL_PANEL_EXCLUDE_OPERATIONAL_ATTRIBUTES.get()); 310 excludeOperationalAttrs.setOpaque(false); 311 add(createDataExclusionOptions(new JLabel[]{null}, 312 new Component[]{excludeOperationalAttrs}), gbc); 313 gbc.gridy ++; 314 gbc.insets.top = 15; 315 add(createDataInclusionOptions(new JLabel[]{}, new Component[]{}), gbc); 316 addBottomGlue(gbc); 317 } 318 319 /** {@inheritDoc} */ 320 public void configurationChanged(ConfigurationChangeEvent ev) 321 { 322 ServerDescriptor desc = ev.getNewDescriptor(); 323 updateSimpleBackendComboBoxModel(backends, lNoBackendsFound, 324 ev.getNewDescriptor()); 325 326 updateErrorPaneAndOKButtonIfAuthRequired(desc, 327 isLocal() ? INFO_CTRL_PANEL_AUTHENTICATION_REQUIRED_FOR_EXPORT.get() : 328 INFO_CTRL_PANEL_CANNOT_CONNECT_TO_REMOTE_DETAILS.get(desc.getHostname())); 329 330 SwingUtilities.invokeLater(new Runnable() 331 { 332 public void run() 333 { 334 lRemoteFileHelp.setVisible(!isLocal()); 335 bBrowse.setVisible(isLocal()); 336 } 337 }); 338 } 339 340 /** {@inheritDoc} */ 341 protected void checkOKButtonEnable() 342 { 343 documentListener.changedUpdate(null); 344 } 345 346 /** {@inheritDoc} */ 347 public void okClicked() 348 { 349 setPrimaryValid(lBackend); 350 setPrimaryValid(lFile); 351 setPrimaryValid(lExportOptions); 352 final LinkedHashSet<LocalizableMessage> errors = new LinkedHashSet<>(); 353 354 String backendName = (String)backends.getSelectedItem(); 355 if (backendName == null) 356 { 357 errors.add(ERR_CTRL_PANEL_NO_BACKEND_SELECTED.get()); 358 setPrimaryInvalid(lBackend); 359 } 360 361 String ldifPath = file.getText(); 362 if (ldifPath == null || ldifPath.trim().equals("")) 363 { 364 errors.add(INFO_NO_LDIF_PATH.get()); 365 setPrimaryInvalid(lFile); 366 } 367 else if (isLocal()) 368 { 369 File f = new File(ldifPath); 370 if (f.isDirectory()) 371 { 372 errors.add(ERR_CTRL_PANEL_EXPORT_DIRECTORY_PROVIDED.get(ldifPath)); 373 } 374 } 375 376 addScheduleErrors(getSchedule(), errors, lExportOptions); 377 if (wrapText.isSelected()) 378 { 379 final String cols = wrapColumn.getText(); 380 final int minValue = 1; 381 final int maxValue = 1000; 382 final LocalizableMessage errMsg = ERR_CTRL_PANEL_INVALID_WRAP_COLUMN.get(minValue, maxValue); 383 if (!checkIntValue(errors, cols, minValue, maxValue, errMsg)) 384 { 385 setPrimaryInvalid(lExportOptions); 386 } 387 } 388 389 updateIncludeExclude(errors, backendName); 390 391 if (errors.isEmpty()) 392 { 393 ProgressDialog progressDialog = new ProgressDialog( 394 Utilities.createFrame(), 395 Utilities.getParentDialog(this), getTitle(), getInfo()); 396 ExportTask newTask = new ExportTask(getInfo(), progressDialog); 397 for (Task task : getInfo().getTasks()) 398 { 399 task.canLaunch(newTask, errors); 400 } 401 boolean confirmed = true; 402 if (errors.isEmpty()) 403 { 404 File f = new File(ldifPath); 405 if (overwrite.isSelected() && f.exists()) 406 { 407 confirmed = displayConfirmationDialog( 408 INFO_CTRL_PANEL_CONFIRMATION_REQUIRED_SUMMARY.get(), 409 INFO_CTRL_PANEL_CONFIRMATION_EXPORT_LDIF_DETAILS.get(ldifPath)); 410 } 411 } 412 if (errors.isEmpty() && confirmed) 413 { 414 launchOperation(newTask, 415 INFO_CTRL_PANEL_EXPORTING_LDIF_SUMMARY.get(backends.getSelectedItem()), 416 INFO_CTRL_PANEL_EXPORTING_LDIF_SUCCESSFUL_SUMMARY.get(), 417 INFO_CTRL_PANEL_EXPORTING_LDIF_SUCCESSFUL_DETAILS.get(), 418 ERR_CTRL_PANEL_EXPORTING_LDIF_ERROR_SUMMARY.get(), 419 null, 420 ERR_CTRL_PANEL_EXPORTING_LDIF_ERROR_DETAILS, 421 progressDialog); 422 progressDialog.setVisible(true); 423 Utilities.getParentDialog(this).setVisible(false); 424 } 425 } 426 if (!errors.isEmpty()) 427 { 428 displayErrorDialog(errors); 429 } 430 } 431 432 /** {@inheritDoc} */ 433 public void cancelClicked() 434 { 435 setPrimaryValid(lBackend); 436 setPrimaryValid(lFile); 437 setPrimaryValid(lExportOptions); 438 super.cancelClicked(); 439 } 440 441 private ScheduleType getSchedule() 442 { 443 return schedulePanel.getSchedule(); 444 } 445 446 /** 447 * The class that performs the export. 448 * 449 */ 450 protected class ExportTask extends InclusionExclusionTask 451 { 452 private Set<String> backendSet; 453 private String fileName; 454 /** 455 * The constructor of the task. 456 * @param info the control panel info. 457 * @param dlg the progress dialog that shows the progress of the task. 458 */ 459 public ExportTask(ControlPanelInfo info, ProgressDialog dlg) 460 { 461 super(info, dlg); 462 backendSet = new HashSet<>(); 463 backendSet.add((String)backends.getSelectedItem()); 464 fileName = file.getText(); 465 } 466 467 /** {@inheritDoc} */ 468 public Type getType() 469 { 470 return Type.EXPORT_LDIF; 471 } 472 473 /** {@inheritDoc} */ 474 public LocalizableMessage getTaskDescription() 475 { 476 return INFO_CTRL_PANEL_EXPORT_TASK_DESCRIPTION.get( 477 backendSet.iterator().next(), fileName); 478 } 479 480 /** {@inheritDoc} */ 481 public boolean canLaunch(Task taskToBeLaunched, 482 Collection<LocalizableMessage> incompatibilityReasons) 483 { 484 boolean canLaunch = true; 485 if (state == State.RUNNING && runningOnSameServer(taskToBeLaunched)) 486 { 487 // All the operations are incompatible if they apply to this backend. 488 Set<String> backends = new TreeSet<>(taskToBeLaunched.getBackends()); 489 backends.retainAll(getBackends()); 490 if (!backends.isEmpty()) 491 { 492 incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); 493 canLaunch = false; 494 } 495 } 496 return canLaunch; 497 } 498 499 /** {@inheritDoc} */ 500 public void runTask() 501 { 502 state = State.RUNNING; 503 lastException = null; 504 try 505 { 506 ArrayList<String> arguments = getCommandLineArguments(); 507 508 String[] args = new String[arguments.size()]; 509 510 arguments.toArray(args); 511 if (isServerRunning()) 512 { 513 returnCode = ExportLDIF.mainExportLDIF(args, false, outPrintStream, 514 errorPrintStream); 515 } 516 else 517 { 518 returnCode = executeCommandLine(getCommandLinePath(), args); 519 } 520 if (returnCode != 0) 521 { 522 state = State.FINISHED_WITH_ERROR; 523 } 524 else 525 { 526 state = State.FINISHED_SUCCESSFULLY; 527 } 528 } 529 catch (Throwable t) 530 { 531 lastException = t; 532 state = State.FINISHED_WITH_ERROR; 533 } 534 } 535 536 /** {@inheritDoc} */ 537 public Set<String> getBackends() 538 { 539 return backendSet; 540 } 541 542 /** {@inheritDoc} */ 543 protected ArrayList<String> getCommandLineArguments() 544 { 545 ArrayList<String> args = new ArrayList<>(); 546 args.add("--ldifFile"); 547 args.add(fileName); 548 args.add("--backendID"); 549 args.add(backendSet.iterator().next()); 550 551 if (!overwrite.isSelected()) 552 { 553 args.add("--appendToLDIF"); 554 } 555 556 if (compressData.isSelected()) 557 { 558 args.add("--compress"); 559 } 560 if (wrapText.isSelected()) 561 { 562 args.add("--wrapColumn"); 563 args.add(wrapColumn.getText().trim()); 564 } 565 if (excludeOperationalAttrs.isSelected()) 566 { 567 args.add("--excludeOperational"); 568 } 569 570 args.addAll(super.getCommandLineArguments()); 571 572 args.addAll(getScheduleArgs(getSchedule())); 573 574 if (isServerRunning()) 575 { 576 args.addAll(getConfigCommandLineArguments()); 577 } 578 args.add(getNoPropertiesFileArgument()); 579 580 return args; 581 } 582 583 /** {@inheritDoc} */ 584 protected String getCommandLinePath() 585 { 586 return getCommandLinePath("export-ldif"); 587 } 588 } 589}