1 36 37 package org.continuent.sequoia.controller.core; 38 39 import java.io.BufferedOutputStream ; 40 import java.io.BufferedReader ; 41 import java.io.BufferedWriter ; 42 import java.io.DataOutputStream ; 43 import java.io.File ; 44 import java.io.FileNotFoundException ; 45 import java.io.FileOutputStream ; 46 import java.io.FileReader ; 47 import java.io.FileWriter ; 48 import java.io.IOException ; 49 import java.io.InputStream ; 50 import java.net.URL ; 51 import java.net.URLDecoder ; 52 import java.text.SimpleDateFormat ; 53 import java.util.ArrayList ; 54 import java.util.Date ; 55 import java.util.Enumeration ; 56 import java.util.Hashtable ; 57 import java.util.Iterator ; 58 import java.util.List ; 59 import java.util.zip.ZipEntry ; 60 import java.util.zip.ZipFile ; 61 62 import javax.management.MalformedObjectNameException ; 63 import javax.management.Notification ; 64 import javax.management.NotificationBroadcasterSupport ; 65 66 import org.continuent.sequoia.common.exceptions.ControllerException; 67 import org.continuent.sequoia.common.exceptions.VirtualDatabaseException; 68 import org.continuent.sequoia.common.i18n.Translate; 69 import org.continuent.sequoia.common.jmx.JmxConstants; 70 import org.continuent.sequoia.common.jmx.notifications.SequoiaNotificationList; 71 import org.continuent.sequoia.common.log.LogManager; 72 import org.continuent.sequoia.common.log.Trace; 73 import org.continuent.sequoia.common.net.SSLConfiguration; 74 import org.continuent.sequoia.common.util.Constants; 75 import org.continuent.sequoia.common.xml.ControllerXmlTags; 76 import org.continuent.sequoia.common.xml.XmlComponent; 77 import org.continuent.sequoia.common.xml.XmlTools; 78 import org.continuent.sequoia.controller.core.shutdown.ControllerShutdownThread; 79 import org.continuent.sequoia.controller.jmx.RmiConnector; 80 import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase; 81 import org.continuent.sequoia.controller.xml.DatabasesParser; 82 83 93 public final class Controller implements XmlComponent 94 { 95 100 private String jdbcIpAddress; 101 102 private int jdbcPortNumber; 103 private int backlogSize; 104 private String name; 105 private boolean allowAdditionalDriver; 106 107 private RmiConnector rmiConnector; 108 private SSLConfiguration sslConfiguration = null; 109 110 111 private ControllerServerThread connectionThread; 112 113 114 static Trace logger = Trace 115 .getLogger("org.continuent.sequoia.controller.core.Controller"); 116 static Trace endUserLogger = Trace 117 .getLogger("org.continuent.sequoia.enduser"); 118 119 120 private Hashtable virtualDatabases; 121 122 123 private Hashtable configuration; 124 125 126 private ReportManager report; 127 128 private boolean isShuttingDown; 129 130 protected NotificationBroadcasterSupport notificationBroadcasterSupport; 131 132 protected int notificationSequence = 0; 133 134 135 136 146 public Controller(String name, String ipAddress, int port, int backlog, 147 boolean allowAdditionalDriver) 148 { 149 virtualDatabases = new Hashtable (); 150 setControllerName(name); 151 this.jdbcIpAddress = ipAddress; 152 this.jdbcPortNumber = port; 153 this.backlogSize = backlog; 154 this.allowAdditionalDriver = allowAdditionalDriver; 155 } 156 157 164 public void setNotificationBroadcasterSupport( 165 NotificationBroadcasterSupport notificationBroadcasterSupport) 166 { 167 this.notificationBroadcasterSupport = notificationBroadcasterSupport; 168 } 169 170 178 protected void sendJmxNotification(String type, String message) 179 { 180 try 181 { 182 notificationBroadcasterSupport.sendNotification(new Notification (type, 183 JmxConstants.getControllerObjectName(), notificationSequence++, 184 message)); 185 } 186 catch (MalformedObjectNameException e) 187 { 188 logger.warn("Unable to send JMX notification", e); 190 } 191 } 192 193 197 207 public void addVirtualDatabases(String xml, String vdbName, int autoEnable) 208 throws ControllerException 209 { 210 if (logger.isDebugEnabled()) 211 logger.debug(Translate.get("controller.add.virtualdatabase", vdbName)); 212 if (vdbName != null && this.hasVirtualDatabase(vdbName)) 213 { 214 throw new ControllerException(Translate.get( 215 "controller.add.virtualdatabase.already.used", vdbName)); 216 } 217 try 218 { 219 DatabasesParser parser = new DatabasesParser(this, vdbName, autoEnable); 220 parser.readXML(xml, true); 221 } 222 catch (Exception e) 223 { 224 String msg = Translate.get("controller.add.virtualdatabases.failed", e 225 .getMessage()); 226 logger.warn(msg, e); 227 throw new ControllerException(msg); 228 } 229 } 230 231 236 public void addVirtualDatabases(String xml) throws ControllerException 237 { 238 if (logger.isDebugEnabled()) 239 { 240 logger.debug(Translate.get("controller.loading.virtualdatabase")); 241 } 242 this.addVirtualDatabases(xml, null, ControllerConstants.AUTO_ENABLE_FALSE); 243 } 244 245 251 public void addVirtualDatabase(VirtualDatabase vdb) 252 throws ControllerException 253 { 254 this.addVirtualDatabase(vdb, ControllerConstants.AUTO_ENABLE_FALSE); 255 } 256 257 265 public synchronized void addVirtualDatabase(VirtualDatabase vdb, int autoLoad) 266 throws ControllerException 267 { 268 if (hasVirtualDatabase(vdb.getDatabaseName())) 270 { 271 String msg = Translate.get("controller.add.virtualdatabase.already.used", 272 vdb.getDatabaseName()); 273 logger.warn(msg); 274 throw new ControllerException(msg); 275 } 276 else 277 { 278 virtualDatabases.put(vdb.getDatabaseName(), vdb); 279 } 280 281 try 283 { 284 if (logger.isDebugEnabled()) 285 logger.debug(Translate.get("controller.database.autoenable", autoLoad)); 286 287 switch (autoLoad) 288 { 289 case ControllerConstants.AUTO_ENABLE_TRUE : 290 vdb.enableAllBackendsFromCheckpoint(); 291 break; 292 case ControllerConstants.AUTO_ENABLE_FALSE : 293 break; 294 default : 295 logger 296 .error("Unsupported autoEnabledBackends mode in controller configuration"); 297 break; 298 } 299 } 300 catch (VirtualDatabaseException e) 301 { 302 logger 303 .warn("Failed to automatically enable backends, manual resynchronization is probably needed"); 304 } 305 306 logger.info(Translate.get("controller.add.virtualdatabase", vdb 307 .getDatabaseName())); 308 endUserLogger.info(Translate.get("controller.add.virtualdatabase.success", 309 vdb.getDatabaseName())); 310 sendJmxNotification( 311 SequoiaNotificationList.CONTROLLER_VIRTUALDATABASE_ADDED, Translate 312 .get("notification.virtualdatabase.added", vdb.getDatabaseName())); 313 } 314 315 322 public VirtualDatabase getVirtualDatabase(String virtualDatabaseName) 323 { 324 return (VirtualDatabase) virtualDatabases.get(virtualDatabaseName); 325 } 326 327 330 public ArrayList getVirtualDatabaseNames() 331 { 332 ArrayList result = new ArrayList (); 333 for (Iterator iter = virtualDatabases.values().iterator(); iter.hasNext();) 334 result.add(((VirtualDatabase) iter.next()).getVirtualDatabaseName()); 335 return result; 336 } 337 338 343 public ArrayList getVirtualDatabases() 344 { 345 return new ArrayList (virtualDatabases.values()); 346 } 347 348 355 public boolean hasVirtualDatabase(String name) 356 { 357 return virtualDatabases.containsKey(name); 358 } 359 360 366 public String removeVirtualDatabase(String virtualname) 367 { 368 if (hasVirtualDatabase(virtualname)) 369 { 370 if (this.virtualDatabases.remove(virtualname) == null) 371 { 372 logger.warn("Unexpected missing virtual database named " + virtualname 373 + " while removing from virtual database list"); 374 } 375 376 sendJmxNotification( 378 SequoiaNotificationList.CONTROLLER_VIRTUALDATABASE_REMOVED, Translate 379 .get("notification.virtualdatabase.shutdown", virtualname)); 380 } 381 return Translate.get("controller.removeVirtualDatabase.success", 382 virtualname); 383 } 384 385 389 392 public void addDriver(byte[] bytes) throws Exception 393 { 394 File driversDirectory = null; 396 URL url = Controller.class 397 .getResource(ControllerConstants.SEQUOIA_DRIVER_JAR_FILE); 398 boolean error = false; 399 if (url != null) 400 { 401 driversDirectory = (new File (URLDecoder.decode(url.getFile()))) 402 .getParentFile(); 403 error = (driversDirectory == null) || !driversDirectory.exists(); 404 } 405 406 if (error) 407 { 408 String msg = Translate.get("controller.driver.dir.not.found", 409 driversDirectory.toString()); 410 logger.error(msg); 411 endUserLogger.error(Translate.get("controller.add.driver.failed", msg)); 412 throw new ControllerException(msg); 413 } 414 415 File temp = null; 417 try 418 { 419 temp = File.createTempFile("driver", "zip", driversDirectory); 420 FileOutputStream output = new FileOutputStream (temp); 421 output.write(bytes); 422 output.close(); 423 } 424 catch (IOException e) 425 { 426 String msg = Translate.get("controller.add.jar.write.failed", e); 427 logger.error(msg); 428 endUserLogger.error(Translate.get("controller.add.driver.failed", msg)); 429 throw new ControllerException(msg); 430 } 431 432 try 434 { 435 Enumeration entries; 436 ZipFile zipFile = new ZipFile (temp); 437 438 int lenght; 440 InputStream in; 441 BufferedOutputStream out; 442 byte[] buffer = new byte[1024]; 443 444 entries = zipFile.entries(); 445 while (entries.hasMoreElements()) 446 { 447 ZipEntry entry = (ZipEntry ) entries.nextElement(); 448 449 if (entry.isDirectory()) 450 { 451 if (logger.isDebugEnabled()) 453 logger.debug(Translate.get("controller.add.jar.extract.dir", entry 454 .getName())); 455 456 (new File (driversDirectory, entry.getName())).mkdir(); 457 continue; 458 } 459 460 if (logger.isDebugEnabled()) 462 logger.debug(Translate.get("controller.add.jar.extract.file", entry 463 .getName())); 464 465 in = zipFile.getInputStream(entry); 466 out = new BufferedOutputStream (new FileOutputStream (driversDirectory 467 + System.getProperty("file.separator") + entry.getName())); 468 while ((lenght = in.read(buffer)) >= 0) 469 out.write(buffer, 0, lenght); 470 471 in.close(); 472 out.close(); 473 } 474 475 zipFile.close(); 476 temp.delete(); 477 String msg = Translate.get("controller.add.driver.success", 478 driversDirectory.toString()); 479 logger.info(msg); 480 endUserLogger.info(msg); 481 } 482 catch (IOException e) 483 { 484 String msg = Translate.get("controller.driver.extract.failed", 485 new String []{temp.getCanonicalPath(), e.getMessage()}); 486 logger.error(msg); 487 endUserLogger.error(Translate.get("controller.add.driver.failed", msg)); 488 throw new ControllerException(msg); 489 } 490 } 491 492 497 public void endOfController(Exception fatal) 498 { 499 logger.fatal(Translate.get("fatal.error")); 500 if (report.isGenerateOnFatal()) 501 { 502 new ReportManager(this).generateAndWriteException(true, fatal); 503 logger.info(Translate.get("fatal.report.generated", report 504 .getReportLocation() 505 + File.separator + ControllerConstants.REPORT_FILE)); 506 } 507 Runtime.getRuntime().exit(1); 508 } 509 510 522 public String loadXmlConfiguration(String filename, String virtualName, 523 int autoLoad) throws Exception 524 { 525 FileReader fileReader = null; 526 try 527 { 528 filename = filename.trim(); 529 try 530 { 531 fileReader = new FileReader (filename); 532 } 533 catch (FileNotFoundException fnf) 534 { 535 return Translate.get("controller.file.not.found", filename); 536 } 537 538 if (logger.isDebugEnabled()) 539 logger.debug("Loading virtual database configuration " + filename); 540 BufferedReader in = new BufferedReader (fileReader); 542 StringBuffer xml = new StringBuffer (); 543 String line; 544 do 545 { 546 line = in.readLine(); 547 if (line != null) 548 xml.append(line); 549 } 550 while (line != null); 551 552 addVirtualDatabases(xml.toString(), virtualName, autoLoad); 554 return Translate.get("controller.file.send", filename); 555 } 556 catch (Exception e) 557 { 558 logger.error(Translate.get("controller.loadXml.failed", 559 ControllerConstants.PRODUCT_NAME, e), e); 560 throw new ControllerException(Translate.get("controller.loadXml.failed", 561 ControllerConstants.PRODUCT_NAME, e)); 562 } 563 finally 564 { 565 if (fileReader != null) 566 fileReader.close(); 567 } 568 } 569 570 574 577 public void refreshLogConfiguration() throws ControllerException 578 { 579 try 580 { 581 LogManager.configure(URLDecoder.decode(this.getClass().getResource( 582 ControllerConstants.LOG4J_RESOURCE).getFile())); 583 if (logger.isDebugEnabled()) 584 logger.info(Translate.get("controller.refresh.log.success")); 585 } 586 catch (Exception e) 587 { 588 throw new ControllerException(Translate 589 .get("controller.logconfigfile.not.found")); 590 } 591 } 592 593 599 public String saveConfiguration() 600 { 601 String msg = Translate.get("controller.save.configuration.failed"); 602 try 603 { 604 String configurationFile = ControllerConstants 605 .getSaveFile(new SimpleDateFormat ("yyyy-MM-dd-HH-mm") 606 .format(new Date ())); 607 DataOutputStream dos = new DataOutputStream (new BufferedOutputStream ( 608 new FileOutputStream (configurationFile))); 609 StringBuffer xml = new StringBuffer (); 610 xml.append(XmlTools.prettyXml(getXmlVirtualDatabases())); 611 String prettyXml = xml.toString(); 612 prettyXml = XmlTools.insertDoctype(prettyXml, 615 ControllerConstants.VIRTUAL_DATABASE_DOCTYPE); 616 dos.write(prettyXml.getBytes()); 617 dos.close(); 618 msg = Translate.get("controller.save.configuration", configurationFile); 619 } 620 catch (Exception e) 621 { 622 msg = Translate.get("controller.save.configuration.failed", e); 623 logger.error(msg); 624 } 625 return msg; 626 } 627 628 631 public void updateLogConfigurationFile(String newConfiguration) 632 throws IOException , ControllerException 633 { 634 File logFile = new File (URLDecoder.decode(getClass().getResource( 635 ControllerConstants.LOG4J_RESOURCE).getFile())); 636 BufferedWriter writer = new BufferedWriter (new FileWriter (logFile)); 637 writer.write(newConfiguration); 638 writer.flush(); 639 writer.close(); 640 refreshLogConfiguration(); 641 } 642 643 647 650 public String viewLogConfigurationFile() throws IOException 651 { 652 File logFile = new File (URLDecoder.decode(getClass().getResource( 653 ControllerConstants.LOG4J_RESOURCE).getFile())); 654 BufferedReader reader = new BufferedReader (new FileReader (logFile)); 655 StringBuffer buffer = new StringBuffer (); 656 String line; 657 while ((line = reader.readLine()) != null) 658 buffer.append(line + System.getProperty("line.separator")); 659 reader.close(); 660 return buffer.toString(); 661 } 662 663 667 670 public boolean isShuttingDown() 671 { 672 return isShuttingDown; 673 } 674 675 678 public void shutdown() throws ControllerException 679 { 680 if (virtualDatabases.size() != 0) 681 { 682 throw new ControllerException(Translate.get( 683 "controller.shutdown.error.existing.virtualdatabases", 684 getControllerName())); 685 } 686 687 ControllerShutdownThread shutdownThread = null; 688 synchronized (this) 689 { 690 if (isShuttingDown()) 691 { 692 logger.info(Translate.get("controller.already.shutting.down", this 693 .getControllerName())); 694 return; 695 } 696 697 isShuttingDown = true; 698 shutdownThread = new ControllerShutdownThread(this); 699 logger.info(Translate 700 .get("controller.shutdown", this.getControllerName())); 701 } 702 703 Thread thread = new Thread (shutdownThread.getShutdownGroup(), 704 shutdownThread, "Controller Shutdown Thread"); 705 thread.start(); 706 707 try 708 { 709 logger.info("Waiting for controller shutdown"); 710 thread.join(); 711 logger.info(Translate.get("controller.shutdown.completed", this 712 .getControllerName())); 713 } 714 catch (InterruptedException e) 715 { 716 e.printStackTrace(); 717 } 718 } 719 720 733 public static void main(String [] args) throws Exception 734 { 735 System.setProperty("javax.management.builder.initial", 736 org.continuent.sequoia.controller.jmx.MBeanServerBuilder.class 737 .getName()); 738 739 if (ControllerConstants.CONTROLLER_FACTORY == null) 740 { 741 System.err 742 .println("Impossible to start Controller with an invalid controller.properties file."); 743 System.exit(1); 744 } 745 746 ControllerConfiguration conf = new ControllerConfiguration(args); 749 750 logger.info(getVersion()); 751 752 Controller controller = conf.getController(); 753 if (controller != null) 754 controller.launch(); 755 else 756 { 757 endUserLogger.error(Translate.get("controller.configure.failed")); 758 throw new Exception (Translate.get("controller.configure.failed")); 759 } 760 } 761 762 766 public void launch() 767 { 768 connectionThread = new ControllerServerThread(this); 769 connectionThread.start(); 770 771 SimpleDateFormat formatter = new SimpleDateFormat ( 772 "yyyy.MM.dd ww 'at' hh:mm:ss a zzz"); 773 Date day = new Date (); 774 String date = formatter.format(day); 775 logger.info(Translate.get("controller.date", date)); 776 logger.info(Translate.get("controller.ready", getControllerName())); 777 endUserLogger.info(Translate.get("controller.ready", getControllerName())); 778 } 779 780 784 789 public boolean allowAdditionalDriver() 790 { 791 return allowAdditionalDriver; 792 } 793 794 797 public int getBacklogSize() 798 { 799 return backlogSize; 800 } 801 802 805 public void setBacklogSize(int size) 806 { 807 backlogSize = size; 808 } 809 810 815 public Hashtable getConfiguration() 816 { 817 return configuration; 818 } 819 820 825 public void setConfiguration(Hashtable configuration) 826 { 827 this.configuration = configuration; 828 } 829 830 835 public ControllerServerThread getConnectionThread() 836 { 837 return connectionThread; 838 } 839 840 845 public String getControllerName() 846 { 847 return name; 848 } 849 850 855 public void setControllerName(String name) 856 { 857 if (name == null) 858 name = jdbcIpAddress + ":" + jdbcPortNumber; 859 this.name = name; 860 } 861 862 867 public String getIPAddress() 868 { 869 return jdbcIpAddress; 870 } 871 872 877 public void setIPAddress(String ipAddress) 878 { 879 this.jdbcIpAddress = ipAddress; 880 } 881 882 887 public int getJdbcPortNumber() 888 { 889 return jdbcPortNumber; 890 } 891 892 897 public void setJdbcPortNumber(int port) 898 { 899 jdbcPortNumber = port; 900 } 901 902 907 public String getJmxName() 908 { 909 if (rmiConnector != null) 910 return rmiConnector.getHostName() + ":" + rmiConnector.getPort(); 911 else 912 return getControllerName(); 913 } 914 915 920 public ReportManager getReport() 921 { 922 return report; 923 } 924 925 930 public void setReport(ReportManager report) 931 { 932 this.report = report; 933 } 934 935 940 public RmiConnector getRmiConnector() 941 { 942 return rmiConnector; 943 } 944 945 950 public void setRmiConnector(RmiConnector rmiConnector) 951 { 952 this.rmiConnector = rmiConnector; 953 } 954 955 960 public SSLConfiguration getSslConfiguration() 961 { 962 return sslConfiguration; 963 } 964 965 970 public void setSslConfiguration(SSLConfiguration sslConfiguration) 971 { 972 this.sslConfiguration = sslConfiguration; 973 } 974 975 980 public static String getVersion() 981 { 982 return Translate.get("controller.info", ControllerConstants.PRODUCT_NAME, 983 Constants.VERSION); 984 } 985 986 989 public String getVersionNumber() 990 { 991 return Constants.VERSION; 992 } 993 994 997 public String getXml() 998 { 999 try 1000 { 1001 String prettyXml = XmlTools.prettyXml(getXmlController()); 1002 return XmlTools.insertDoctype(prettyXml, 1003 ControllerConstants.CONTROLLER_DOCTYPE); 1004 } 1005 catch (Exception e) 1006 { 1007 logger.error(Translate.get("controller.xml.transformation.failed", e)); 1008 return e.getMessage(); 1009 } 1010 } 1011 1012 1018 public String getXmlController() 1019 { 1020 StringBuffer info = new StringBuffer (); 1021 info.append("<" + ControllerConstants.CONTROLLER_XML_ROOT_ELEMENT + ">"); 1022 info.append("<" + ControllerXmlTags.ELT_CONTROLLER + " " 1023 + ControllerXmlTags.ATT_CONTROLLER_NAME + "=\"" + getControllerName() 1024 + "\" " + ControllerXmlTags.ATT_CONTROLLER_IP + "=\"" + getIPAddress() 1025 + "\" " + ControllerXmlTags.ATT_CONTROLLER_PORT + "=\"" 1026 + getJdbcPortNumber() + "\" " 1027 + ControllerXmlTags.ATT_ALLOW_ADDITIONAL_DRIVER + "=\"" 1028 + allowAdditionalDriver() + "\">"); 1029 1030 info.append("<" + ControllerXmlTags.ELT_JMX + " " 1032 + ControllerXmlTags.ATT_JMX_ADAPTOR_IP + "=\"" 1033 + rmiConnector.getHostName() + "\" " 1034 + ControllerXmlTags.ATT_JMX_ADAPTOR_PORT + "=\"" 1035 + rmiConnector.getPort() + "\" "); 1036 if (configuration.containsKey(ControllerXmlTags.ATT_JMX_CONNECTOR_USERNAME)) 1037 { 1038 info.append(ControllerXmlTags.ATT_JMX_CONNECTOR_USERNAME + "=\"" 1039 + configuration.get(ControllerXmlTags.ATT_JMX_CONNECTOR_USERNAME) 1040 + "\" " + ControllerXmlTags.ATT_JMX_CONNECTOR_PASSWORD + "=\"" 1041 + configuration.get(ControllerXmlTags.ATT_JMX_CONNECTOR_PASSWORD) 1042 + "\" "); 1043 } 1044 info.append(">"); 1045 if (rmiConnector.getSslConfig() != null) info.append(rmiConnector.getSslConfig().getXml()); 1047 info.append("</" + ControllerXmlTags.ELT_JMX + ">"); 1048 1049 if (sslConfiguration != null) 1051 { 1052 info.append(sslConfiguration.getXml()); 1053 } 1054 1055 if (report.isReportEnabled()) 1057 { 1058 info.append("<" + ControllerXmlTags.ELT_REPORT + " " 1059 + ControllerXmlTags.ATT_REPORT_ENABLE_FILE_LOGGING + "=\"" 1060 + report.isEnableFileLogging() + "\" " 1061 + ControllerXmlTags.ATT_REPORT_HIDE_SENSITIVE_DATA + "=\"" 1062 + report.isHideSensitiveData() + "\" " 1063 + ControllerXmlTags.ATT_REPORT_GENERATE_ON_FATAL + "=\"" 1064 + report.isGenerateOnFatal() + "\" " 1065 + ControllerXmlTags.ATT_REPORT_GENERATE_ON_SHUTDOWN + "=\"" 1066 + report.isGenerateOnShutdown() + "\" " 1067 + ControllerXmlTags.ATT_REPORT_REPORT_LOCATION + "=\"" 1068 + report.getReportLocation() + "\" />"); 1069 } 1070 1071 info.append("</" + ControllerXmlTags.ELT_CONTROLLER + ">"); 1072 info.append("</" + ControllerConstants.CONTROLLER_XML_ROOT_ELEMENT + ">"); 1073 return info.toString(); 1074 } 1075 1076 1081 public String getXmlVirtualDatabases() 1082 { 1083 try 1084 { 1085 StringBuffer info = new StringBuffer (); 1086 info.append(XmlComponent.XML_VERSION); 1087 info.append("\n"); 1088 info.append("<" + ControllerConstants.VIRTUAL_DATABASE_XML_ROOT_ELEMENT 1089 + ">"); 1090 List vdbs = this.getVirtualDatabases(); 1091 for (int i = 0; i < vdbs.size(); i++) 1092 { 1093 info.append(((XmlComponent) vdbs.get(i)).getXml()); 1094 } 1095 info.append("</" + ControllerConstants.VIRTUAL_DATABASE_XML_ROOT_ELEMENT 1096 + ">"); 1097 return info.toString(); 1098 } 1099 catch (Exception e) 1100 { 1101 logger.error(e.getMessage(), e); 1102 return e.getMessage(); 1103 } 1104 } 1105 1106} | Popular Tags |