/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2008-2010 Sun Microsystems, Inc.
* Portions Copyright 2014-2015 ForgeRock AS
*/
package org.opends.guitools.controlpanel.ui;
import static org.opends.messages.AdminToolMessages.*;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import org.forgerock.i18n.LocalizableMessage;
import org.opends.guitools.controlpanel.browser.BrowserController;
import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent;
import org.opends.guitools.controlpanel.task.NewEntryTask;
import org.opends.guitools.controlpanel.task.Task;
import org.opends.guitools.controlpanel.ui.nodes.BasicNode;
import org.opends.guitools.controlpanel.util.BackgroundTask;
import org.opends.guitools.controlpanel.util.Utilities;
import org.opends.server.types.Entry;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.util.LDIFException;
import org.opends.server.util.LDIFReader;
/**
* Abstract class used to re-factor some code among the different panels that
* are used to create a new entry.
*/
public abstract class AbstractNewEntryPanel extends StatusGenericPanel
{
private static final long serialVersionUID = 6894546787832469213L;
/** The parent node that was selected when the user clicked on the new entry action. */
protected BasicNode parentNode;
/** The browser controller. */
protected BrowserController controller;
/**
* Sets the parent and the browser controller for this panel.
* @param parentNode the selected parent node (or <CODE>null</CODE> if no
* parent node was selected).
* @param controller the browser controller.
*/
public void setParent(BasicNode parentNode, BrowserController controller)
{
this.parentNode = parentNode;
this.controller = controller;
}
/**
* Returns the title for the progress dialog.
* @return the title for the progress dialog.
*/
protected abstract LocalizableMessage getProgressDialogTitle();
/**
* Returns the LDIF representation of the new entry.
* @return the LDIF representation of the new entry.
*/
protected abstract String getLDIF();
/**
* Updates the list of errors by checking the syntax of the entry.
* @param errors the list of errors that must be updated.
*/
protected abstract void checkSyntax(ArrayList<LocalizableMessage> errors);
/**
* Returns <CODE>true</CODE> if the syntax of the entry must be checked in
* the background and <CODE>false</CODE> otherwise.
* @return <CODE>true</CODE> if the syntax of the entry must be checked in
* the background and <CODE>false</CODE> otherwise.
*/
protected boolean checkSyntaxBackground()
{
return false;
}
/** {@inheritDoc} */
public void okClicked()
{
final ArrayList<LocalizableMessage> errors = new ArrayList<>();
if (checkSyntaxBackground())
{
BackgroundTask<Void> worker = new BackgroundTask<Void>()
{
public Void processBackgroundTask()
{
try
{
Thread.sleep(2000);
}
catch (Throwable t)
{
}
checkSyntax(errors);
return null;
}
public void backgroundTaskCompleted(Void returnValue, Throwable t)
{
if (t != null)
{
errors.add(ERR_CTRL_PANEL_UNEXPECTED_DETAILS.get(t));
}
displayMainPanel();
setEnabledCancel(true);
setEnabledOK(true);
handleErrorsAndLaunchTask(errors);
}
};
displayMessage(INFO_CTRL_PANEL_CHECKING_SUMMARY.get());
setEnabledCancel(false);
setEnabledOK(false);
worker.startBackgroundTask();
}
else
{
checkSyntax(errors);
handleErrorsAndLaunchTask(errors);
}
}
/**
* Checks that there are not errors in the list and launches a new entry
* task.
* @param errors the list of errors.
*/
private void handleErrorsAndLaunchTask(ArrayList<LocalizableMessage> errors)
{
Entry entry = null;
if (errors.isEmpty())
{
try
{
entry = getEntry();
}
catch (Throwable t)
{
// Unexpected error: getEntry() should work after calling checkSyntax
throw new RuntimeException("Unexpected error: "+t, t);
}
String dn = entry.getName().toString();
// Checking for the existence of an entry is fast enough so we can do
// it on the event thread.
if (entryExists(dn))
{
errors.add(ERR_CTRL_PANEL_ENTRY_ALREADY_EXISTS.get(dn));
}
}
if (errors.isEmpty())
{
final ProgressDialog dlg = new ProgressDialog(
Utilities.createFrame(), Utilities.getParentDialog(this),
getProgressDialogTitle(), getInfo());
try
{
NewEntryTask newTask =
new NewEntryTask(getInfo(), dlg, entry, getLDIF(),
parentNode, controller);
for (Task task : getInfo().getTasks())
{
task.canLaunch(newTask, errors);
}
if (errors.isEmpty())
{
launchOperation(newTask,
INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUMMARY.get(),
INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUCCESSFUL_SUMMARY.get(),
INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUCCESSFUL_DETAILS.get(),
ERR_CTRL_PANEL_CREATING_NEW_ENTRY_ERROR_SUMMARY.get(),
ERR_CTRL_PANEL_CREATING_NEW_ENTRY_ERROR_DETAILS.get(),
null,
dlg);
dlg.setVisible(true);
Utilities.getParentDialog(this).setVisible(false);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
dlg.toFront();
}
});
}
}
catch (Throwable t)
{
// Unexpected error: getEntry() should work after calling checkSyntax
throw new RuntimeException("Unexpected error: "+t, t);
}
}
if (!errors.isEmpty())
{
displayErrorDialog(errors);
}
}
/** {@inheritDoc} */
public void configurationChanged(ConfigurationChangeEvent ev)
{
updateErrorPaneIfServerRunningAndAuthRequired(ev.getNewDescriptor(),
INFO_CTRL_PANEL_NEW_ENTRY_REQUIRES_SERVER_RUNNING.get(),
INFO_CTRL_PANEL_NEW_ENTRY_REQUIRES_AUTHENTICATION.get());
}
/**
* Returns the entry object representing what the user provided as data.
* @return the entry object representing what the user provided as data.
* @throws LDIFException if there is an error with the LDIF syntax.
* @throws IOException if there is an error creating the internal stream.
*/
protected Entry getEntry() throws LDIFException, IOException
{
LDIFImportConfig ldifImportConfig = null;
try
{
String ldif = getLDIF();
if (ldif.trim().length() == 0)
{
throw new LDIFException(ERR_LDIF_REPRESENTATION_REQUIRED.get());
}
ldifImportConfig = new LDIFImportConfig(new StringReader(ldif));
LDIFReader reader = new LDIFReader(ldifImportConfig);
Entry entry = reader.readEntry(checkSchema());
if (entry == null)
{
throw new LDIFException(ERR_LDIF_REPRESENTATION_REQUIRED.get());
}
if (entry.getObjectClasses().isEmpty())
{
throw new LDIFException(ERR_OBJECTCLASS_FOR_ENTRY_REQUIRED.get());
}
return entry;
}
finally
{
if (ldifImportConfig != null)
{
ldifImportConfig.close();
}
}
}
/**
* Returns <CODE>true</CODE> if the schema must be checked and
* <CODE>false</CODE> otherwise.
* @return <CODE>true</CODE> if the schema must be checked and
* <CODE>false</CODE> otherwise.
*/
protected boolean checkSchema()
{
return getInfo().getServerDescriptor().isSchemaEnabled();
}
}