001/** 002 * Copyright (C) 2014 Universidade de Aveiro, DETI/IEETA, Bioinformatics Group - http://bioinformatics.ua.pt/ 003 * 004 * This file is part of Dicoogle/dicoogle. 005 * 006 * Dicoogle/dicoogle is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Dicoogle/dicoogle is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Dicoogle. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package pt.ua.dicoogle.server.web.management; 020 021import java.io.UnsupportedEncodingException; 022import java.util.Enumeration; 023import java.util.Map; 024import java.util.HashMap; 025 026import pt.ua.dicoogle.core.XMLSupport; 027import pt.ua.dicoogle.core.ServerSettings; 028 029import java.io.IOException; 030 031import javax.servlet.http.HttpServletRequest; 032import javax.servlet.http.HttpServletResponse; 033 034import pt.ua.dicoogle.server.ControlServices; 035import pt.ua.dicoogle.plugins.PluginController; 036import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4; 037import pt.ua.dicoogle.sdk.settings.Utils; 038 039// FIXME do the procedures of this class need to be synchronized?!? 040/** 041 * A wrapper used to manage the services and plugins remotely through the web 042 * environment/app. 043 * 044 * @author António Novo <antonio.novo@ua.pt> 045 */ 046public class Services { 047 048 /** 049 * The current instance of this class. 050 */ 051 private static Services instance; 052 /** 053 * Pointers to the objects that maintain the services and plugins 054 * information. 055 */ 056 private static ControlServices svcs; 057 private static PluginController plgs; 058 /** 059 * Types of actions to perform. 060 */ 061 public static final int SVC_NO_ACTION = 0; 062 public static final int SVC_START = 1; 063 public static final int SVC_STOP = 2; 064 public static final int SVC_INIT_START = 3; 065 public static final int SVC_SET_PORT = 4; 066 public static final int SVC_SET_SETTINGS = 5; 067 /** 068 * Textual representation of the actions available. 069 */ 070 public static final String ACTION_START = "start"; 071 public static final String ACTION_STOP = "stop"; 072 public static final String ACTION_INIT_START = "init-start"; 073 public static final String ACTION_SET_PORT = "set-port"; 074 public static final String ACTION_SET_ADVANCED_SETTINGS = "set-settings"; 075 /** 076 * Textural representation of the params available. 077 */ 078 public static final String PARAM_ACTION = "action"; 079 public static final String PARAM_SERVICE = "service"; 080 public static final String PARAM_INIT_START = "init-start"; 081 public static final String PARAM_PORT = "port"; 082 /** 083 * The embedded services name. 084 */ 085 public static final String storageName = "Storage"; 086 public static final String queryRetrieveName = "Query Retrieve"; 087 public static final String webServicesName = "Web Services"; 088 public static final String webServerName = "Web Server"; 089 public static final String remoteGUIName = "Remote GUI"; 090 /** 091 * The results indicating what was wrong with a performAction call. 092 */ 093 public static final int RES_NO_ACTION = 0; 094 public static final int RES_INVALID_ACTION = 1; 095 public static final int RES_NO_SERVICE_NAME = 2; 096 public static final int RES_INVALID_SERVICE_NAME = 3; 097 public static final int RES_INVALID_ACTION_PARAMETER = 4; 098 public static final int RES_WARNING = 5; 099 public static final int RES_OK = 6; 100 /** 101 * The object responsible for saving the settings between server inits. 102 */ 103 private XMLSupport xmlSupport; 104 /** 105 * Server settings container. 106 */ 107 private ServerSettings cfgs; 108 109 private Services() { 110 svcs = ControlServices.getInstance(); 111 plgs = PluginController.getInstance(); 112 113 cfgs = ServerSettings.getInstance(); 114 xmlSupport = new XMLSupport(); 115 } 116 117 /** 118 * Returns the current instance of this class. 119 * 120 * @return the current instance of this class. 121 */ 122 public synchronized static Services getInstance() { 123 if (instance == null) { 124 instance = new Services(); 125 } 126 127 return instance; 128 } 129 130 /** 131 * This converts and applies the new textual values into the 132 * originalSettings HashMap, taking into account their original class/type. 133 * Only the settings that exist on both Maps are updated, this avoid invalid 134 * settings and Class type injections from happening. 135 * 136 * @param originalSettings the original advanced/internal settings of a 137 * plugin or service. 138 * @param newSettings the new settings to apply. 139 * @return the originalSettings HashMap with the new values in place (you 140 * can use the reference passed as originalSettings instead if you want, 141 * they will allways be the same). 142 */ 143 public HashMap<String, Object> processAdvancedSettings(HashMap<String, Object> originalSettings, HashMap<String, String[]> newSettings) { 144 for (Map.Entry<String, Object> setting : originalSettings.entrySet()) { 145 String name = Utils.getHTMLElementIDFromString(setting.getKey()); // NOTE remmember that the setting name is "kinda encoded" (and not in the URLEncode way, that's handled automagically) 146 Object value = setting.getValue(); 147 148 if (newSettings.containsKey(name)) // if the setting is found on the request try to update its value (maintaining the same type ofc) 149 { 150 String[] newValue = newSettings.get(name); 151 152 if (value != null) { 153 // parse the value depending on its class 154 if (value.getClass().equals(Integer.class)) { 155 value = Integer.valueOf(newValue[0]); 156 } else if (value.getClass().equals(Float.class)) { 157 value = Float.valueOf(newValue[0]); 158 } else if (value.getClass().equals(Boolean.class)) { 159 value = Boolean.valueOf(Utils.parseCheckBoxValue(newValue[0])); 160 } /*else if (value.getClass().equals(ServerDirectoryPath.class)) 161 value = ServerDirectoryPath.fromHTTPParams((ServerDirectoryPath) value, newSettings, name);*/ 162 //else if (value instanceof GenericSetting) { 163 // value = ((GenericSetting) value).fromHTTPParams(newSettings, name); 164 // } 165 else // String or unrecognized class 166 { 167 value = newValue[0]; 168 } 169 170 setting.setValue(value); 171 } else // null is treated as String 172 { 173 value = newValue[0]; 174 175 setting.setValue(value); 176 } 177 178 } else // if the setting was not found check if it's a Boolean one, this is a FIX because browsers omit unchecked checkboxes on form action 179 { 180 if (value.getClass().equals(Boolean.class)) { 181 setting.setValue(false); 182 } 183 } 184 } 185 186 return originalSettings; // just for easier use 187 } 188 189 /** 190 * Performs a certain action to a service or plugin. 191 * 192 * @param action the action to perform. 193 * @param svcName the name of the service or plugin to perform the action 194 * at. 195 * @param initStart the init-start param value. 196 * @param port the set-port param value. 197 * @param advSettings a HashMap with all the advanced settings and their 198 * values. 199 * @return an int value indicating what was wrong with the call (see 200 * Services.RES_* for values/name pairs) 201 */ 202 @Deprecated 203 public int performAction(int action, String svcName, boolean initStart, int port, HashMap<String, String[]> advSettings) { 204 if ((svcName == null) || svcName.trim().isEmpty()) { 205 return RES_NO_SERVICE_NAME; 206 } 207 208 try { 209 switch (action) { 210 case SVC_START: 211 if (svcName.equalsIgnoreCase(webServerName)) { 212 svcs.startWebServer(); 213 return RES_OK; 214 } else { 215 if (svcName.equalsIgnoreCase(webServicesName)) { 216 217 svcs.startWebServices(); 218 return RES_OK; 219 } else { 220 if (svcName.equalsIgnoreCase(storageName)) { 221 svcs.startStorage(); 222 return RES_OK; 223 } else { 224 if (svcName.equalsIgnoreCase(queryRetrieveName)) { 225 svcs.startQueryRetrieve(); 226 return RES_OK; 227 } else { 228 //TODO: DELETED 229 /*for (String plug : plgs.getPluginsNames()) { 230 if (plug.equalsIgnoreCase(svcName)) { 231 svcs.startPlugin(svcName); 232 return RES_OK; 233 } 234 }*/ 235 236 return RES_INVALID_SERVICE_NAME; 237 } 238 } 239 } 240 } 241 242 case SVC_STOP: 243 if (svcName.equalsIgnoreCase(webServerName)) { 244 svcs.stopWebServer(); 245 return RES_OK; 246 } else { 247 if (svcName.equalsIgnoreCase(webServicesName)) { 248 249 svcs.stopWebServices(); 250 return RES_OK; 251 } else { 252 if (svcName.equalsIgnoreCase(storageName)) { 253 svcs.stopStorage(); 254 return RES_OK; 255 } else { 256 if (svcName.equalsIgnoreCase(queryRetrieveName)) { 257 svcs.stopQueryRetrieve(); 258 return RES_OK; 259 } else { 260 //TODO: DELETED 261 /*for (String plug : plgs.getPluginsNames()) { 262 if (svcName.equalsIgnoreCase(plug)) { 263 svcs.stopPlugin(svcName); 264 return RES_OK; 265 } 266 }*/ 267 268 return RES_INVALID_SERVICE_NAME; 269 } 270 } 271 } 272 } 273 274 case SVC_INIT_START: 275 if (svcName.equalsIgnoreCase(webServerName)) { 276 setWebServerStart(initStart); 277 return RES_OK; 278 } else { 279 if (svcName.equalsIgnoreCase(webServicesName)) { 280 281 setWebServicesStart(initStart); 282 return RES_OK; 283 } else { 284 if (svcName.equalsIgnoreCase(storageName)) { 285 setStorageStart(initStart); 286 return RES_OK; 287 } else { 288 if (svcName.equalsIgnoreCase(queryRetrieveName)) { 289 setQueryRetrieveStart(initStart); 290 return RES_OK; 291 } else { 292 //TODO: DELETED 293 /*for (String plug : plgs.getPluginsNames()) { 294 if (svcName.equalsIgnoreCase(plug)) { 295 cfgs.setAutoStartPlugin(svcName, initStart); 296 return RES_OK; 297 } 298 }*/ 299 300 return RES_INVALID_SERVICE_NAME; 301 } 302 } 303 } 304 } 305 306 case SVC_SET_PORT: { 307 if ((port < 0) || (port > 65535)) { 308 return RES_INVALID_ACTION_PARAMETER; 309 } 310 311 if (svcName.equalsIgnoreCase(webServerName)) { 312 setWebServerPort(port); 313 return RES_OK; 314 } else { 315 if (svcName.equalsIgnoreCase(webServicesName)) { 316 317 setWebServicesPort(port); 318 return RES_OK; 319 } else { 320 if (svcName.equalsIgnoreCase(storageName)) { 321 setStoragePort(port); 322 return RES_OK; 323 } else { 324 if (svcName.equalsIgnoreCase(queryRetrieveName)) { 325 setQueryRetrievePort(port); 326 return RES_OK; 327 } else { 328 if (svcName.equalsIgnoreCase(remoteGUIName)) { 329 setRemoteGUIPort(port); 330 return RES_OK; 331 } else { 332 // TODO for plugins 333 334 return RES_INVALID_SERVICE_NAME; 335 } 336 } 337 } 338 } 339 } 340 } 341 342 case SVC_SET_SETTINGS: 343 if (advSettings == null || advSettings.isEmpty()) { 344 return RES_INVALID_ACTION_PARAMETER; 345 } else { 346 if (svcName.equalsIgnoreCase(storageName)) { 347 HashMap<String, Object> settings = cfgs.getStorageSettings(); 348 349 processAdvancedSettings(settings, advSettings); 350 351 // try to apply the settings 352 if (cfgs.tryStorageSettings(settings)) { 353 cfgs.setStorageSettings(settings); 354 355 saveSettings(); 356 357 return RES_OK; 358 } else { 359 return RES_INVALID_ACTION_PARAMETER; 360 } 361 } else { 362 if (svcName.equalsIgnoreCase(queryRetrieveName)) { 363 HashMap<String, Object> settings = cfgs.getQueryRetrieveSettings(); 364 365 processAdvancedSettings(settings, advSettings); 366 367 // try to apply the settings 368 if (cfgs.tryQueryRetrieveSettings(settings)) { 369 cfgs.setQueryRetrieveSettings(settings); 370 371 saveSettings(); 372 373 return RES_OK; 374 } else { 375 return RES_INVALID_ACTION_PARAMETER; 376 } 377 } else { 378 if (svcName.equalsIgnoreCase(remoteGUIName)) { 379 HashMap<String, Object> settings = cfgs.getRGUISettings(); 380 381 processAdvancedSettings(settings, advSettings); 382 383 // try to apply the settings 384 if (cfgs.tryRGUISettings(settings)) { 385 cfgs.setRGUISettings(settings); 386 387 saveSettings(); 388 389 return RES_OK; 390 } else { 391 return RES_INVALID_ACTION_PARAMETER; 392 } 393 } else { 394 if (plgs.hasAdvancedSettings(svcName)) { 395 //TODO: DELETED 396 //HashMap<String, Object> settings = plgs.getAdvancedSettings(svcName); 397 398 //processAdvancedSettings(settings, advSettings); 399 400 401 // try to apply the settings 402 if (/*plgs.trySettings(svcName, settings)*/true) { 403 //plgs.setSettings(svcName, settings); 404 405 //plgs.saveSettings(); 406 407 return RES_OK; 408 } else { 409 return RES_INVALID_ACTION_PARAMETER; 410 } 411 } 412 413 return RES_INVALID_SERVICE_NAME; 414 } 415 } 416 } 417 } 418 419 case SVC_NO_ACTION: 420 default: 421 return RES_INVALID_ACTION; 422 } 423 } catch (IOException ex) { 424 return RES_WARNING; 425 } 426 } 427 428 /** 429 * Performs a certain action to a service or plugin, and save the settings 430 * if needed. 431 * 432 * @param request the request object. 433 * @return an int value indicating what was wrong with the call (see 434 * Services.RES_* for values/name pairs). 435 */ 436 public int performAction(HttpServletRequest request) throws UnsupportedEncodingException { 437 // set proper encoding on the request 438 request.setCharacterEncoding("UTF-8"); 439 440 // get the action to take 441 String action = request.getParameter(PARAM_ACTION); 442 443 // check if it is a valid action 444 if (action == null) { 445 return RES_NO_ACTION; 446 } 447 448 // get the name of the service/plugin to execute the action at 449 String svcName = request.getParameter(PARAM_SERVICE); 450 451 int portNumber = 0; 452 boolean initOnStart = false; 453 HashMap<String, String[]> advSettings = new HashMap<>(); 454 455 int act = SVC_NO_ACTION; 456 if (action.equalsIgnoreCase(ACTION_START)) { 457 act = SVC_START; 458 } else if (action.equalsIgnoreCase(ACTION_STOP)) { 459 act = SVC_STOP; 460 } else if (action.equalsIgnoreCase(ACTION_INIT_START)) { 461 initOnStart = Utils.parseCheckBoxValue(request.getParameter(PARAM_INIT_START)); 462 act = SVC_INIT_START; 463 } else if (action.equalsIgnoreCase(ACTION_SET_PORT)) { 464 String port = request.getParameter(PARAM_PORT); 465 466 if (port == null || port.trim().isEmpty()) { 467 return RES_INVALID_ACTION_PARAMETER; 468 } 469 470 portNumber = Integer.parseInt(port); 471 act = SVC_SET_PORT; 472 } else if (action.equalsIgnoreCase(ACTION_SET_ADVANCED_SETTINGS)) { 473 // get all the settings and their values 474 Enumeration<String> params = request.getParameterNames(); 475 while (params.hasMoreElements()) { 476 String name = params.nextElement(); 477 478 // ignore the main params (the ones that go us here) 479 if (name.equalsIgnoreCase(PARAM_ACTION) || name.equalsIgnoreCase(PARAM_SERVICE)) { 480 continue; 481 } 482 483 String[] value = request.getParameterValues(name); 484 485 advSettings.put(name, value); 486 } 487 488 act = SVC_SET_SETTINGS; 489 } else { 490 return RES_INVALID_ACTION; 491 } 492 493 // execute the action requested 494 int result = performAction(act, svcName, initOnStart, portNumber, advSettings); 495 496 // save the settings if needed 497 if ((result == RES_OK) && ((act == SVC_INIT_START) || (act == SVC_SET_PORT))) { 498 saveSettings(); 499 } 500 501 // return the performAction result 502 return result; 503 } 504 505 /** 506 * Processes a request from a servlet to perform an action on a service or 507 * plugin. 508 * 509 * @param request the servlet request object. 510 * @param response the servlet response object. 511 * @throws IOException if there was an error while attempting to perform the 512 * requested action. 513 */ 514 public void processServletRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { 515 // try to perform the action 516 int result = performAction(request); 517 518 // check the result and repond accordingly 519 switch (result) { 520 case RES_OK: 521 response.setStatus(HttpServletResponse.SC_OK); 522 break; 523 524 case RES_NO_ACTION: 525 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No action defined!"); 526 break; 527 528 case RES_INVALID_ACTION: 529 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid action!"); 530 break; 531 532 case RES_NO_SERVICE_NAME: 533 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "No service/plugin name defined!"); 534 break; 535 536 case RES_INVALID_SERVICE_NAME: 537 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid service/plugin name!"); 538 break; 539 540 case RES_WARNING: 541 default: 542 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unexpected action result!"); 543 break; 544 } 545 } 546 547 /** 548 * Processes a request from a webapp to perform an action on a service or 549 * plugin. 550 * 551 * @param request the webapp request object. 552 * @param response the webapp response object. 553 * @throws IOException if there was an error while attempting to perform the 554 * requested action. 555 * @return an int value that represents theresult of the operation performed 556 * (see Services.RES_* for values/name pairs). 557 */ 558 public int processWebappRequest(HttpServletRequest request, HttpServletResponse response) throws IOException { 559 // try to perform the action 560 int result = performAction(request); 561 562 // check the result and repond accordingly 563 switch (result) { 564 case RES_OK: 565 response.setStatus(HttpServletResponse.SC_OK); 566 break; 567 568 case RES_NO_ACTION: 569 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 570 break; 571 572 case RES_INVALID_ACTION: 573 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 574 break; 575 576 case RES_NO_SERVICE_NAME: 577 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 578 break; 579 580 case RES_INVALID_SERVICE_NAME: 581 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); 582 break; 583 584 case RES_WARNING: 585 default: 586 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 587 break; 588 } 589 590 return result; 591 } 592 593 /** 594 * Returns an HTML String containing the form element to perform some action 595 * an a plugin name by the brokerURL. 596 * 597 * @param brokerURL the URL where the form will post its data. 598 * @param action the action to take. 599 * @param name the name of the service or plugin where the action will be 600 * performed. 601 * @return an HTML String containing the form element to perform some action 602 * an a plugin name by the brokerURL. 603 */ 604 private String getHTMLActionForm(String brokerURL, String action, String name) { 605 String result = "<form action=\"" + brokerURL + "\" method=\"get\"><input type=\"hidden\" name=\"" + PARAM_ACTION + "\" value=\"" + action.toLowerCase() + "\" /><input type=\"hidden\" name=\"" + PARAM_SERVICE + "\" value=\"" + name + "\" />"; 606 607 String buttonStyle = "btn"; 608 if (action.equalsIgnoreCase("start")) { 609 buttonStyle += " btn-success"; 610 } 611 if (action.equalsIgnoreCase("stop")) { 612 buttonStyle += " btn-danger"; 613 } 614 615 result += "<input type=\"submit\" class=\"" + buttonStyle + "\" value=\"" + action + "\" />"; 616 617 // add a little warning for stopping the web server, making it unable to be used remotely again 618 /*if (name.equalsIgnoreCase(webServerName)) 619 { 620 result += "<div class=\"warning\"><span class=\"notice\">!</span></div>"; 621 }*/ 622 623 result += "</form>"; 624 625 return result; 626 } 627 628 /** 629 * Returns an HTML String containing the form element to change the start on 630 * init flag of a plugin name by the brokerURL. 631 * 632 * @param brokerURL the URL where the form will post its data. 633 * @param name the name of the service or plugin where the action will be 634 * performed. 635 * @param startInitially if the plugin or service is currently set to start 636 * initially or not. 637 * @param canBeDisabled if this plugin or service can be disabled. 638 * @return an HTML String containing the form element to change the start on 639 * init flag of a plugin name by the brokerURL. 640 */ 641 private String getHTMLStartOnInitForm(String brokerURL, String name, boolean startInitially, boolean canBeDisabled) { 642 String result = "<form action=\"" + brokerURL + "\" method=\"get\"><input type=\"hidden\" name=\"" + PARAM_ACTION + "\" value=\"" + ACTION_INIT_START + "\" /><input type=\"hidden\" name=\"" + PARAM_SERVICE + "\" value=\"" + name + "\" />"; 643 644 result += "<label for=\"" + PARAM_INIT_START + "-" + Utils.getHTMLElementIDFromString(name) + "\" class=\"checkbox inline\">"; 645 result += "<input type=\"checkbox\" id=\"" + PARAM_INIT_START + "-" + Utils.getHTMLElementIDFromString(name) + "\" name=\"" + PARAM_INIT_START + "\" " + (startInitially ? "checked=\"checked\"" : "") + " onclick=\"this.parent.submit();\" " + (canBeDisabled ? "" : "disabled=\"disabled\"") + " /> Auto Start"; 646 result += "</label>"; 647 result += "<input type=\"submit\" hidden=\"hidden\" />"; 648 649 // add a little warning for disabling the web server, making it unable to be used remotely again 650 /*if (name.equalsIgnoreCase(webServerName)) 651 { 652 result += "<div class=\"warning\"><span class=\"notice\">!</span></div>"; 653 }*/ 654 655 result += "</form>"; 656 657 return result; 658 } 659 660 /** 661 * Returns an HTML String containing the form element to change the port 662 * number of a plugin name by the brokerURL. 663 * 664 * @param brokerURL the URL where the form will post its data. 665 * @param name the name of the service or plugin where the action will be 666 * performed. 667 * @param port the current plugin or service port number. 668 * @return an HTML String containing the form element to change the port 669 * number of a plugin name by the brokerURL. 670 */ 671 private String getHTMLPortForm(String brokerURL, String name, int port) { 672 String result = "<form action=\"" + brokerURL + "\" method=\"get\"><input type=\"hidden\" name=\"" + PARAM_ACTION + "\" value=\"" + ACTION_SET_PORT + "\" /><input type=\"hidden\" name=\"" + PARAM_SERVICE + "\" value=\"" + name + "\" />"; 673 674 result += "<label for=\"" + PARAM_PORT + "-" + Utils.getHTMLElementIDFromString(name) + "\">"; 675 result += "Port: " + "<input id=\"" + PARAM_PORT + "-" + Utils.getHTMLElementIDFromString(name) + "\" type=\"number\" name=\"" + PARAM_PORT + "\" min=\"0\" max=\"65535\" maxlength=\"5\" size=\"5\" value=\"" + port + "\" class=\"input-small\" style=\"margin-right: 10px;\"/>"; 676 result += "<input type=\"submit\" class=\"btn\" value=\"Set Port\" class=\"btn\" />"; 677 result += "</label>"; 678 679 // add a little warning for stopping the web server, making it unable to be used remotely again 680 /*if (name.equalsIgnoreCase(webServerName)) 681 { 682 result += "<div class=\"warning\"><span class=\"notice\">!</span></div>"; 683 }*/ 684 685 result += "</form>"; 686 687 return result; 688 } 689 690 /** 691 * Returns an HTML String containing the form element to see and modify the 692 * advanced/internal options of a plugin or service name by the brokerURL. 693 * 694 * @param brokerURL the URL where the form will post its data. 695 * @param name the name of the service or plugin where the action will be 696 * performed. 697 * @return an HTML String containing the form element to see and modify the 698 * advanced/internal options of a plugin or service name by the brokerURL. 699 */ 700 @Deprecated 701 private String getHTMLAdvancedOptionForm(String brokerURL, String name) { 702 String result = "<form action=\"" + brokerURL + "\" method=\"get\"><input type=\"hidden\" name=\"" + PARAM_SERVICE + "\" value=\"" + name + "\" />"; 703 704 result += "<input type=\"submit\" class=\"btn\" value=\"Advanced Options\" class=\"btn btn-info\" />"; 705 706 result += "</form>"; 707 708 return result; 709 } 710 711 /** 712 * Returns a String containing the HTML code for a row to the HTML service 713 * management table, based o the parameters passed to it. 714 * 715 * @param isRunning if the target service is currently running. 716 * @param brokerURL the url of the service broker. 717 * @param name the name of the target service. 718 * @param canBeDisabled if the plugins or service can be disabled from 719 * starting/stoping. 720 * @param startInitially if the plugin or service is currently set to be 721 * start on server initialization. 722 * @param hasPort if the plugin or service has a port number that can be 723 * changed. 724 * @param port the current port number of the plugin or service. 725 * @param hasAdvancedOptions if the pugin or service has advanced (internal) 726 * options. 727 * @param advancedOptionsManagerURL the URL of the pugin or service advanced 728 * options manager. 729 * @return a String containing the HTML code for a row to the HTML service 730 * management table, based o the parameters passed to it. 731 */ 732 @Deprecated 733 private String getHTMLServiceManagementTableRow(boolean isRunning, String brokerURL, String name, boolean canBeStopped, boolean canBeDisabled, boolean startInitially, boolean hasPort, int port, boolean hasAdvancedOptions, String advancedOptionsManagerURL) { 734 String result = "<tr " + (name.equalsIgnoreCase(webServerName) ? "class=\"warning\"" : "") + ">"; // add a little warning for stopping the web server, making it unable to be used remotely again 735 736 result += "<td>" + escapeHtml4(name) + "</td>"; 737 if (isRunning) { 738 result += "<td class=\"running\">Running</td>"; 739 if (canBeStopped) { 740 result += "<td>" + getHTMLActionForm(brokerURL, "Stop", name) + "</td>"; 741 } else { 742 result += "<td></td>"; 743 } 744 } else { 745 result += "<td class=\"stopped\">Stopped</td>"; 746 if (canBeStopped) { 747 result += "<td>" + getHTMLActionForm(brokerURL, "Start", name) + "</td>"; 748 } else { 749 result += "<td>" + "<div class=\"error\"></div>" + getHTMLActionForm(brokerURL, "Start", name) + "</td>"; // add a little error notification, so that the admin can see that the plugin failed to start 750 } 751 } 752 result += "<td>" + getHTMLStartOnInitForm(brokerURL, name, startInitially, canBeDisabled) + "</td>"; 753 if (hasPort) { 754 result += "<td>" + getHTMLPortForm(brokerURL, name, port) + "</td>"; 755 } else { 756 result += "<td></td>"; 757 } 758 if (hasAdvancedOptions) { 759 result += "<td>" + getHTMLAdvancedOptionForm(advancedOptionsManagerURL, name) + "</td>"; 760 } else { 761 result += "<td></td>"; 762 } 763 764 result += "</tr>"; 765 766 return result; 767 } 768 769 /** 770 * Returns an HTML String containing the list of all plugins and services 771 * available, their status and action that can be taken. 772 * 773 * @param brokerURL the URL of the service manager page (where the form will 774 * post data to). 775 * @param advancedOptionsManagerURL the URL of the plugin/service 776 * advanced/internal options manager. 777 * @param id the ID of this HTML element, can be null if not needed. 778 * @return an HTML String containing the list of all plugins and services 779 * available, their status and action that can be taken. 780 */ 781 @Deprecated 782 public String getHTMLServiceManagementTable(String brokerURL, String advancedOptionsManagerURL, String id) { 783 String result = ""; 784 if ((id == null) || id.trim().isEmpty()) { 785 result += "<table class=\"table table-striped\">"; 786 } else { 787 result += "<table id=\"" + id + "\" class=\"table table-striped\">"; 788 } 789 result += "<thead>"; 790 result += "<tr>"; 791 result += "<th>Name</th>"; 792 result += "<th>Status</th>"; 793 result += "<th>Actions</th>"; 794 result += "<th>Start on Init</th>"; 795 result += "<th>Options</th>"; 796 result += "<th>Advanced Options</th>"; 797 result += "</tr>"; 798 result += "</thead>"; 799 result += "<tbody>"; 800 801 // list all the plugins 802 //TODO: DELETED 803 /*for (String plug : plgs.getPluginsNames()) { 804 result += getHTMLServiceManagementTableRow(plgs.isPluginRunning(plug), brokerURL, plug, true, true, cfgs.getAutoStartPlugin(plug), false, 0, plgs.hasAdvancedSettings(plug), advancedOptionsManagerURL); 805 }*/ 806 // list the storage service 807 result += getHTMLServiceManagementTableRow(svcs.storageIsRunning(), brokerURL, storageName, true, true, storageStart(), true, storagePort(), false, /*advancedOptionsManagerURL*/ null); 808 // list the query retrieve service 809 result += getHTMLServiceManagementTableRow(svcs.queryRetrieveIsRunning(), brokerURL, queryRetrieveName, true, true, queryRetrieveStart(), true, queryRetrievePort(), true, advancedOptionsManagerURL); 810 // list the web services 811 //result += getHTMLServiceManagementTableRow(false, brokerURL, webServicesName, false, false, false, true, webServicesPort(), false, null); 812 // list the web server 813 result += getHTMLServiceManagementTableRow(svcs.webServerIsRunning(), brokerURL, webServerName, true, true, webServerStart(), true, webServerPort(), false, null); 814 // list the RMI service 815 result += getHTMLServiceManagementTableRow(true, brokerURL, remoteGUIName, false, false, true, true, remoteGUIPort(), true, advancedOptionsManagerURL); // FIXME actually get if the RMI is running or not 816 817 result += "</tbody>"; 818 result += "</table>"; 819 820 return result; 821 } 822 823 /** 824 * Returns an HTML String containing the list of all plugins and services 825 * available, their status and action that can be taken. 826 * 827 * @param brokerURL the URL of the service manager page (where the form will 828 * post data to). 829 * @param advancedOptionsManagerURL the URL of the plugin/service 830 * advanced/internal options manager. 831 * @return an HTML String containing the list of all plugins and services 832 * available, their status and action that can be taken. 833 */ 834 @Deprecated 835 public String getHTMLServiceManagementTable(String brokerURL, String advancedOptionsManagerURL) { 836 return getHTMLServiceManagementTable(brokerURL, advancedOptionsManagerURL, null); 837 } 838 839 /** 840 * Return if the Storage service is started initially. 841 * 842 * @return if the Storage service is started initially. 843 */ 844 public boolean storageStart() { 845 return cfgs.isStorage(); 846 } 847 848 /** 849 * Return if the QueryRetrieve service is started initially. 850 * 851 * @return if the QueryRetrieve service is started initially. 852 */ 853 public boolean queryRetrieveStart() { 854 return cfgs.isQueryRetrive(); 855 } 856 857 /** 858 * Return if the WebServices service is started initially. 859 * 860 * @return if the WebServices service is started initially. 861 */ 862 public boolean webServicesStart() { 863 return cfgs.getWeb().isWebServices(); 864 } 865 866 /** 867 * Return if the WebServer service is started initially. 868 * 869 * @return if the WebServer service is started initially. 870 */ 871 public boolean webServerStart() { 872 return cfgs.getWeb().isWebServer(); 873 } 874 875 /** 876 * Sets if the Storage service is started initially. 877 * 878 * @param start if the Storage service is started initially. 879 */ 880 public void setStorageStart(boolean start) { 881 cfgs.setStorage(start); 882 } 883 884 /** 885 * Sets if the QueryRetrieve service is started initially. 886 * 887 * @param start if the QueryRetrieve service is started initially. 888 */ 889 public void setQueryRetrieveStart(boolean start) { 890 cfgs.setQueryRetrive(start); 891 } 892 893 /** 894 * Sets if the WebServices service is started initially. 895 * 896 * @param start if the WebServices service is started initially. 897 */ 898 public void setWebServicesStart(boolean start) { 899 cfgs.getWeb().setWebServices(start); 900 } 901 902 /** 903 * Sets if the WebServer service is started initially. 904 * 905 * @param start if the WebServer service is started initially. 906 */ 907 public void setWebServerStart(boolean start) { 908 cfgs.getWeb().setWebServer(start); 909 } 910 911 /** 912 * Returns the Storage service port. 913 * 914 * @return the Storage service port. 915 */ 916 public int storagePort() { 917 return cfgs.getStoragePort(); 918 } 919 920 /** 921 * Returns the QueryRetrieve service port. 922 * 923 * @return the QueryRetrieve service port. 924 */ 925 public int queryRetrievePort() { 926 return cfgs.getWlsPort(); 927 } 928 929 /** 930 * Returns the WebServices service port. 931 * 932 * @return the WebServices service port. 933 */ 934 public int webServicesPort() { 935 return cfgs.getWeb().getServicePort(); 936 } 937 938 /** 939 * Returns the WebServer service port. 940 * 941 * @return the WebServer service port. 942 */ 943 public int webServerPort() { 944 return cfgs.getWeb().getServerPort(); 945 } 946 947 /** 948 * Returns the RemoteGUI service port. 949 * 950 * @return the RemoteGUI service port. 951 */ 952 public int remoteGUIPort() { 953 return cfgs.getRemoteGUIPort(); 954 } 955 956 /** 957 * Returns the RemoteGUI service external IP. 958 * 959 * @return the RemoteGUI service external IP. 960 */ 961 public String remoteGUIExtIP() { 962 return cfgs.getRGUIExternalIP(); 963 } 964 965 /** 966 * Sets the Storage service port. 967 * 968 * @param port the Storage service port. 969 */ 970 public void setStoragePort(int port) { 971 cfgs.setStoragePort(port); 972 } 973 974 /** 975 * Sets the QueryRetrieve service port. 976 * 977 * @param port the QueryRetrieve service port. 978 */ 979 public void setQueryRetrievePort(int port) { 980 cfgs.setWlsPort(port); 981 } 982 983 /** 984 * Sets the WebServices service port. 985 * 986 * @param port the WebServices service port. 987 */ 988 public void setWebServicesPort(int port) { 989 cfgs.getWeb().setServicePort(port); 990 } 991 992 /** 993 * Sets the WebServer service port. 994 * 995 * @param port the WebServer service port. 996 */ 997 public void setWebServerPort(int port) { 998 cfgs.getWeb().setServerPort(port); 999 } 1000 1001 /** 1002 * Sets the RemoteGUI service port. 1003 * 1004 * @param port the RemoteGUI service port. 1005 */ 1006 public void setRemoteGUIPort(int port) { 1007 cfgs.setRemoteGUIPort(port); 1008 } 1009 1010 /** 1011 * Sets the RemoteGUI service external IP. 1012 * 1013 * @param extIP the RemoteGUI service external IP. 1014 */ 1015 public void setRemoteGUIExtIP(String extIP) { 1016 cfgs.setRGUIExternalIP(extIP); 1017 } 1018 1019 /** 1020 * Saves the settings for use between server inits. 1021 */ 1022 public void saveSettings() { 1023 1024 xmlSupport.printXML(); 1025 } 1026 1027 /** 1028 * For a request, returns the name of the service/plugin required. 1029 * 1030 * @param request the servlet request object. 1031 * @return the name of the service/plugin required. 1032 * @throws IOException 1033 */ 1034 public String getRequestServiceName(HttpServletRequest request) throws IOException { 1035 // set proper encoding on the request 1036 request.setCharacterEncoding("UTF-8"); 1037 1038 // get the name of the service/plugin 1039 return request.getParameter(PARAM_SERVICE); 1040 } 1041 1042 public String getHTMLSettingHelp(String fieldTitle, String help) { 1043 String result = ""; 1044 1045 // make sure that there is a valid help notice 1046 if (help == null) { 1047 return result; 1048 } 1049 help = help.trim(); 1050 if (help.isEmpty()) { 1051 return result; 1052 } 1053 1054 // replace the "\n" (#13/#10) with "\\n" so that JS can interpret that correctly instead of ending up with a new line on the document 1055 //help = help.replaceAll("\n", "\\\\n"); 1056 // also the "\t" ones 1057 //help = help.replaceAll("\t", "\\\\t"); 1058 1059 // add a button that will show the help (button because of touch interfaces, instead of popup for desktop) 1060 System.out.println("HELP: "+help); 1061 String msg = escapeHtml4(help.replaceAll("\n", "<br>")); 1062 result += buildInfoButton(fieldTitle, msg); 1063 System.out.println("MSG: "+msg); 1064 return result; 1065 } 1066 1067 private String buildInfoButton(String title, String msg){ 1068 StringBuilder builder = new StringBuilder(); 1069 1070 builder.append("<a "); 1071 //builder.append(id); 1072 builder.append(" data-original-title=\""); 1073 builder.append(title); 1074 builder.append("\" href=\"#\" class=\"btn btn-mini btn-info\" data-toggle=\"popover\" data-html=\"true\" data-content=\""); 1075 builder.append(msg); 1076 builder.append("\" onclick=\"return false;\">Info</a>\n"); 1077 1078 return builder.toString(); 1079 } 1080 1081 1082 /** 1083 * Returns a row for the advanced settings form. 1084 * 1085 * @param name the name of the setting. 1086 * @param value the type/value of the setting. 1087 * @param help s String containing a help notice for this setting, can be 1088 * null if not needed. 1089 * @return a String containing a HTML code to a row for the advanced 1090 * settings form. 1091 */ 1092 public String getHTMLAdvancedSettingsFormRow(String name, Object value, String help) { 1093 1094 String result = ""; 1095 1096 String id = Utils.getHTMLElementIDFromString(name); 1097 1098 result += "<tr>"; 1099 1100 result += "<td><label for=\"" + id + "\">" + escapeHtml4(name) + ":</label></td>"; 1101 result += "<td>" + Utils.getHTMLInputFromType(id, value) + getHTMLSettingHelp(escapeHtml4(name) , help) + "</td>"; // TODO add a button with help, like in the desktop application [getHelpForParam(pluginName, paramName) != null] 1102 1103 result += "</tr>"; 1104 1105 return result; 1106 } 1107 1108 /** 1109 * Based on the request, returns a String containing a form with all the 1110 * settings inputs boxes. These boxes are rendered/specified in accordance 1111 * with the each setting value type reported by the plugin/service. 1112 * 1113 * @param request the servlet request object. 1114 * @param brokerURL the URL of the broker that will apply the settings after 1115 * receiving this forms post. 1116 * @param elementID the ID of this HTML form, can be null. 1117 * @return a String containing the HTML structure for the form with all the 1118 * plugin advanced setting. 1119 */ 1120 public String getHTMLServiceAdvancedSettingsForm(HttpServletRequest request, String brokerURL, String elementID) throws IOException { 1121 String result = ""; 1122 1123 String name = getRequestServiceName(request); 1124 1125 // test if this is a embeded service and has advanced settings 1126 boolean isStorage = storageName.equalsIgnoreCase(name); 1127 boolean isQueryRetrieve = queryRetrieveName.equalsIgnoreCase(name); 1128 boolean isRemoteGUI = remoteGUIName.equalsIgnoreCase(name); 1129 boolean isEmbededService = isStorage || isQueryRetrieve || isRemoteGUI; 1130 1131 // if it's not a embeded service 1132 if (!isEmbededService) { 1133 // test if it's a plugin and has advanced settings 1134 if (!plgs.hasAdvancedSettings(name)) { 1135 result += "<h3>The required plugin/service is either invalid or has no advanced settings!</h3>"; 1136 return result; 1137 } 1138 } 1139 1140 if ((elementID == null) || elementID.trim().isEmpty()) { 1141 result += "<form "; 1142 } else { 1143 result += "<form id=\"" + elementID + "\" "; 1144 } 1145 result += "action=\"" + brokerURL + "\" method=\"get\">"; 1146 1147 result += "<input type=\"hidden\" name=\"" + PARAM_ACTION + "\" value=\"" + ACTION_SET_ADVANCED_SETTINGS + "\" />"; 1148 result += "<input type=\"hidden\" name=\"" + PARAM_SERVICE + "\" value=\"" + escapeHtml4(name) + "\" />"; 1149 1150 result += "<table class=\"table table-hover\"><tbody>"; 1151 1152 HashMap<String, Object> settings = null; 1153 HashMap<String, String> settingsHelp = null; 1154 if (!isEmbededService) // if it's a plugin 1155 { 1156 //TODO: DELETED 1157 //settings = plgs.getAdvancedSettings(name); 1158 settingsHelp = plgs.getAdvancedSettingsHelp(name); 1159 } else { 1160 if (isStorage) { 1161 settings = cfgs.getStorageSettings(); 1162 settingsHelp = cfgs.getStorageSettingsHelp(); 1163 } else if (isQueryRetrieve) { 1164 settings = cfgs.getQueryRetrieveSettings(); 1165 settingsHelp = cfgs.getQueryRetrieveSettingsHelp(); 1166 } else // Remote GUI 1167 { 1168 settings = cfgs.getRGUISettings(); 1169 settingsHelp = cfgs.getRGUISettingsHelp(); 1170 } 1171 } 1172 // just to avoid any unwanted exceptions, in case a plugin misbehaves 1173 if (settings == null) { 1174 settings = new HashMap<String, Object>(); 1175 } 1176 if (settingsHelp == null) { 1177 settingsHelp = new HashMap<String, String>(); 1178 } 1179 1180 // create a table row for each setting (includes name, value/type and help, if available) 1181 for (Map.Entry<String, Object> setting : settings.entrySet()) { 1182 String key = setting.getKey(); 1183 Object value = setting.getValue(); 1184 String help = settingsHelp.get(key); 1185 1186 result += getHTMLAdvancedSettingsFormRow(key, value, help); 1187 } 1188 1189 result += "</tbody></table><br />"; 1190 1191 result += "<input type=\"submit\" value=\"Apply Settings\" class=\"btn btn-primary\"/>"; 1192 result += "</form>"; 1193 1194 return result; 1195 } 1196}