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-2016 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 @Override 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 @Override 103 public Void processBackgroundTask() 104 { 105 try 106 { 107 Thread.sleep(2000); 108 } 109 catch (Throwable t) 110 { 111 } 112 checkSyntax(errors); 113 return null; 114 } 115 @Override 116 public void backgroundTaskCompleted(Void returnValue, Throwable t) 117 { 118 if (t != null) 119 { 120 errors.add(ERR_CTRL_PANEL_UNEXPECTED_DETAILS.get(t)); 121 } 122 displayMainPanel(); 123 setEnabledCancel(true); 124 setEnabledOK(true); 125 handleErrorsAndLaunchTask(errors); 126 } 127 }; 128 displayMessage(INFO_CTRL_PANEL_CHECKING_SUMMARY.get()); 129 setEnabledCancel(false); 130 setEnabledOK(false); 131 worker.startBackgroundTask(); 132 } 133 else 134 { 135 checkSyntax(errors); 136 handleErrorsAndLaunchTask(errors); 137 } 138 } 139 140 /** 141 * Checks that there are not errors in the list and launches a new entry 142 * task. 143 * @param errors the list of errors. 144 */ 145 private void handleErrorsAndLaunchTask(ArrayList<LocalizableMessage> errors) 146 { 147 Entry entry = null; 148 if (errors.isEmpty()) 149 { 150 try 151 { 152 entry = getEntry(); 153 } 154 catch (Throwable t) 155 { 156 // Unexpected error: getEntry() should work after calling checkSyntax 157 throw new RuntimeException("Unexpected error: "+t, t); 158 } 159 String dn = entry.getName().toString(); 160 // Checking for the existence of an entry is fast enough so we can do 161 // it on the event thread. 162 if (entryExists(dn)) 163 { 164 errors.add(ERR_CTRL_PANEL_ENTRY_ALREADY_EXISTS.get(dn)); 165 } 166 } 167 if (errors.isEmpty()) 168 { 169 final ProgressDialog dlg = new ProgressDialog( 170 Utilities.createFrame(), Utilities.getParentDialog(this), 171 getProgressDialogTitle(), getInfo()); 172 try 173 { 174 NewEntryTask newTask = 175 new NewEntryTask(getInfo(), dlg, entry, getLDIF(), 176 parentNode, controller); 177 for (Task task : getInfo().getTasks()) 178 { 179 task.canLaunch(newTask, errors); 180 } 181 if (errors.isEmpty()) 182 { 183 launchOperation(newTask, 184 INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUMMARY.get(), 185 INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUCCESSFUL_SUMMARY.get(), 186 INFO_CTRL_PANEL_CREATING_NEW_ENTRY_SUCCESSFUL_DETAILS.get(), 187 ERR_CTRL_PANEL_CREATING_NEW_ENTRY_ERROR_SUMMARY.get(), 188 ERR_CTRL_PANEL_CREATING_NEW_ENTRY_ERROR_DETAILS.get(), 189 null, 190 dlg); 191 dlg.setVisible(true); 192 Utilities.getParentDialog(this).setVisible(false); 193 SwingUtilities.invokeLater(new Runnable() 194 { 195 @Override 196 public void run() 197 { 198 dlg.toFront(); 199 } 200 }); 201 } 202 } 203 catch (Throwable t) 204 { 205 // Unexpected error: getEntry() should work after calling checkSyntax 206 throw new RuntimeException("Unexpected error: "+t, t); 207 } 208 } 209 if (!errors.isEmpty()) 210 { 211 displayErrorDialog(errors); 212 } 213 } 214 215 @Override 216 public void configurationChanged(ConfigurationChangeEvent ev) 217 { 218 updateErrorPaneIfServerRunningAndAuthRequired(ev.getNewDescriptor(), 219 INFO_CTRL_PANEL_NEW_ENTRY_REQUIRES_SERVER_RUNNING.get(), 220 INFO_CTRL_PANEL_NEW_ENTRY_REQUIRES_AUTHENTICATION.get()); 221 } 222 223 /** 224 * Returns the entry object representing what the user provided as data. 225 * @return the entry object representing what the user provided as data. 226 * @throws LDIFException if there is an error with the LDIF syntax. 227 * @throws IOException if there is an error creating the internal stream. 228 */ 229 protected Entry getEntry() throws LDIFException, IOException 230 { 231 LDIFImportConfig ldifImportConfig = null; 232 try 233 { 234 String ldif = getLDIF(); 235 if (ldif.trim().length() == 0) 236 { 237 throw new LDIFException(ERR_LDIF_REPRESENTATION_REQUIRED.get()); 238 } 239 240 ldifImportConfig = new LDIFImportConfig(new StringReader(ldif)); 241 LDIFReader reader = new LDIFReader(ldifImportConfig); 242 Entry entry = reader.readEntry(checkSchema()); 243 if (entry == null) 244 { 245 throw new LDIFException(ERR_LDIF_REPRESENTATION_REQUIRED.get()); 246 } 247 if (entry.getObjectClasses().isEmpty()) 248 { 249 throw new LDIFException(ERR_OBJECTCLASS_FOR_ENTRY_REQUIRED.get()); 250 } 251 return entry; 252 } 253 finally 254 { 255 if (ldifImportConfig != null) 256 { 257 ldifImportConfig.close(); 258 } 259 } 260 } 261 262 /** 263 * Returns <CODE>true</CODE> if the schema must be checked and 264 * <CODE>false</CODE> otherwise. 265 * @return <CODE>true</CODE> if the schema must be checked and 266 * <CODE>false</CODE> otherwise. 267 */ 268 private boolean checkSchema() 269 { 270 return getInfo().getServerDescriptor().isSchemaEnabled(); 271 } 272}