Source Code Cross Referenced for Controller.java in  » Database-JDBC-Connection-Pool » sequoia-2.10.9 » org » continuent » sequoia » controller » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » sequoia 2.10.9 » org.continuent.sequoia.controller.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Sequoia: Database clustering technology.
0003:         * Copyright (C) 2002-2004 French National Institute For Research In Computer
0004:         * Science And Control (INRIA).
0005:         * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
0006:         * Contact: sequoia@continuent.org
0007:         * 
0008:         * Licensed under the Apache License, Version 2.0 (the "License");
0009:         * you may not use this file except in compliance with the License.
0010:         * You may obtain a copy of the License at
0011:         * 
0012:         * http://www.apache.org/licenses/LICENSE-2.0
0013:         * 
0014:         * Unless required by applicable law or agreed to in writing, software
0015:         * distributed under the License is distributed on an "AS IS" BASIS,
0016:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:         * See the License for the specific language governing permissions and
0018:         * limitations under the License. 
0019:         *
0020:         * Free Software Foundation; either version 2.1 of the License, or any later
0021:         * version.
0022:         * 
0023:         * This library is distributed in the hope that it will be useful, but WITHOUT
0024:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0025:         * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General public final License
0026:         * for more details.
0027:         * 
0028:         * You should have received a copy of the GNU Lesser General public final License
0029:         * along with this library; if not, write to the Free Software Foundation,
0030:         * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
0031:         *
0032:         * Initial developer(s): Emmanuel Cecchet. 
0033:         * Contributor(s): Mathieu Peltier, Nicolas Modrzyk.
0034:         */package org.continuent.sequoia.controller.core;
0035:
0036:        import java.io.BufferedOutputStream;
0037:        import java.io.BufferedReader;
0038:        import java.io.BufferedWriter;
0039:        import java.io.DataOutputStream;
0040:        import java.io.File;
0041:        import java.io.FileNotFoundException;
0042:        import java.io.FileOutputStream;
0043:        import java.io.FileReader;
0044:        import java.io.FileWriter;
0045:        import java.io.IOException;
0046:        import java.io.InputStream;
0047:        import java.net.URL;
0048:        import java.net.URLDecoder;
0049:        import java.text.SimpleDateFormat;
0050:        import java.util.ArrayList;
0051:        import java.util.Date;
0052:        import java.util.Enumeration;
0053:        import java.util.Hashtable;
0054:        import java.util.Iterator;
0055:        import java.util.List;
0056:        import java.util.Locale;
0057:        import java.util.zip.ZipEntry;
0058:        import java.util.zip.ZipFile;
0059:
0060:        import javax.management.MalformedObjectNameException;
0061:        import javax.management.Notification;
0062:        import javax.management.NotificationBroadcasterSupport;
0063:
0064:        import org.continuent.sequoia.common.exceptions.ControllerException;
0065:        import org.continuent.sequoia.common.exceptions.VirtualDatabaseException;
0066:        import org.continuent.sequoia.common.i18n.Translate;
0067:        import org.continuent.sequoia.common.jmx.JmxConstants;
0068:        import org.continuent.sequoia.common.jmx.notifications.SequoiaNotificationList;
0069:        import org.continuent.sequoia.common.log.LogManager;
0070:        import org.continuent.sequoia.common.log.Trace;
0071:        import org.continuent.sequoia.common.util.Constants;
0072:        import org.continuent.sequoia.common.xml.ControllerXmlTags;
0073:        import org.continuent.sequoia.common.xml.XmlComponent;
0074:        import org.continuent.sequoia.common.xml.XmlTools;
0075:        import org.continuent.sequoia.controller.core.security.ControllerSecurityManager;
0076:        import org.continuent.sequoia.controller.core.shutdown.ControllerShutdownThread;
0077:        import org.continuent.sequoia.controller.jmx.MBeanServerManager;
0078:        import org.continuent.sequoia.controller.jmx.RmiConnector;
0079:        import org.continuent.sequoia.controller.virtualdatabase.VirtualDatabase;
0080:        import org.continuent.sequoia.controller.xml.DatabasesParser;
0081:
0082:        /**
0083:         * The Sequoia controller main class. It loads its configuration file and wait
0084:         * for virtual database to be loaded.
0085:         * 
0086:         * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
0087:         * @author <a href="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
0088:         * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
0089:         * @author <a href="mailto:duncan@mightybot.com">Duncan Smith </a>
0090:         * @version 1.0
0091:         */
0092:        public final class Controller implements  XmlComponent {
0093:
0094:            /** Sequoia controller port number listening for driver connections */
0095:            private int portNumber;
0096:            private int backlogSize;
0097:
0098:            /**
0099:             * The IP address to bind the controller to. Useful for machines that contain
0100:             * multiple network interface cards and wish to bind to a specific card.
0101:             * Default evaluates to localhost IP address (127.0.0.1).
0102:             */
0103:            private String ipAddress;
0104:
0105:            /** Thread that listens for driver connections */
0106:            private ControllerServerThread connectionThread;
0107:
0108:            /** Logger instances. */
0109:            static Trace logger = Trace
0110:                    .getLogger("org.continuent.sequoia.controller.core.Controller");
0111:            static Trace endUserLogger = Trace
0112:                    .getLogger("org.continuent.sequoia.enduser");
0113:
0114:            /** Hashtable of <code>VirtualDatabase</code> objects. */
0115:            private Hashtable virtualDatabases;
0116:
0117:            /** Hashtable of options */
0118:            private Hashtable configuration;
0119:
0120:            /** Security Manager */
0121:            private ControllerSecurityManager security;
0122:
0123:            /** Report Manager */
0124:            private ReportManager report;
0125:
0126:            private boolean isShuttingDown;
0127:
0128:            protected NotificationBroadcasterSupport notificationBroadcasterSupport;
0129:
0130:            protected int notificationSequence = 0;
0131:
0132:            /* Constructor(s) */
0133:
0134:            /**
0135:             * Creates a new <code>Controller</code> instance.
0136:             * 
0137:             * @param ipAddress bind the controller to this ipAddress
0138:             * @param port bind the controller to listen to this port
0139:             * @param backlog backlog connection size
0140:             */
0141:            public Controller(String ipAddress, int port, int backlog) {
0142:                virtualDatabases = new Hashtable();
0143:                this .ipAddress = ipAddress;
0144:                this .portNumber = port;
0145:                this .backlogSize = backlog;
0146:            }
0147:
0148:            /**
0149:             * Sets the NotificationBroadcasterSupport associated with the MBean managing
0150:             * this controller.
0151:             * 
0152:             * @param notificationBroadcasterSupport the notificationBroadcasterSupport
0153:             *          associated with the mbean managing this controller
0154:             */
0155:            public void setNotificationBroadcasterSupport(
0156:                    NotificationBroadcasterSupport notificationBroadcasterSupport) {
0157:                this .notificationBroadcasterSupport = notificationBroadcasterSupport;
0158:            }
0159:
0160:            /**
0161:             * Sends a JMX Notification on behalf of the MBean associated with this
0162:             * controller
0163:             * 
0164:             * @param type type of the JMX notification
0165:             * @param message message associated with the notification
0166:             * @see SequoiaNotificationList
0167:             */
0168:            protected void sendJmxNotification(String type, String message) {
0169:                if (!MBeanServerManager.isJmxEnabled()) {
0170:                    // do not send jmx notification if jmx is not enabled
0171:                    return;
0172:                }
0173:                try {
0174:                    notificationBroadcasterSupport
0175:                            .sendNotification(new Notification(type,
0176:                                    JmxConstants.getControllerObjectName(),
0177:                                    notificationSequence++, message));
0178:                } catch (MalformedObjectNameException e) {
0179:                    // unable to get a correct controller object name: do nothing
0180:                    logger.warn("Unable to send JMX notification", e);
0181:                }
0182:            }
0183:
0184:            //
0185:            // Virtual databases management
0186:            //
0187:
0188:            /**
0189:             * Adds virtual databases contained in the XML document given as a String. If
0190:             * a virtual database name is provided, only this database is loaded with the
0191:             * provided autoLoad and checkpoint information.
0192:             * 
0193:             * @param xml XML configuration file content
0194:             * @param vdbName optional virtual database name to autoload
0195:             * @param autoEnable autoenable backend mode for virtual database (or init)
0196:             * @param checkpoint checkpoint name if autoEnable is set to force
0197:             * @throws ControllerException if an error occurs
0198:             */
0199:            public void addVirtualDatabases(String xml, String vdbName,
0200:                    int autoEnable, String checkpoint)
0201:                    throws ControllerException {
0202:                if (logger.isDebugEnabled())
0203:                    logger.debug(Translate.get(
0204:                            "controller.add.virtualdatabase", vdbName));
0205:                if (vdbName != null && this .hasVirtualDatabase(vdbName)) {
0206:                    throw new ControllerException(Translate.get(
0207:                            "controller.add.virtualdatabase.already.used",
0208:                            vdbName));
0209:                }
0210:                try {
0211:                    DatabasesParser parser = new DatabasesParser(this , vdbName,
0212:                            autoEnable, checkpoint);
0213:                    parser.readXML(xml, true);
0214:                } catch (Exception e) {
0215:                    String msg = Translate.get(
0216:                            "controller.add.virtualdatabases.failed", e
0217:                                    .getMessage());
0218:                    logger.warn(msg, e);
0219:                    throw new ControllerException(msg);
0220:                }
0221:            }
0222:
0223:            /**
0224:             * Register a VirtualDatabase with default options
0225:             * 
0226:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#addVirtualDatabases(String)
0227:             */
0228:            public void addVirtualDatabases(String xml)
0229:                    throws ControllerException {
0230:                if (logger.isDebugEnabled()) {
0231:                    logger.debug(Translate
0232:                            .get("controller.loading.virtualdatabase"));
0233:                }
0234:                this .addVirtualDatabases(xml, null,
0235:                        ControllerConstants.AUTO_ENABLE_FALSE, null);
0236:            }
0237:
0238:            /**
0239:             * Registers a new <code>VirtualDatabase</code> in this controller.
0240:             * 
0241:             * @param vdb the <code>VirtualDatabase</code> to register
0242:             * @throws ControllerException if an error occurs
0243:             */
0244:            public void addVirtualDatabase(VirtualDatabase vdb)
0245:                    throws ControllerException {
0246:                this .addVirtualDatabase(vdb,
0247:                        ControllerConstants.AUTO_ENABLE_FALSE, null);
0248:            }
0249:
0250:            /**
0251:             * Add the virtual database with the specified options
0252:             * 
0253:             * @param vdb the <code>VirtualDatabase</code> object to add
0254:             * @param autoLoad specified if backends should be enabled
0255:             * @param checkPoint specified the checkPoint to recover from, leave null if
0256:             *          no recovery speficied
0257:             * @throws ControllerException if database already exists on the specified
0258:             *           <code>Controller</code> object
0259:             */
0260:            public synchronized void addVirtualDatabase(VirtualDatabase vdb,
0261:                    int autoLoad, String checkPoint) throws ControllerException {
0262:                // Add the database or retrieve it if it already exists
0263:                if (hasVirtualDatabase(vdb.getDatabaseName())) {
0264:                    String msg = Translate.get(
0265:                            "controller.add.virtualdatabase.already.used", vdb
0266:                                    .getDatabaseName());
0267:                    logger.warn(msg);
0268:                    throw new ControllerException(msg);
0269:                } else {
0270:                    virtualDatabases.put(vdb.getDatabaseName(), vdb);
0271:                }
0272:
0273:                // Enable backends with the proper states
0274:                try {
0275:                    if (logger.isDebugEnabled())
0276:                        logger.debug(Translate.get(
0277:                                "controller.database.autoenable", autoLoad));
0278:
0279:                    switch (autoLoad) {
0280:                    case ControllerConstants.AUTO_ENABLE_TRUE:
0281:                        vdb.enableAllBackendsFromCheckpoint();
0282:                        break;
0283:                    case ControllerConstants.AUTO_ENABLE_FALSE:
0284:                        break;
0285:                    case ControllerConstants.AUTO_ENABLE_FORCE:
0286:                        logger
0287:                                .warn("Backends enabled in force mode from checkpoint "
0288:                                        + checkPoint);
0289:                        vdb.forceEnableAllBackendsFromCheckpoint(checkPoint);
0290:                        break;
0291:                    case ControllerConstants.AUTO_ENABLE_INIT:
0292:                    case ControllerConstants.AUTO_ENABLE_FORCE_LOAD:
0293:                        break;
0294:                    default:
0295:                        logger
0296:                                .error("Unsupported autoEnabledBackends mode in controller configuration");
0297:                        break;
0298:                    }
0299:                } catch (VirtualDatabaseException e) {
0300:                    logger
0301:                            .warn("Failed to automatically enable backends, manual resynchronization is probably needed");
0302:                }
0303:
0304:                logger.info(Translate.get("controller.add.virtualdatabase", vdb
0305:                        .getDatabaseName()));
0306:                endUserLogger.info(Translate.get(
0307:                        "controller.add.virtualdatabase.success", vdb
0308:                                .getDatabaseName()));
0309:                sendJmxNotification(
0310:                        SequoiaNotificationList.CONTROLLER_VIRTUALDATABASE_ADDED,
0311:                        Translate.get("notification.virtualdatabase.added", vdb
0312:                                .getDatabaseName()));
0313:            }
0314:
0315:            /**
0316:             * Gets the <code>VirtualDatabase</code> object corresponding to a virtual
0317:             * database name.
0318:             * 
0319:             * @param virtualDatabaseName the virtual database name
0320:             * @return a <code>VirtualDatabase</code> object or null if not found
0321:             */
0322:            public VirtualDatabase getVirtualDatabase(String virtualDatabaseName) {
0323:                return (VirtualDatabase) virtualDatabases
0324:                        .get(virtualDatabaseName);
0325:            }
0326:
0327:            /**
0328:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#getVirtualDatabaseNames()
0329:             */
0330:            public ArrayList getVirtualDatabaseNames() {
0331:                ArrayList result = new ArrayList();
0332:                for (Iterator iter = virtualDatabases.values().iterator(); iter
0333:                        .hasNext();)
0334:                    result.add(((VirtualDatabase) iter.next())
0335:                            .getVirtualDatabaseName());
0336:                return result;
0337:            }
0338:
0339:            /**
0340:             * Returns information about the available virtual databases.
0341:             * 
0342:             * @return ArrayList of information about virtual databases.
0343:             */
0344:            public ArrayList getVirtualDatabases() {
0345:                return new ArrayList(virtualDatabases.values());
0346:            }
0347:
0348:            /**
0349:             * Tests if a <code>VirtualDatabase</code> of a given name exists in this
0350:             * controller.
0351:             * 
0352:             * @param name the virtual database name
0353:             * @return <code>true</code> if the virtual database exists
0354:             */
0355:            public boolean hasVirtualDatabase(String name) {
0356:                return virtualDatabases.containsKey(name);
0357:            }
0358:
0359:            /**
0360:             * Removes the virtual database with the given name (if any)
0361:             * 
0362:             * @param virtualname name of the virtual database
0363:             * @return a translated string for success message
0364:             */
0365:            public String removeVirtualDatabase(String virtualname) {
0366:                if (hasVirtualDatabase(virtualname)) {
0367:                    if (this .virtualDatabases.remove(virtualname) == null) {
0368:                        logger
0369:                                .warn("Unexpected missing virtual database named "
0370:                                        + virtualname
0371:                                        + " while removing from virtual database list");
0372:                    }
0373:
0374:                    // Send notification
0375:                    sendJmxNotification(
0376:                            SequoiaNotificationList.CONTROLLER_VIRTUALDATABASE_REMOVED,
0377:                            Translate.get(
0378:                                    "notification.virtualdatabase.shutdown",
0379:                                    virtualname));
0380:                }
0381:                return Translate
0382:                        .get("controller.removeVirtualDatabase.success",
0383:                                virtualname);
0384:            }
0385:
0386:            //
0387:            // Controller operations
0388:            //
0389:
0390:            /**
0391:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#addDriver(byte[])
0392:             */
0393:            public void addDriver(byte[] bytes) throws Exception {
0394:                // Try to find drivers directory in the classpath
0395:                File driversDirectory = null;
0396:                URL url = Controller.class
0397:                        .getResource(ControllerConstants.SEQUOIA_DRIVER_JAR_FILE);
0398:                boolean error = false;
0399:                if (url != null) {
0400:                    driversDirectory = (new File(URLDecoder.decode(url
0401:                            .getFile()))).getParentFile();
0402:                    error = (driversDirectory == null)
0403:                            || !driversDirectory.exists();
0404:                }
0405:
0406:                if (error) {
0407:                    String msg = Translate.get(
0408:                            "controller.driver.dir.not.found", driversDirectory
0409:                                    .toString());
0410:                    logger.error(msg);
0411:                    endUserLogger.error(Translate.get(
0412:                            "controller.add.driver.failed", msg));
0413:                    throw new ControllerException(msg);
0414:                }
0415:
0416:                // Read the array of bytes to a file
0417:                File temp = null;
0418:                try {
0419:                    temp = File.createTempFile("driver", "zip",
0420:                            driversDirectory);
0421:                    FileOutputStream output = new FileOutputStream(temp);
0422:                    output.write(bytes);
0423:                    output.close();
0424:                } catch (IOException e) {
0425:                    String msg = Translate.get(
0426:                            "controller.add.jar.write.failed", e);
0427:                    logger.error(msg);
0428:                    endUserLogger.error(Translate.get(
0429:                            "controller.add.driver.failed", msg));
0430:                    throw new ControllerException(msg);
0431:                }
0432:
0433:                // Unzip the file content
0434:                try {
0435:                    Enumeration entries;
0436:                    ZipFile zipFile = new ZipFile(temp);
0437:
0438:                    // Read the file
0439:                    int lenght;
0440:                    InputStream in;
0441:                    BufferedOutputStream out;
0442:                    byte[] buffer = new byte[1024];
0443:
0444:                    entries = zipFile.entries();
0445:                    while (entries.hasMoreElements()) {
0446:                        ZipEntry entry = (ZipEntry) entries.nextElement();
0447:
0448:                        if (entry.isDirectory()) {
0449:                            // Create the directory
0450:                            if (logger.isDebugEnabled())
0451:                                logger.debug(Translate.get(
0452:                                        "controller.add.jar.extract.dir", entry
0453:                                                .getName()));
0454:
0455:                            (new File(driversDirectory, entry.getName()))
0456:                                    .mkdir();
0457:                            continue;
0458:                        }
0459:
0460:                        // Extract the file
0461:                        if (logger.isDebugEnabled())
0462:                            logger.debug(Translate.get(
0463:                                    "controller.add.jar.extract.file", entry
0464:                                            .getName()));
0465:
0466:                        in = zipFile.getInputStream(entry);
0467:                        out = new BufferedOutputStream(new FileOutputStream(
0468:                                driversDirectory
0469:                                        + System.getProperty("file.separator")
0470:                                        + entry.getName()));
0471:                        while ((lenght = in.read(buffer)) >= 0)
0472:                            out.write(buffer, 0, lenght);
0473:
0474:                        in.close();
0475:                        out.close();
0476:                    }
0477:
0478:                    zipFile.close();
0479:                    temp.delete();
0480:                    String msg = Translate.get("controller.add.driver.success",
0481:                            driversDirectory.toString());
0482:                    logger.info(msg);
0483:                    endUserLogger.info(msg);
0484:                } catch (IOException e) {
0485:                    String msg = Translate.get(
0486:                            "controller.driver.extract.failed", new String[] {
0487:                                    temp.getCanonicalPath(), e.getMessage() });
0488:                    logger.error(msg);
0489:                    endUserLogger.error(Translate.get(
0490:                            "controller.add.driver.failed", msg));
0491:                    throw new ControllerException(msg);
0492:                }
0493:            }
0494:
0495:            /**
0496:             * Read a XML configuration file and load only the
0497:             * <code>VirtualDatabase</code> specified in the arguments list
0498:             * 
0499:             * @param filename XML configuration file name to take info on
0500:             *          <code>VirtualDatabase</code>
0501:             * @param virtualName the only database to load, null if should load all
0502:             * @param autoLoad specifies if the backends should be enabled automatically
0503:             *          after loading
0504:             * @param checkPoint checkPoint to recover from when enabling backends. Leave
0505:             *          <code>null</code> if no recovery option is needed.
0506:             * @return a diagnostic message (success or error)
0507:             * @throws Exception if an error occurs
0508:             */
0509:            public String loadXmlConfiguration(String filename,
0510:                    String virtualName, int autoLoad, String checkPoint)
0511:                    throws Exception {
0512:                FileReader fileReader = null;
0513:                try {
0514:                    filename = filename.trim();
0515:                    try {
0516:                        fileReader = new FileReader(filename);
0517:                    } catch (FileNotFoundException fnf) {
0518:                        return Translate.get("controller.file.not.found",
0519:                                filename);
0520:                    }
0521:
0522:                    if (logger.isDebugEnabled())
0523:                        logger.debug("Loading virtual database configuration "
0524:                                + filename);
0525:                    // Read the file
0526:                    BufferedReader in = new BufferedReader(fileReader);
0527:                    StringBuffer xml = new StringBuffer();
0528:                    String line;
0529:                    do {
0530:                        line = in.readLine();
0531:                        if (line != null)
0532:                            xml.append(line);
0533:                    } while (line != null);
0534:
0535:                    // Send it to the controller
0536:                    addVirtualDatabases(xml.toString(), virtualName, autoLoad,
0537:                            checkPoint);
0538:                    return Translate.get("controller.file.send", filename);
0539:                } catch (Exception e) {
0540:                    logger.error(Translate.get("controller.loadXml.failed",
0541:                            ControllerConstants.PRODUCT_NAME, e), e);
0542:                    throw new ControllerException(Translate.get(
0543:                            "controller.loadXml.failed",
0544:                            ControllerConstants.PRODUCT_NAME, e));
0545:                } finally {
0546:                    if (fileReader != null)
0547:                        fileReader.close();
0548:                }
0549:            }
0550:
0551:            /**
0552:             * Save current configuration of the controller to a default file
0553:             * 
0554:             * @return Status message
0555:             * @throws Exception if an error occurs
0556:             * @see org.continuent.sequoia.controller.core.ControllerConstants#getSaveFile
0557:             */
0558:            public String saveConfiguration() throws Exception {
0559:                String msg;
0560:                try {
0561:                    String configurationFile = ControllerConstants
0562:                            .getSaveFile(new SimpleDateFormat(
0563:                                    "yyyy-MM-dd-HH-mm").format(new Date()));
0564:                    DataOutputStream dos = new DataOutputStream(
0565:                            new BufferedOutputStream(new FileOutputStream(
0566:                                    configurationFile)));
0567:                    StringBuffer xml = new StringBuffer();
0568:                    xml.append(XmlTools.prettyXml(getXmlVirtualDatabases()));
0569:                    String prettyXml = xml.toString();
0570:                    // ugly hack to insert the doctype which has been stripped
0571:                    // when prettyfying the xml
0572:                    prettyXml = XmlTools.insertDoctype(prettyXml,
0573:                            ControllerConstants.VIRTUAL_DATABASE_DOCTYPE);
0574:                    dos.write(prettyXml.getBytes());
0575:                    dos.close();
0576:                    msg = Translate.get("controller.save.configuration",
0577:                            configurationFile);
0578:                    return msg;
0579:                } catch (Exception e) {
0580:                    msg = Translate.get("controller.save.configuration.failed",
0581:                            e);
0582:                    logger.error(msg);
0583:                    throw new ControllerException(msg, e);
0584:                }
0585:            }
0586:
0587:            //
0588:            // Controller shutdown
0589:            //
0590:            /**
0591:             * Create report about fatal error
0592:             * 
0593:             * @param fatal the cause of the fatal error
0594:             */
0595:            public void endOfController(Exception fatal) {
0596:                endUserLogger.fatal(Translate.get("fatal.error"));
0597:                logger.fatal(Translate.get("fatal.error"));
0598:                if (report.isGenerateOnFatal()) {
0599:                    new ReportManager(this ).generateAndWriteException(true,
0600:                            fatal);
0601:                    logger
0602:                            .info(Translate.get("fatal.report.generated",
0603:                                    report.getReportLocation() + File.separator
0604:                                            + ControllerConstants.REPORT_FILE));
0605:                }
0606:                Runtime.getRuntime().exit(1);
0607:            }
0608:
0609:            /**
0610:             * Access the connection thread. Need this for shutting down
0611:             * 
0612:             * @return <code>connectionThread</code>
0613:             */
0614:            public ControllerServerThread getConnectionThread() {
0615:                return connectionThread;
0616:            }
0617:
0618:            /**
0619:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#isShuttingDown()
0620:             */
0621:            public boolean isShuttingDown() {
0622:                return isShuttingDown;
0623:            }
0624:
0625:            /**
0626:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#shutdown()
0627:             */
0628:            public void shutdown() throws ControllerException {
0629:                if (virtualDatabases.size() != 0) {
0630:                    String listOfActiveVdbs = "";
0631:                    for (Enumeration e = virtualDatabases.keys(); e
0632:                            .hasMoreElements();) {
0633:                        if (listOfActiveVdbs.length() != 0)
0634:                            listOfActiveVdbs = listOfActiveVdbs + ",";
0635:                        listOfActiveVdbs = listOfActiveVdbs + e.nextElement();
0636:                    }
0637:                    String msg = Translate
0638:                            .get(
0639:                                    "controller.shutdown.error.existing.virtualdatabases",
0640:                                    new String[] { getControllerName(),
0641:                                            listOfActiveVdbs });
0642:                    throw new ControllerException(msg);
0643:                }
0644:
0645:                ControllerShutdownThread shutdownThread = null;
0646:                synchronized (this ) {
0647:                    if (isShuttingDown()) {
0648:                        logger.info(Translate.get(
0649:                                "controller.already.shutting.down", this 
0650:                                        .getControllerName()));
0651:                        return;
0652:                    }
0653:
0654:                    isShuttingDown = true;
0655:                    shutdownThread = new ControllerShutdownThread(this );
0656:                    logger.info(Translate.get("controller.shutdown", this 
0657:                            .getControllerName()));
0658:                }
0659:
0660:                Thread thread = new Thread(shutdownThread.getShutdownGroup(),
0661:                        shutdownThread, "Controller Shutdown Thread");
0662:                thread.start();
0663:
0664:                try {
0665:                    logger.info("Waiting for controller shutdown");
0666:                    thread.join();
0667:                    logger.info(Translate.get("controller.shutdown.completed",
0668:                            this .getControllerName()));
0669:                } catch (InterruptedException e) {
0670:                    e.printStackTrace();
0671:                }
0672:            }
0673:
0674:            /**
0675:             * Launches the Sequoia controller. The available options are:
0676:             * <ul>
0677:             * <li><code>-h</code> or <code>--help</code> <code>&lt;port&gt;</code>:
0678:             * displays usage informations.</li>
0679:             * <li><code>-j</code> or <code>--jmx</code> <code>&lt;port&gt;</code>:
0680:             * optinal JMX server HTTP adaptor port number.</li>
0681:             * <li><code>-n</code> or <code>--name</code> <code>&lt;name&gt;</code>:
0682:             * optional controller name.</li>
0683:             * <li><code>-i</code> or <code>--ip</code> <code>&lt;ip&gt;</code>:
0684:             * optional IP address to beind the controller to.</li>
0685:             * <li><code>-r</code> or <code>--rmi</code> <code>&lt;port&gt;</code>:
0686:             * optional RMI registry port number.</li>
0687:             * <li><code>-v</code> or <code>--version</code>: displays version
0688:             * informations.</li>
0689:             * </ul>
0690:             * <p>
0691:             * The controller starts listening for socket connections on the default port.
0692:             * Jmx is configured, and a virtual database can be added.
0693:             * <p>
0694:             * {@link org.continuent.sequoia.controller.core.ControllerConstants#DEFAULT_PORT}
0695:             * Default Listening port
0696:             * 
0697:             * @param args command line arguments (see above)
0698:             * @throws Exception when everything goes wrong
0699:             */
0700:            public static void main(String[] args) throws Exception {
0701:                System
0702:                        .setProperty(
0703:                                "javax.management.builder.initial",
0704:                                org.continuent.sequoia.controller.jmx.MBeanServerBuilder.class
0705:                                        .getName());
0706:
0707:                if (ControllerConstants.CONTROLLER_FACTORY == null) {
0708:                    System.err
0709:                            .println("Impossible to start Controller with an invalid controller.properties file.");
0710:                    System.exit(1);
0711:                }
0712:
0713:                // This parses command line arguments and exits for 
0714:                // --help and --version
0715:                ControllerConfiguration conf = new ControllerConfiguration(args);
0716:
0717:                logger.info(getVersion());
0718:
0719:                Controller controller = conf.getController();
0720:                if (controller != null)
0721:                    controller.launch();
0722:                else {
0723:                    endUserLogger.error(Translate
0724:                            .get("controller.configure.failed"));
0725:                    throw new Exception(Translate
0726:                            .get("controller.configure.failed"));
0727:                }
0728:            }
0729:
0730:            /**
0731:             * Actively launch the <code>controller</code>. Add startup actions here to
0732:             * avoid them in <method>main </method>
0733:             */
0734:            public void launch() {
0735:                connectionThread = new ControllerServerThread(this );
0736:                connectionThread.start();
0737:
0738:                SimpleDateFormat formatter = new SimpleDateFormat(
0739:                        "yyyy.MM.dd ww 'at' hh:mm:ss a zzz");
0740:                Date day = new Date();
0741:                String date = formatter.format(day);
0742:                logger.info(Translate.get("controller.date", date));
0743:                logger.info(Translate.get("controller.ready",
0744:                        getControllerName()));
0745:                endUserLogger.info(Translate.get("controller.ready",
0746:                        getControllerName()));
0747:            }
0748:
0749:            //
0750:            // Controller information
0751:            //
0752:
0753:            /**
0754:             * Returns the controller name.
0755:             * 
0756:             * @return String
0757:             */
0758:            public String getControllerName() {
0759:                return ipAddress + ":" + portNumber;
0760:            }
0761:
0762:            /**
0763:             * Get the IP address to bind the controller to
0764:             * 
0765:             * @return the IP address
0766:             */
0767:            public String getIPAddress() {
0768:                return ipAddress;
0769:            }
0770:
0771:            /**
0772:             * Set the IP address to bind the controller to
0773:             * 
0774:             * @param ipAddress the IP address to use
0775:             */
0776:            public void setIPAddress(String ipAddress) {
0777:                this .ipAddress = ipAddress;
0778:            }
0779:
0780:            /**
0781:             * Get the controller port number
0782:             * 
0783:             * @return the port number
0784:             */
0785:            public int getPortNumber() {
0786:                return portNumber;
0787:            }
0788:
0789:            /**
0790:             * Set the controller backlog size.
0791:             * 
0792:             * @param port the port number to set
0793:             */
0794:            public void setPortNumber(int port) {
0795:                portNumber = port;
0796:            }
0797:
0798:            /**
0799:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#getBacklogSize()
0800:             */
0801:            public int getBacklogSize() {
0802:                return backlogSize;
0803:            }
0804:
0805:            /**
0806:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#setBacklogSize(int)
0807:             */
0808:            public void setBacklogSize(int size) {
0809:                backlogSize = size;
0810:            }
0811:
0812:            /**
0813:             * Returns jmx enable
0814:             * 
0815:             * @return jmxEnabled
0816:             */
0817:            public boolean getJmxEnable() {
0818:                return MBeanServerManager.isJmxEnabled();
0819:            }
0820:
0821:            /**
0822:             * Return the jmx name of this controller (hostname:rmiport)
0823:             * 
0824:             * @return jmx name
0825:             */
0826:            public String getJmxName() {
0827:                if (getJmxEnable()) {
0828:                    List rmiConnectors = RmiConnector.getRmiConnectors();
0829:                    if ((rmiConnectors != null) && (rmiConnectors.size() > 0)) {
0830:                        RmiConnector connector = ((RmiConnector) rmiConnectors
0831:                                .get(0));
0832:                        return connector.getHostName() + ":"
0833:                                + connector.getPort();
0834:                    }
0835:                }
0836:                return getControllerName();
0837:            }
0838:
0839:            /**
0840:             * set enable JMX
0841:             * 
0842:             * @param enable true if jmx should be enable.
0843:             */
0844:            public void setJmxEnable(boolean enable) {
0845:                configuration.put(ControllerConfiguration.JMX_ENABLE, ""
0846:                        + enable);
0847:            }
0848:
0849:            /**
0850:             * Returns Version as a long String
0851:             * 
0852:             * @return version
0853:             */
0854:            public static String getVersion() {
0855:                return Translate.get("controller.info", new String[] {
0856:                        ControllerConstants.PRODUCT_NAME, Constants.VERSION });
0857:            }
0858:
0859:            /**
0860:             * Get current configuration options
0861:             * 
0862:             * @return configure a <code>Hashtable</code> with controller options
0863:             */
0864:            public Hashtable getConfiguration() {
0865:                return configuration;
0866:            }
0867:
0868:            /**
0869:             * Check whether security is enabled or not
0870:             * 
0871:             * @return true if there is not null controller security manager
0872:             */
0873:            public boolean isSecurityEnabled() {
0874:                return security != null;
0875:            }
0876:
0877:            /**
0878:             * @return Returns the security.
0879:             */
0880:            public ControllerSecurityManager getSecurity() {
0881:                return security;
0882:            }
0883:
0884:            /**
0885:             * @param security The security to set.
0886:             */
0887:            public void setSecurity(ControllerSecurityManager security) {
0888:                this .security = security;
0889:            }
0890:
0891:            /**
0892:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#generateReport()
0893:             */
0894:            public void generateReport() throws Exception {
0895:                report.generate(true);
0896:            }
0897:
0898:            /**
0899:             * Sets the configuration value.
0900:             * 
0901:             * @param configuration The configuration to set.
0902:             */
0903:            public void setConfiguration(Hashtable configuration) {
0904:                this .configuration = configuration;
0905:            }
0906:
0907:            /**
0908:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#getVersionNumber()
0909:             */
0910:            public String getVersionNumber() {
0911:                return Constants.VERSION;
0912:            }
0913:
0914:            /**
0915:             * @see org.continuent.sequoia.common.xml.XmlComponent#getXml()
0916:             */
0917:            public String getXml() {
0918:                try {
0919:                    String prettyXml = XmlTools.prettyXml(getXmlController());
0920:                    return XmlTools.insertDoctype(prettyXml,
0921:                            ControllerConstants.CONTROLLER_DOCTYPE);
0922:                } catch (Exception e) {
0923:                    logger.error(Translate.get(
0924:                            "controller.xml.transformation.failed", e));
0925:                    return e.getMessage();
0926:                }
0927:            }
0928:
0929:            /**
0930:             * Return the xml version of the controller.xml file without doc type
0931:             * declaration, just data.
0932:             * 
0933:             * @return controller xml data
0934:             */
0935:            public String getXmlController() {
0936:                StringBuffer info = new StringBuffer();
0937:                info
0938:                        .append("<"
0939:                                + ControllerConstants.CONTROLLER_XML_ROOT_ELEMENT
0940:                                + ">");
0941:                info.append("<" + ControllerXmlTags.ELT_CONTROLLER + " "
0942:                        + ControllerXmlTags.ATT_CONTROLLER_IP + "=\""
0943:                        + this .getIPAddress() + "\" "
0944:                        + ControllerXmlTags.ATT_CONTROLLER_PORT + "=\""
0945:                        + this .getPortNumber() + "\" " + ">");
0946:
0947:                info.append("<" + ControllerXmlTags.ELT_INTERNATIONALIZATION
0948:                        + " " + ControllerXmlTags.ATT_LANGUAGE + "=\""
0949:                        + Locale.getDefault().getLanguage() + "\"/>");
0950:
0951:                if (report.isReportEnabled()) {
0952:                    info.append("<" + ControllerXmlTags.ELT_REPORT + " "
0953:                            + ControllerXmlTags.ATT_REPORT_ENABLE_FILE_LOGGING
0954:                            + "=\"" + report.isEnableFileLogging() + "\" "
0955:                            + ControllerXmlTags.ATT_REPORT_HIDE_SENSITIVE_DATA
0956:                            + "=\"" + report.isHideSensitiveData() + "\" "
0957:                            + ControllerXmlTags.ATT_REPORT_GENERATE_ON_FATAL
0958:                            + "=\"" + report.isGenerateOnFatal() + "\" "
0959:                            + ControllerXmlTags.ATT_REPORT_GENERATE_ON_SHUTDOWN
0960:                            + "=\"" + report.isGenerateOnShutdown() + "\" "
0961:                            + ControllerXmlTags.ATT_REPORT_REPORT_LOCATION
0962:                            + "=\"" + report.getReportLocation() + "\" />");
0963:                }
0964:
0965:                if (getJmxEnable()) {
0966:                    info.append("<" + ControllerXmlTags.ELT_JMX + ">");
0967:                    if (configuration
0968:                            .containsKey(JmxConstants.ADAPTOR_TYPE_HTTP)) {
0969:                        info.append("<"
0970:                                + ControllerXmlTags.ELT_HTTP_JMX_ADAPTOR
0971:                                + " "
0972:                                + ControllerXmlTags.ATT_JMX_ADAPTOR_PORT
0973:                                + "=\""
0974:                                + configuration
0975:                                        .get(JmxConstants.ADAPTOR_TYPE_HTTP)
0976:                                + "\" />");
0977:                    }
0978:                    if (configuration
0979:                            .containsKey(JmxConstants.ADAPTOR_TYPE_RMI)) {
0980:                        info.append("<"
0981:                                + ControllerXmlTags.ELT_RMI_JMX_ADAPTOR
0982:                                + " "
0983:                                + ControllerXmlTags.ATT_JMX_ADAPTOR_PORT
0984:                                + "=\""
0985:                                + configuration
0986:                                        .get(JmxConstants.ADAPTOR_TYPE_RMI)
0987:                                + "\" />");
0988:                    }
0989:
0990:                    info.append("</" + ControllerXmlTags.ELT_JMX + ">");
0991:                }
0992:
0993:                if (this .isSecurityEnabled())
0994:                    info.append(this .getSecurity().getXml());
0995:                info.append("</" + ControllerXmlTags.ELT_CONTROLLER + ">");
0996:                info
0997:                        .append("</"
0998:                                + ControllerConstants.CONTROLLER_XML_ROOT_ELEMENT
0999:                                + ">");
1000:                return info.toString();
1001:            }
1002:
1003:            /**
1004:             * Same as above but for the virtual databases.
1005:             * 
1006:             * @return xml virtual databases data.
1007:             */
1008:            public String getXmlVirtualDatabases() {
1009:                try {
1010:                    StringBuffer info = new StringBuffer();
1011:                    info.append(XML_VERSION);
1012:                    info.append("\n");
1013:                    info
1014:                            .append("<"
1015:                                    + ControllerConstants.VIRTUAL_DATABASE_XML_ROOT_ELEMENT
1016:                                    + ">");
1017:                    List vdbs = this .getVirtualDatabases();
1018:                    for (int i = 0; i < vdbs.size(); i++) {
1019:                        info.append(((XmlComponent) vdbs.get(i)).getXml());
1020:                    }
1021:                    info
1022:                            .append("</"
1023:                                    + ControllerConstants.VIRTUAL_DATABASE_XML_ROOT_ELEMENT
1024:                                    + ">");
1025:                    return info.toString();
1026:                } catch (Exception e) {
1027:                    logger.error(e.getMessage(), e);
1028:                    return e.getMessage();
1029:                }
1030:            }
1031:
1032:            // 
1033:            // Logging system
1034:            //
1035:
1036:            /**
1037:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#refreshLogConfiguration()
1038:             */
1039:            public void refreshLogConfiguration() throws ControllerException {
1040:                try {
1041:                    LogManager.configure(URLDecoder.decode(this .getClass()
1042:                            .getResource(ControllerConstants.LOG4J_RESOURCE)
1043:                            .getFile()));
1044:                    if (logger.isDebugEnabled())
1045:                        logger.info(Translate
1046:                                .get("controller.refresh.log.success"));
1047:                } catch (Exception e) {
1048:                    throw new ControllerException(Translate
1049:                            .get("controller.logconfigfile.not.found"));
1050:                }
1051:            }
1052:
1053:            /**
1054:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#updateLogConfigurationFile(java.lang.String)
1055:             */
1056:            public void updateLogConfigurationFile(String newConfiguration)
1057:                    throws IOException, ControllerException {
1058:                File logFile = new File(URLDecoder.decode(getClass()
1059:                        .getResource(ControllerConstants.LOG4J_RESOURCE)
1060:                        .getFile()));
1061:                BufferedWriter writer = new BufferedWriter(new FileWriter(
1062:                        logFile));
1063:                writer.write(newConfiguration);
1064:                writer.flush();
1065:                writer.close();
1066:                refreshLogConfiguration();
1067:            }
1068:
1069:            /**
1070:             * @see org.continuent.sequoia.common.jmx.mbeans.ControllerMBean#viewLogConfigurationFile()
1071:             */
1072:            public String viewLogConfigurationFile() throws IOException {
1073:                File logFile = new File(URLDecoder.decode(getClass()
1074:                        .getResource(ControllerConstants.LOG4J_RESOURCE)
1075:                        .getFile()));
1076:                BufferedReader reader = new BufferedReader(new FileReader(
1077:                        logFile));
1078:                StringBuffer buffer = new StringBuffer();
1079:                String line;
1080:                while ((line = reader.readLine()) != null)
1081:                    buffer.append(line + System.getProperty("line.separator"));
1082:                reader.close();
1083:                return buffer.toString();
1084:            }
1085:
1086:            /**
1087:             * Returns the report value.
1088:             * 
1089:             * @return Returns the report.
1090:             */
1091:            public ReportManager getReport() {
1092:                return report;
1093:            }
1094:
1095:            /**
1096:             * Sets the report value.
1097:             * 
1098:             * @param report The report to set.
1099:             */
1100:            public void setReport(ReportManager report) {
1101:                this.report = report;
1102:            }
1103:
1104:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.