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