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-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2015 ForgeRock AS. 016 */ 017package org.opends.guitools.controlpanel.ui; 018 019import static org.opends.messages.AdminToolMessages.*; 020 021import java.io.IOException; 022import java.io.StringReader; 023import java.util.ArrayList; 024 025import javax.swing.SwingUtilities; 026 027import org.forgerock.i18n.LocalizableMessage; 028import org.opends.guitools.controlpanel.browser.BrowserController; 029import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 030import org.opends.guitools.controlpanel.task.NewEntryTask; 031import org.opends.guitools.controlpanel.task.Task; 032import org.opends.guitools.controlpanel.ui.nodes.BasicNode; 033import org.opends.guitools.controlpanel.util.BackgroundTask; 034import org.opends.guitools.controlpanel.util.Utilities; 035import org.opends.server.types.Entry; 036import org.opends.server.types.LDIFImportConfig; 037import org.opends.server.util.LDIFException; 038import org.opends.server.util.LDIFReader; 039 040/** 041 * Abstract class used to re-factor some code among the different panels that 042 * are used to create a new entry. 043 */ 044public abstract class AbstractNewEntryPanel extends StatusGenericPanel 045{ 046 private static final long serialVersionUID = 6894546787832469213L; 047 048 /** The parent node that was selected when the user clicked on the new entry action. */ 049 protected BasicNode parentNode; 050 /** The browser controller. */ 051 protected BrowserController controller; 052 053 /** 054 * Sets the parent and the browser controller for this panel. 055 * @param parentNode the selected parent node (or <CODE>null</CODE> if no 056 * parent node was selected). 057 * @param controller the browser controller. 058 */ 059 public void setParent(BasicNode parentNode, BrowserController controller) 060 { 061 this.parentNode = parentNode; 062 this.controller = controller; 063 } 064 065 /** 066 * Returns the title for the progress dialog. 067 * @return the title for the progress dialog. 068 */ 069 protected abstract LocalizableMessage getProgressDialogTitle(); 070 /** 071 * Returns the LDIF representation of the new entry. 072 * @return the LDIF representation of the new entry. 073 */ 074 protected abstract String getLDIF(); 075 076 /** 077 * Updates the list of errors by checking the syntax of the entry. 078 * @param errors the list of errors that must be updated. 079 */ 080 protected abstract void checkSyntax(ArrayList<LocalizableMessage> errors); 081 082 /** 083 * Returns <CODE>true</CODE> if the syntax of the entry must be checked in 084 * the background and <CODE>false</CODE> otherwise. 085 * @return <CODE>true</CODE> if the syntax of the entry must be checked in 086 * the background and <CODE>false</CODE> otherwise. 087 */ 088 protected boolean checkSyntaxBackground() 089 { 090 return false; 091 } 092 093 /** {@inheritDoc} */ 094 public void okClicked() 095 { 096 final ArrayList<LocalizableMessage> errors = new ArrayList<>(); 097 098 if (checkSyntaxBackground()) 099 { 100 BackgroundTask<Void> worker = new BackgroundTask<Void>() 101 { 102 public Void processBackgroundTask() 103 { 104 try 105 { 106 Thread.sleep(2000); 107 } 108 catch (Throwable t) 109 { 110 } 111 checkSyntax(errors); 112 return null; 113 } 114 public void backgroundTaskCompleted(Void returnValue, Throwable t) 115 { 116 if (t != null) 117 { 118 errors.add(ERR_CTRL_PANEL_UNEXPECTED_DETAILS.get(t)); 119 } 120 displayMainPanel(); 121 setEnabledCancel(true); 122 setEnabledOK(true); 123 handleErrorsAndLaunchTask(errors); 124 } 125 }; 126 displayMessage(INFO_CTRL_PANEL_CHECKING_SUMMARY.get()); 127 setEnabledCancel(false); 128 setEnabledOK(false); 129 worker.startBackgroundTask(); 130 } 131 else 132 { 133 checkSyntax(errors); 134 handleErrorsAndLaunchTask(errors); 135 } 136 } 137 138 /** 139 * Checks that there are not errors in the list and launches a new entry 140 * task. 141 * @param errors the list of errors. 142 */ 143 private void handleErrorsAndLaunchTask(ArrayList<LocalizableMessage> errors) 144 { 145 Entry entry = null; 146 if (errors.isEmpty()) 147 { 148 try 149 { 150 entry = getEntry(); 151 } 152 catch (Throwable t) 153 { 154 // Unexpected error: getEntry() should work after calling checkSyntax 155 throw new RuntimeException("Unexpected error: "+t, t); 156 } 157 String dn = entry.getName().toString(); 158 // Checking for the existence of an entry is fast enough so we can do 159 // it on the event thread. 160 if (entryExists(dn)) 161 { 162 errors.add(ERR_CTRL_PANEL_ENTRY_ALREADY_EXISTS.get(dn)); 163 } 164 } 165 if (errors.isEmpty()) 166 { 167 final ProgressDialog dlg = new ProgressDialog( 168 Utilities.createFrame(), Utilities.getParentDialog(this), 169 getProgressDialogTitle(), getInfo()); 170 try 171 { 172 NewEntryTask newTask = 173 new NewEntryTask(getInfo(), dlg, entry, getLDIF(), 174 parentNode, controller); 175 for (Task task : getInfo().getTasks()) 176 { 177 task.canLaunch(newTask, errors); 178 } 179 if (errors.isEmpty()) 180 { 181 launchOperation(newTask, 182 INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUMMARY.get(), 183 INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUCCESSFUL_SUMMARY.get(), 184 INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUCCESSFUL_DETAILS.get(), 185 ERR_CTRL_PANEL_CREATING_NEW_ENTRY_ERROR_SUMMARY.get(), 186 ERR_CTRL_PANEL_CREATING_NEW_ENTRY_ERROR_DETAILS.get(), 187 null, 188 dlg); 189 dlg.setVisible(true); 190 Utilities.getParentDialog(this).setVisible(false); 191 SwingUtilities.invokeLater(new Runnable() 192 { 193 public void run() 194 { 195 dlg.toFront(); 196 } 197 }); 198 } 199 } 200 catch (Throwable t) 201 { 202 // Unexpected error: getEntry() should work after calling checkSyntax 203 throw new RuntimeException("Unexpected error: "+t, t); 204 } 205 } 206 if (!errors.isEmpty()) 207 { 208 displayErrorDialog(errors); 209 } 210 } 211 212 /** {@inheritDoc} */ 213 public void configurationChanged(ConfigurationChangeEvent ev) 214 { 215 updateErrorPaneIfServerRunningAndAuthRequired(ev.getNewDescriptor(), 216 INFO_CTRL_PANEL_NEW_ENTRY_REQUIRES_SERVER_RUNNING.get(), 217 INFO_CTRL_PANEL_NEW_ENTRY_REQUIRES_AUTHENTICATION.get()); 218 } 219 220 /** 221 * Returns the entry object representing what the user provided as data. 222 * @return the entry object representing what the user provided as data. 223 * @throws LDIFException if there is an error with the LDIF syntax. 224 * @throws IOException if there is an error creating the internal stream. 225 */ 226 protected Entry getEntry() throws LDIFException, IOException 227 { 228 LDIFImportConfig ldifImportConfig = null; 229 try 230 { 231 String ldif = getLDIF(); 232 if (ldif.trim().length() == 0) 233 { 234 throw new LDIFException(ERR_LDIF_REPRESENTATION_REQUIRED.get()); 235 } 236 237 ldifImportConfig = new LDIFImportConfig(new StringReader(ldif)); 238 LDIFReader reader = new LDIFReader(ldifImportConfig); 239 Entry entry = reader.readEntry(checkSchema()); 240 if (entry == null) 241 { 242 throw new LDIFException(ERR_LDIF_REPRESENTATION_REQUIRED.get()); 243 } 244 if (entry.getObjectClasses().isEmpty()) 245 { 246 throw new LDIFException(ERR_OBJECTCLASS_FOR_ENTRY_REQUIRED.get()); 247 } 248 return entry; 249 } 250 finally 251 { 252 if (ldifImportConfig != null) 253 { 254 ldifImportConfig.close(); 255 } 256 } 257 } 258 259 /** 260 * Returns <CODE>true</CODE> if the schema must be checked and 261 * <CODE>false</CODE> otherwise. 262 * @return <CODE>true</CODE> if the schema must be checked and 263 * <CODE>false</CODE> otherwise. 264 */ 265 protected boolean checkSchema() 266 { 267 return getInfo().getServerDescriptor().isSchemaEnabled(); 268 } 269}