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