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