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 java.awt.Component; 023import java.awt.Dimension; 024import java.awt.GridBagConstraints; 025import java.awt.event.ActionEvent; 026import java.awt.event.ActionListener; 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.HashSet; 030import java.util.LinkedHashSet; 031import java.util.Set; 032 033import javax.swing.Box; 034import javax.swing.JButton; 035import javax.swing.JEditorPane; 036import javax.swing.JLabel; 037import javax.swing.SwingUtilities; 038 039import org.forgerock.i18n.LocalizableMessage; 040import org.opends.guitools.controlpanel.datamodel.ControlPanelInfo; 041import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 042import org.opends.guitools.controlpanel.task.Task; 043import org.opends.guitools.controlpanel.util.Utilities; 044import org.opends.server.tools.ConfigureWindowsService; 045 046/** The panel that displays the Windows Service panel configuration for the server. */ 047public class WindowsServicePanel extends StatusGenericPanel 048{ 049 private static final long serialVersionUID = 6415350296295459469L; 050 private JLabel lState; 051 private JButton bEnable; 052 private JButton bDisable; 053 054 private boolean previousLocal = true; 055 056 private boolean isWindowsServiceEnabled; 057 058 /** Default constructor. */ 059 public WindowsServicePanel() 060 { 061 super(); 062 createLayout(); 063 } 064 065 @Override 066 public LocalizableMessage getTitle() 067 { 068 return INFO_CTRL_PANEL_WINDOWS_SERVICE_TITLE.get(); 069 } 070 071 /** Creates the layout of the panel (but the contents are not populated here). */ 072 private void createLayout() 073 { 074 GridBagConstraints gbc = new GridBagConstraints(); 075 gbc.anchor = GridBagConstraints.WEST; 076 gbc.weightx = 0.0; 077 gbc.gridx = 0; 078 gbc.gridy = 0; 079 gbc.gridwidth = 4; 080 gbc.weightx = 1.0; 081 gbc.fill = GridBagConstraints.BOTH; 082 083 String text = INFO_CTRL_PANEL_WINDOWS_SERVICE_PANEL_TEXT.get().toString(); 084 085 JEditorPane pane = Utilities.makeHtmlPane(text, 086 ColorAndFontConstants.defaultFont); 087 088 Utilities.updatePreferredSize(pane, 100, text, 089 ColorAndFontConstants.defaultFont, false); 090 gbc.weighty = 0.0; 091 add(pane, gbc); 092 093 gbc.gridy = 1; 094 gbc.gridwidth = 1; 095 gbc.weightx = 0.0; 096 gbc.weighty = 0.0; 097 JLabel lWindowsService =Utilities.createPrimaryLabel( 098 INFO_CTRL_PANEL_WINDOWS_SERVICE_INTEGRATION_LABEL.get()); 099 gbc.insets.top = 10; 100 add(lWindowsService, gbc); 101 lState = Utilities.createDefaultLabel(); 102 lState.setText(isWindowsServiceEnabled ? 103 INFO_ENABLED_LABEL.get().toString() : 104 INFO_DISABLED_LABEL.get().toString()); 105 gbc.insets.left = 10; 106 gbc.gridx = 1; 107 add(lState, gbc); 108 109 bEnable = Utilities.createButton( 110 INFO_CTRL_PANEL_ENABLE_WINDOWS_SERVICE_BUTTON.get()); 111 bDisable = Utilities.createButton( 112 INFO_CTRL_PANEL_DISABLE_WINDOWS_SERVICE_BUTTON.get()); 113 bEnable.setOpaque(false); 114 bDisable.setOpaque(false); 115 int maxWidth = Math.max(bEnable.getPreferredSize().width, 116 bDisable.getPreferredSize().width); 117 int maxHeight = Math.max(bEnable.getPreferredSize().height, 118 bDisable.getPreferredSize().height); 119 bEnable.setPreferredSize(new Dimension(maxWidth, maxHeight)); 120 bDisable.setPreferredSize(new Dimension(maxWidth, maxHeight)); 121 122 ActionListener listener = new ActionListener() 123 { 124 @Override 125 public void actionPerformed(ActionEvent ev) 126 { 127 updateWindowsService(); 128 } 129 }; 130 bEnable.addActionListener(listener); 131 bDisable.addActionListener(listener); 132 133 gbc.gridx = 2; 134 add(bEnable, gbc); 135 add(bDisable, gbc); 136 137 gbc.weightx = 1.0; 138 gbc.gridx = 3; 139 add(Box.createHorizontalGlue(), gbc); 140 141 bEnable.setVisible(!isWindowsServiceEnabled); 142 bDisable.setVisible(isWindowsServiceEnabled); 143 addBottomGlue(gbc); 144 } 145 146 @Override 147 public GenericDialog.ButtonType getButtonType() 148 { 149 return GenericDialog.ButtonType.CLOSE; 150 } 151 152 @Override 153 public Component getPreferredFocusComponent() 154 { 155 if (!isWindowsServiceEnabled) 156 { 157 return bEnable; 158 } 159 else 160 { 161 return bDisable; 162 } 163 } 164 165 @Override 166 public void configurationChanged(ConfigurationChangeEvent ev) 167 { 168 boolean previousValue = isWindowsServiceEnabled; 169 isWindowsServiceEnabled = ev.getNewDescriptor().isWindowsServiceEnabled(); 170 171 final boolean isLocal = ev.getNewDescriptor().isLocal(); 172 if (isLocal != previousLocal || isWindowsServiceEnabled != previousValue) 173 { 174 previousLocal = isLocal; 175 SwingUtilities.invokeLater(new Runnable() 176 { 177 @Override 178 public void run() 179 { 180 lState.setText(isWindowsServiceEnabled ? 181 INFO_ENABLED_LABEL.get().toString() : 182 INFO_DISABLED_LABEL.get().toString()); 183 bEnable.setVisible(!isWindowsServiceEnabled); 184 bDisable.setVisible(isWindowsServiceEnabled); 185 186 if (!isLocal) 187 { 188 displayErrorMessage(INFO_CTRL_PANEL_SERVER_REMOTE_SUMMARY.get(), 189 INFO_CTRL_PANEL_SERVER_MUST_BE_LOCAL_WINDOWS_SERVICE_SUMMARY.get()); 190 packParentDialog(); 191 } 192 else 193 { 194 displayMainPanel(); 195 } 196 } 197 }); 198 } 199 } 200 201 @Override 202 public void okClicked() 203 { 204 // NO ok button 205 } 206 207 private void updateWindowsService() 208 { 209 LinkedHashSet<LocalizableMessage> errors = new LinkedHashSet<>(); 210 ProgressDialog progressDialog = new ProgressDialog( 211 Utilities.createFrame(), Utilities.getParentDialog(this), getTitle(), 212 getInfo()); 213 WindowsServiceTask newTask = new WindowsServiceTask(getInfo(), 214 progressDialog, !isWindowsServiceEnabled); 215 for (Task task : getInfo().getTasks()) 216 { 217 task.canLaunch(newTask, errors); 218 } 219 if (errors.isEmpty()) 220 { 221 if (isWindowsServiceEnabled) 222 { 223 launchOperation(newTask, 224 INFO_CTRL_PANEL_DISABLING_WINDOWS_SERVICE_SUMMARY.get(), 225 INFO_CTRL_PANEL_DISABLING_WINDOWS_SERVICE_SUCCESSFUL_SUMMARY.get(), 226 INFO_CTRL_PANEL_DISABLING_WINDOWS_SERVICE_SUCCESSFUL_DETAILS.get(), 227 ERR_CTRL_PANEL_DISABLING_WINDOWS_SERVICE_ERROR_SUMMARY.get(), 228 null, 229 ERR_CTRL_PANEL_DISABLING_WINDOWS_SERVICE_ERROR_DETAILS, 230 progressDialog); 231 } 232 else 233 { 234 launchOperation(newTask, 235 INFO_CTRL_PANEL_ENABLING_WINDOWS_SERVICE_SUMMARY.get(), 236 INFO_CTRL_PANEL_ENABLING_WINDOWS_SERVICE_SUCCESSFUL_SUMMARY.get(), 237 INFO_CTRL_PANEL_ENABLING_WINDOWS_SERVICE_SUCCESSFUL_DETAILS.get(), 238 ERR_CTRL_PANEL_ENABLING_WINDOWS_SERVICE_ERROR_SUMMARY.get(), 239 null, 240 ERR_CTRL_PANEL_ENABLING_WINDOWS_SERVICE_ERROR_DETAILS, 241 progressDialog); 242 } 243 progressDialog.setVisible(true); 244 } 245 else 246 { 247 displayErrorDialog(errors); 248 } 249 } 250 251 /** The task in charge of updating the windows service configuration. */ 252 private class WindowsServiceTask extends Task 253 { 254 private Set<String> backendSet; 255 private boolean enableService; 256 /** 257 * The constructor of the task. 258 * @param info the control panel info. 259 * @param dlg the progress dialog that shows the progress of the task. 260 * @param enableService whether the windows service must be enabled or 261 * disabled. 262 */ 263 private WindowsServiceTask(ControlPanelInfo info, ProgressDialog dlg, 264 boolean enableService) 265 { 266 super(info, dlg); 267 this.enableService = enableService; 268 backendSet = new HashSet<>(); 269 } 270 271 @Override 272 public Type getType() 273 { 274 if (enableService) 275 { 276 return Type.ENABLE_WINDOWS_SERVICE; 277 } 278 else 279 { 280 return Type.DISABLE_WINDOWS_SERVICE; 281 } 282 } 283 284 @Override 285 public LocalizableMessage getTaskDescription() 286 { 287 if (enableService) 288 { 289 return INFO_CTRL_PANEL_ENABLE_WINDOWS_SERVICE_TASK_DESCRIPTION.get(); 290 } 291 else 292 { 293 return INFO_CTRL_PANEL_DISABLE_WINDOWS_SERVICE_TASK_DESCRIPTION.get(); 294 } 295 } 296 297 @Override 298 public boolean canLaunch(Task taskToBeLaunched, 299 Collection<LocalizableMessage> incompatibilityReasons) 300 { 301 Type type = taskToBeLaunched.getType(); 302 if (state == State.RUNNING 303 && runningOnSameServer(taskToBeLaunched) 304 && (type == Type.ENABLE_WINDOWS_SERVICE 305 || type == Type.DISABLE_WINDOWS_SERVICE)) 306 { 307 incompatibilityReasons.add(getIncompatibilityMessage(this, taskToBeLaunched)); 308 return false; 309 } 310 return true; 311 } 312 313 @Override 314 public void runTask() 315 { 316 state = State.RUNNING; 317 lastException = null; 318 try 319 { 320 if (enableService) 321 { 322 returnCode = ConfigureWindowsService.enableService(outPrintStream, errorPrintStream); 323 if (returnCode != ConfigureWindowsService.SERVICE_ALREADY_ENABLED && 324 returnCode != ConfigureWindowsService.SERVICE_ENABLE_SUCCESS) 325 { 326 state = State.FINISHED_WITH_ERROR; 327 } 328 else 329 { 330 state = State.FINISHED_SUCCESSFULLY; 331 } 332 } 333 else 334 { 335 returnCode = ConfigureWindowsService.disableService(outPrintStream, errorPrintStream); 336 if (returnCode != ConfigureWindowsService.SERVICE_ALREADY_DISABLED 337 && returnCode != ConfigureWindowsService.SERVICE_DISABLE_SUCCESS) 338 { 339 state = State.FINISHED_WITH_ERROR; 340 } 341 else 342 { 343 state = State.FINISHED_SUCCESSFULLY; 344 } 345 } 346 } 347 catch (Throwable t) 348 { 349 lastException = t; 350 state = State.FINISHED_WITH_ERROR; 351 } 352 } 353 354 @Override 355 public Set<String> getBackends() 356 { 357 return backendSet; 358 } 359 360 @Override 361 protected ArrayList<String> getCommandLineArguments() 362 { 363 ArrayList<String> args = new ArrayList<>(); 364 365 if (enableService) 366 { 367 args.add("--enableService"); 368 } 369 else 370 { 371 args.add("--disableService"); 372 } 373 374 return args; 375 } 376 377 @Override 378 protected String getCommandLinePath() 379 { 380 return getCommandLinePath("windows-service"); 381 } 382 } 383}