KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > controller > core > Controller


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2005 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General public final License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General public final License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General public final License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Mathieu Peltier, Nicolas Modrzyk.
23  */

24
25 package org.objectweb.cjdbc.controller.core;
26
27 import java.io.BufferedOutputStream JavaDoc;
28 import java.io.BufferedReader JavaDoc;
29 import java.io.BufferedWriter JavaDoc;
30 import java.io.DataOutputStream JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.FileNotFoundException JavaDoc;
33 import java.io.FileOutputStream JavaDoc;
34 import java.io.FileReader JavaDoc;
35 import java.io.FileWriter JavaDoc;
36 import java.io.IOException JavaDoc;
37 import java.io.InputStream JavaDoc;
38 import java.net.URL JavaDoc;
39 import java.net.URLDecoder JavaDoc;
40 import java.text.SimpleDateFormat JavaDoc;
41 import java.util.ArrayList JavaDoc;
42 import java.util.Date JavaDoc;
43 import java.util.Enumeration JavaDoc;
44 import java.util.Hashtable JavaDoc;
45 import java.util.Iterator JavaDoc;
46 import java.util.Locale JavaDoc;
47 import java.util.zip.ZipEntry JavaDoc;
48 import java.util.zip.ZipFile JavaDoc;
49
50 import javax.management.NotCompliantMBeanException JavaDoc;
51 import javax.management.ObjectName JavaDoc;
52
53 import org.objectweb.cjdbc.common.exceptions.ControllerException;
54 import org.objectweb.cjdbc.common.exceptions.VirtualDatabaseException;
55 import org.objectweb.cjdbc.common.i18n.Translate;
56 import org.objectweb.cjdbc.common.jmx.JmxConstants;
57 import org.objectweb.cjdbc.common.jmx.JmxException;
58 import org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean;
59 import org.objectweb.cjdbc.common.jmx.notifications.CjdbcNotificationList;
60 import org.objectweb.cjdbc.common.log.LogManager;
61 import org.objectweb.cjdbc.common.log.Trace;
62 import org.objectweb.cjdbc.common.util.Constants;
63 import org.objectweb.cjdbc.common.xml.ControllerXmlTags;
64 import org.objectweb.cjdbc.common.xml.DatabasesXmlTags;
65 import org.objectweb.cjdbc.common.xml.XmlComponent;
66 import org.objectweb.cjdbc.common.xml.XmlTools;
67 import org.objectweb.cjdbc.controller.core.security.ControllerSecurityManager;
68 import org.objectweb.cjdbc.controller.core.shutdown.ControllerForceShutdownThread;
69 import org.objectweb.cjdbc.controller.core.shutdown.ControllerSafeShutdownThread;
70 import org.objectweb.cjdbc.controller.core.shutdown.ControllerShutdownThread;
71 import org.objectweb.cjdbc.controller.core.shutdown.ControllerWaitShutdownThread;
72 import org.objectweb.cjdbc.controller.jmx.AbstractStandardMBean;
73 import org.objectweb.cjdbc.controller.jmx.MBeanServerManager;
74 import org.objectweb.cjdbc.controller.jmx.RmiConnector;
75 import org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabase;
76 import org.objectweb.cjdbc.controller.xml.DatabasesParser;
77
78 /**
79  * The C-JDBC controller main class. It registers itself in the RMI registry and
80  * waits for C-JDBC driver requests.
81  *
82  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
83  * @author <a HREF="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
84  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
85  * @author <a HREF="mailto:duncan@mightybot.com">Duncan Smith </a>
86  * @version 1.0
87  */

88 public final class Controller extends AbstractStandardMBean
89     implements
90       ControllerMBean,
91       XmlComponent
92 {
93
94   /** C-JDBC controller port number listening for driver connections */
95   private int portNumber;
96   private int backlogSize;
97
98   /**
99    * The IP address to bind the controller to. Useful for machines that contain
100    * multiple network interface cards and wish to bind to a specific card.
101    * Default evaluates to localhost IP address (127.0.0.1).
102    */

103   private String JavaDoc ipAddress;
104
105   /** Thread that listens for driver connections */
106   private ControllerServerThread connectionThread;
107
108   /** Logger instance. */
109   static Trace logger = Trace
110                                                .getLogger("org.objectweb.cjdbc.controller.core.Controller");
111
112   /** Hashtable of <code>VirtualDatabase</code> objects. */
113   private Hashtable JavaDoc virtualDatabases;
114
115   /** Hashtable of options */
116   private Hashtable JavaDoc configuration;
117
118   /** Security Manager */
119   private ControllerSecurityManager security;
120
121   /** Report Manager */
122   private ReportManager report;
123
124   private boolean isShuttingDown;
125
126   /* Constructor(s) */
127
128   /**
129    * Creates a new <code>Controller</code> instance.
130    *
131    * @param ipAddress bind the controller to this ipAddress
132    * @param port bind the controller to listen to this port
133    * @param backlog backlog connection size
134    * @exception NotCompliantMBeanException in case the bean does not comply with
135    * jmx
136    * @exception JmxException the bean could not be registered
137    */

138   public Controller(String JavaDoc ipAddress, int port, int backlog)
139       throws NotCompliantMBeanException JavaDoc, JmxException
140   {
141     super(ControllerMBean.class);
142     virtualDatabases = new Hashtable JavaDoc();
143     this.ipAddress = ipAddress;
144     this.portNumber = port;
145     this.backlogSize = backlog;
146     ObjectName JavaDoc name = JmxConstants.getControllerObjectName();
147     MBeanServerManager.registerMBean(this, name);
148   }
149
150   //
151
// Virtual databases management
152
//
153

154   /**
155    * Adds virtual databases contained in the XML document given as a String. If
156    * a virtual database name is provided, only this database is loaded with the
157    * provided autoLoad and checkpoint information.
158    *
159    * @param xml XML configuration file content
160    * @param vdbName optional virtual database name to autoload
161    * @param autoEnable autoenable backend mode for virtual database
162    * @param checkpoint checkpoint name if autoEnable is set to force
163    * @throws ControllerException if an error occurs
164    */

165   public void addVirtualDatabases(String JavaDoc xml, String JavaDoc vdbName, int autoEnable,
166       String JavaDoc checkpoint) throws ControllerException
167   {
168     if (logger.isDebugEnabled())
169       logger.debug(Translate.get("controller.add.virtualdatabase", vdbName));
170     if (vdbName != null && this.hasVirtualDatabase(vdbName))
171     {
172       throw new ControllerException(Translate
173           .get("controller.add.virtualdatabase.already.used"));
174     }
175     try
176     {
177       DatabasesParser parser = new DatabasesParser(this, vdbName, autoEnable,
178           checkpoint);
179       parser.readXML(xml, true);
180     }
181     catch (Exception JavaDoc e)
182     {
183       String JavaDoc msg = Translate.get("controller.add.virtualdatabase.failed", e);
184       logger.warn(msg, e);
185       throw new ControllerException(msg);
186     }
187   }
188
189   /**
190    * Register a VirtualDatabase with default options
191    *
192    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#addVirtualDatabases(String)
193    */

194   public void addVirtualDatabases(String JavaDoc xml) throws ControllerException
195   {
196     if (logger.isDebugEnabled())
197     {
198       logger.debug(Translate.get("controller.loading.virtualdatabase"));
199     }
200     this.addVirtualDatabases(xml, null,
201         ControllerConstants.AUTO_ENABLE_BACKEND,
202         ControllerConstants.DATABASE_DEFAULT_CHECKPOINT);
203   }
204
205   /**
206    * Registers a new <code>VirtualDatabase</code> in this controller.
207    *
208    * @param vdb the <code>VirtualDatabase</code> to register
209    * @throws ControllerException if an error occurs
210    */

211   public void addVirtualDatabase(VirtualDatabase vdb)
212       throws ControllerException
213   {
214     this.addVirtualDatabase(vdb, ControllerConstants.AUTO_ENABLE_BACKEND,
215         ControllerConstants.DATABASE_DEFAULT_CHECKPOINT);
216   }
217
218   /**
219    * Add the virtual database with the specified options
220    *
221    * @param vdb the <code>VirtualDatabase</code> object to add
222    * @param autoLoad specified if backends should be enabled
223    * @param checkPoint specified the checkPoint to recover from, leave null if
224    * no recovery speficied
225    * @throws ControllerException if database already exists on the specified
226    * <code>Controller</code> object
227    */

228   public synchronized void addVirtualDatabase(VirtualDatabase vdb,
229       int autoLoad, String JavaDoc checkPoint) throws ControllerException
230   {
231     // Add the database or retrieve it if it already exists
232
if (hasVirtualDatabase(vdb.getDatabaseName()))
233     {
234       String JavaDoc msg = Translate.get("controller.database.already.exists", vdb
235           .getDatabaseName());
236       logger.warn(msg);
237       throw new ControllerException(msg);
238     }
239     else
240     {
241       virtualDatabases.put(vdb.getDatabaseName(), vdb);
242
243       // Send notification
244
if (MBeanServerManager.isJmxEnabled())
245       {
246         Hashtable JavaDoc databases = new Hashtable JavaDoc();
247         try
248         {
249           databases.put("backends", vdb.getAllBackendNames());
250         }
251         catch (VirtualDatabaseException e)
252         {
253           // ignore
254
}
255         RmiConnector.broadcastNotification(this,
256             CjdbcNotificationList.CONTROLLER_VIRTUALDATABASE_ADDED,
257             CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get(
258                 "notification.virtualdatabase.added", vdb
259                     .getVirtualDatabaseName()), databases);
260       }
261     }
262
263     // Enable backends with the proper states
264
try
265     {
266       if (logger.isDebugEnabled())
267         logger.debug(Translate.get("controller.database.autoenable", autoLoad));
268
269       switch (autoLoad)
270       {
271         case ControllerConstants.AUTO_ENABLE_TRUE :
272           vdb.enableAllBackendsFromCheckpoint();
273           break;
274         case ControllerConstants.AUTO_ENABLE_FALSE :
275           break;
276         case ControllerConstants.AUTO_ENABLE_FORCE :
277           logger.warn("Backends enabled in force mode from checkpoint "
278               + checkPoint);
279           vdb.forceEnableAllBackendsFromCheckpoint(checkPoint);
280           break;
281         default :
282           logger
283               .error("Unsupported autoEnabledBackends mode in controller configuration");
284           break;
285       }
286     }
287     catch (VirtualDatabaseException e)
288     {
289       throw new ControllerException(e);
290     }
291
292     logger.info(Translate.get("controller.add.virtualdatabase", vdb
293         .getDatabaseName()));
294   }
295
296   /**
297    * Gets the <code>VirtualDatabase</code> object corresponding to a virtual
298    * database name.
299    *
300    * @param virtualDatabaseName the virtual database name
301    * @return a <code>VirtualDatabase</code> object or null if not found
302    */

303   public VirtualDatabase getVirtualDatabase(String JavaDoc virtualDatabaseName)
304   {
305     return (VirtualDatabase) virtualDatabases.get(virtualDatabaseName);
306   }
307
308   /**
309    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#getVirtualDatabaseNames()
310    */

311   public ArrayList JavaDoc getVirtualDatabaseNames()
312   {
313     ArrayList JavaDoc result = new ArrayList JavaDoc();
314     for (Iterator JavaDoc iter = virtualDatabases.values().iterator(); iter.hasNext();)
315       result.add(((VirtualDatabase) iter.next()).getVirtualDatabaseName());
316     return result;
317   }
318
319   /**
320    * Returns information about the available virtual databases.
321    *
322    * @return ArrayList of information about virtual databases.
323    */

324   public ArrayList JavaDoc getVirtualDatabases()
325   {
326     ArrayList JavaDoc result = new ArrayList JavaDoc();
327     for (Iterator JavaDoc iter = virtualDatabases.values().iterator(); iter.hasNext();)
328       result.add(iter.next());
329     return result;
330   }
331
332   /**
333    * Tests if a <code>VirtualDatabase</code> of a given name exists in this
334    * controller.
335    *
336    * @param name the virtual database name
337    * @return <code>true</code> if the virtual database exists
338    */

339   public boolean hasVirtualDatabase(String JavaDoc name)
340   {
341     return virtualDatabases.containsKey(name);
342   }
343
344   /**
345    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#removeVirtualDatabase(String)
346    */

347   public String JavaDoc removeVirtualDatabase(String JavaDoc virtualname)
348       throws ControllerException
349   {
350     if (hasVirtualDatabase(virtualname))
351     {
352       VirtualDatabase vdb = (VirtualDatabase) virtualDatabases.get(virtualname);
353       try
354       {
355         vdb.disableAllBackends();
356       }
357       catch (VirtualDatabaseException e)
358       {
359         throw new ControllerException(e);
360       }
361       this.virtualDatabases.remove(virtualname);
362
363       // Send notification
364
if (MBeanServerManager.isJmxEnabled())
365       {
366         Hashtable JavaDoc databases = new Hashtable JavaDoc();
367         try
368         {
369           databases.put("backends", vdb.getAllBackendNames());
370         }
371         catch (VirtualDatabaseException e)
372         {
373           // ignore
374
}
375         RmiConnector.broadcastNotification(this,
376             CjdbcNotificationList.CONTROLLER_VIRTUALDATABASE_REMOVED,
377             CjdbcNotificationList.NOTIFICATION_LEVEL_INFO, Translate.get(
378                 "notification.virtualdatabase.removed", vdb
379                     .getVirtualDatabaseName()), databases);
380       }
381     }
382     return Translate.get("controller.removeVirtualDatabase.success",
383         virtualname);
384   }
385
386   //
387
// Controller operations
388
//
389

390   /**
391    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#addDriver(byte[])
392    */

393   public void addDriver(byte[] bytes) throws Exception JavaDoc
394   {
395     // Try to find drivers directory in the classpath
396
File JavaDoc driversDirectory = null;
397     URL JavaDoc url = Controller.class
398         .getResource(ControllerConstants.C_JDBC_DRIVER_JAR_FILE);
399     boolean error = false;
400     if (url != null)
401     {
402       driversDirectory = (new File JavaDoc(URLDecoder.decode(url.getFile())))
403           .getParentFile();
404       error = (driversDirectory == null) || !driversDirectory.exists();
405     }
406
407     if (error)
408     {
409       String JavaDoc msg = Translate.get("controller.driver.dir.not.found");
410       logger.error(msg);
411       throw new ControllerException(msg);
412     }
413
414     // Read the array of bytes to a file
415
File JavaDoc temp = null;
416     try
417     {
418       temp = File.createTempFile("driver", "zip", driversDirectory);
419       FileOutputStream JavaDoc output = new FileOutputStream JavaDoc(temp);
420       output.write(bytes);
421       output.close();
422     }
423     catch (IOException JavaDoc e)
424     {
425       String JavaDoc msg = Translate.get("controller.add.jar.read.failed", e);
426       logger.error(msg);
427       throw new ControllerException(msg);
428     }
429
430     // Unzip the file content
431
try
432     {
433       Enumeration JavaDoc entries;
434       ZipFile JavaDoc zipFile = new ZipFile JavaDoc(temp);
435
436       // Read the file
437
int lenght;
438       InputStream JavaDoc in;
439       BufferedOutputStream JavaDoc out;
440       byte[] buffer = new byte[1024];
441
442       entries = zipFile.entries();
443       while (entries.hasMoreElements())
444       {
445         ZipEntry JavaDoc entry = (ZipEntry JavaDoc) entries.nextElement();
446
447         if (entry.isDirectory())
448         {
449           // Create the directory
450
if (logger.isDebugEnabled())
451             logger.debug(Translate.get("controller.add.jar.extract.dir", entry
452                 .getName()));
453
454           (new File JavaDoc(driversDirectory, entry.getName())).mkdir();
455           continue;
456         }
457
458         // Extract the file
459
if (logger.isDebugEnabled())
460           logger.debug(Translate.get("controller.add.jar.extract.file", entry
461               .getName()));
462
463         in = zipFile.getInputStream(entry);
464         out = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(driversDirectory
465             + System.getProperty("file.separator") + entry.getName()));
466         while ((lenght = in.read(buffer)) >= 0)
467           out.write(buffer, 0, lenght);
468
469         in.close();
470         out.close();
471       }
472
473       zipFile.close();
474       temp.delete();
475       logger.info(Translate.get("controller.add.jar.to.directory",
476           driversDirectory.toString()));
477     }
478     catch (IOException JavaDoc e)
479     {
480       String JavaDoc msg = Translate.get("controller.driver.extract.failed", e);
481       logger.error(msg);
482       throw new ControllerException(msg);
483     }
484   }
485
486   /**
487    * Read a XML configuration file and load only the
488    * <code>VirtualDatabase</code> specified in the arguments list
489    *
490    * @param filename XML configuration file name to take info on
491    * <code>VirtualDatabase</code>
492    * @param virtualName the only database to load, null if should load all
493    * @param autoLoad specifies if the backends should be enabled automatically
494    * after loading
495    * @param checkPoint checkPoint to recover from when enabling backends. Leave
496    * <code>null</code> if no recovery option is needed.
497    * @return a diagnostic message (success or error)
498    * @throws Exception if an error occurs
499    */

500   public String JavaDoc loadXmlConfiguration(String JavaDoc filename, String JavaDoc virtualName,
501       int autoLoad, String JavaDoc checkPoint) throws Exception JavaDoc
502   {
503     FileReader JavaDoc fileReader = null;
504     try
505     {
506       filename = filename.trim();
507       try
508       {
509         fileReader = new FileReader JavaDoc(filename);
510       }
511       catch (FileNotFoundException JavaDoc fnf)
512       {
513         return Translate.get("controller.file.not.found", filename);
514       }
515
516       // Read the file
517
BufferedReader JavaDoc in = new BufferedReader JavaDoc(fileReader);
518       StringBuffer JavaDoc xml = new StringBuffer JavaDoc();
519       String JavaDoc line;
520       do
521       {
522         line = in.readLine();
523         if (line != null)
524           xml.append(line);
525       }
526       while (line != null);
527
528       // Send it to the controller
529
addVirtualDatabases(xml.toString(), virtualName, autoLoad, checkPoint);
530       return Translate.get("controller.file.send", filename);
531     }
532     catch (Exception JavaDoc e)
533     {
534       logger.error(Translate.get("controller.loadXml.failed", e), e);
535       throw new ControllerException(Translate.get("controller.loadXml.failed",
536           e));
537     }
538     finally
539     {
540       if (fileReader != null)
541         fileReader.close();
542     }
543   }
544
545   /**
546    * Save current configuration of the controller to a default file
547    *
548    * @return Status message
549    * @throws VirtualDatabaseException if an error occurs
550    * @see org.objectweb.cjdbc.controller.core.ControllerConstants#getSaveFile
551    */

552   public String JavaDoc saveConfiguration() throws VirtualDatabaseException
553   {
554     String JavaDoc msg = Translate.get("controller.save.configuration.failed");
555     try
556     {
557       String JavaDoc configurationFile = ControllerConstants
558           .getSaveFile(new SimpleDateFormat JavaDoc("yyyy-MM-dd-HH-mm")
559               .format(new Date JavaDoc()));
560       DataOutputStream JavaDoc dos = new DataOutputStream JavaDoc(new BufferedOutputStream JavaDoc(
561           new FileOutputStream JavaDoc(configurationFile)));
562       StringBuffer JavaDoc xml = new StringBuffer JavaDoc();
563       xml.append(XmlTools.prettyXml(getXmlVirtualDatabases()));
564       String JavaDoc prettyXml = xml.toString();
565       // ugly hack to insert the doctype which has been stripped
566
// when prettyfying the xml
567
prettyXml = XmlTools.insertCjdbcDoctype(prettyXml);
568       dos.write(prettyXml.getBytes());
569       dos.close();
570       msg = Translate.get("controller.save.configuration", configurationFile);
571     }
572     catch (Exception JavaDoc e)
573     {
574       msg = Translate.get("controller.save.configuration.failed", e);
575       logger.error(msg);
576     }
577     return msg;
578   }
579
580   //
581
// Controller shutdown
582
//
583
/**
584    * Create report about fatal error
585    *
586    * @param fatal the cause of the fatal error
587    */

588   public void endOfController(Exception JavaDoc fatal)
589   {
590     logger.fatal(Translate.get("fatal.error"));
591     if (report.isGenerateOnFatal())
592     {
593       new ReportManager(this, fatal).generate();
594       logger.info(Translate.get("fatal.report.generated", report
595           .getReportLocation()
596           + File.separator + ControllerConstants.REPORT_FILE));
597     }
598     Runtime.getRuntime().exit(1);
599   }
600
601   /**
602    * Access the connection thread. Need this for shutting down
603    *
604    * @return <code>connectionThread</code>
605    */

606   public ControllerServerThread getConnectionThread()
607   {
608     return connectionThread;
609   }
610
611   /**
612    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#isShuttingDown()
613    */

614   public boolean isShuttingDown()
615   {
616     return isShuttingDown;
617   }
618
619   /**
620    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#shutdown(int)
621    */

622   public void shutdown(int level) throws ControllerException
623   {
624     ControllerShutdownThread shutdownThread = null;
625     synchronized (this)
626     {
627       if (isShuttingDown())
628       {
629         logger.info(Translate.get("controller.already.shutting.down", this
630             .getControllerName()));
631         return;
632       }
633
634       if (isSecurityEnabled() && !security.getAllowConsoleShutdown())
635         throw new ControllerException(Translate
636             .get("controller.shutdown.refused"));
637
638       switch (level)
639       {
640         case Constants.SHUTDOWN_WAIT :
641           shutdownThread = new ControllerWaitShutdownThread(this);
642           logger.info(Translate.get("controller.shutdown.type.wait", this
643               .getControllerName()));
644           break;
645         case Constants.SHUTDOWN_SAFE :
646           isShuttingDown = true;
647           shutdownThread = new ControllerSafeShutdownThread(this);
648           logger.info(Translate.get("controller.shutdown.type.safe", this
649               .getControllerName()));
650           break;
651         case Constants.SHUTDOWN_FORCE :
652           isShuttingDown = true;
653           shutdownThread = new ControllerForceShutdownThread(this);
654           logger.warn(Translate.get("controller.shutdown.type.force", this
655               .getControllerName()));
656           break;
657         default :
658           String JavaDoc msg = Translate
659               .get("controller.shutdown.unknown.level", level);
660           logger.error(msg);
661           throw new RuntimeException JavaDoc(msg);
662       }
663     }
664
665     Thread JavaDoc thread = new Thread JavaDoc(shutdownThread.getShutdownGroup(),
666         shutdownThread, "Controller Shutdown Thread");
667     thread.start();
668
669     try
670     {
671       logger.info("Waiting for shutdown");
672       thread.join();
673       logger.info("Shutdown over");
674     }
675     catch (InterruptedException JavaDoc e)
676     {
677       e.printStackTrace();
678     }
679   }
680
681   /**
682    * Launches the C-JDBC controller and bind it with RMI registry. The available
683    * options are:
684    * <ul>
685    * <li><code>-h</code> or <code>--help</code> <code>&lt;port&gt;</code>:
686    * displays usage informations.</li>
687    * <li><code>-j</code> or <code>--jmx</code> <code>&lt;port&gt;</code>:
688    * optinal JMX server HTTP adaptor port number.</li>
689    * <li><code>-n</code> or <code>--name</code> <code>&lt;name&gt;</code>:
690    * optional controller name.</li>
691    * <li><code>-i</code> or <code>--ip</code> <code>&lt;ip&gt;</code>:
692    * optional IP address to beind the controller to.</li>
693    * <li><code>-r</code> or <code>--rmi</code> <code>&lt;port&gt;</code>:
694    * optional RMI registry port number.</li>
695    * <li><code>-v</code> or <code>--version</code>: displays version
696    * informations.</li>
697    * </ul>
698    * <p>
699    * The controller starts listening for socket connections on the default port.
700    * Jmx is configured, and a virtual database can be added.
701    * <p>
702    * {@link org.objectweb.cjdbc.controller.core.ControllerConstants#DEFAULT_PORT}
703    * Default Listening port
704    *
705    * @param args command line arguments (see above)
706    * @throws Exception when everything goes wrong
707    */

708   public static void main(String JavaDoc[] args) throws Exception JavaDoc
709   {
710     logger.info(getVersion());
711
712     System.setProperty("javax.management.builder.initial",
713         org.objectweb.cjdbc.controller.jmx.MBeanServerBuilder.class.getName());
714
715     ControllerFactory conf = new ControllerFactory(args);
716     Controller controller = conf.getController();
717     if (controller != null)
718       controller.launch();
719     else
720       throw new Exception JavaDoc(Translate.get("controller.configure.failed"));
721   }
722
723   /**
724    * Actively launch the <code>controller</code>. Add startup actions here to
725    * avoid them in <method>main </method>
726    */

727   public void launch()
728   {
729     connectionThread = new ControllerServerThread(this);
730     connectionThread.start();
731
732     SimpleDateFormat JavaDoc formatter = new SimpleDateFormat JavaDoc(
733         "yyyy.MM.dd ww 'at' hh:mm:ss a zzz");
734     Date JavaDoc day = new Date JavaDoc();
735     String JavaDoc date = formatter.format(day);
736     logger.info(Translate.get("controller.date", date));
737     logger.info(Translate.get("controller.ready", getControllerName()));
738   }
739
740   //
741
// Controller information
742
//
743

744   /**
745    * Returns the controller name.
746    *
747    * @return String
748    */

749   public String JavaDoc getControllerName()
750   {
751     return ipAddress + ":" + portNumber;
752   }
753
754   /**
755    * Get the IP address to bind the controller to
756    *
757    * @return the IP address
758    */

759   public String JavaDoc getIPAddress()
760   {
761     return ipAddress;
762   }
763
764   /**
765    * Set the IP address to bind the controller to
766    *
767    * @param ipAddress the IP address to use
768    */

769   public void setIPAddress(String JavaDoc ipAddress)
770   {
771     this.ipAddress = ipAddress;
772   }
773
774   /**
775    * Get the controller port number
776    *
777    * @return the port number
778    */

779   public int getPortNumber()
780   {
781     return portNumber;
782   }
783
784   /**
785    * Set the controller backlog size.
786    *
787    * @param port the port number to set
788    */

789   public void setPortNumber(int port)
790   {
791     portNumber = port;
792   }
793
794   /**
795    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#getBacklogSize()
796    */

797   public int getBacklogSize()
798   {
799     return backlogSize;
800   }
801
802   /**
803    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#setBacklogSize(int)
804    */

805   public void setBacklogSize(int size)
806   {
807     backlogSize = size;
808   }
809
810   /**
811    * Returns jmx enable
812    *
813    * @return jmxEnabled
814    */

815   public boolean getJmxEnable()
816   {
817     return MBeanServerManager.isJmxEnabled();
818   }
819
820   /**
821    * Return the jmx name of this controller (hostname:rmiport)
822    *
823    * @return jmx name
824    */

825   public String JavaDoc getJmxName()
826   {
827     if (getJmxEnable())
828     {
829       RmiConnector connector = ((RmiConnector) RmiConnector.getRmiConnectors()
830           .get(0));
831       return connector.getHostName() + ":" + connector.getPort();
832     }
833     else
834       return getControllerName();
835   }
836
837   /**
838    * set enable JMX
839    *
840    * @param enable true if jmx should be enable.
841    */

842   public void setJmxEnable(boolean enable)
843   {
844     configuration.put(ControllerFactory.JMX_ENABLE, "" + enable);
845   }
846
847   /**
848    * Returns Version as a long String
849    *
850    * @return version
851    */

852   public static String JavaDoc getVersion()
853   {
854     return Translate.get("controller.info", Constants.VERSION);
855   }
856
857   /**
858    * Get current configuration options
859    *
860    * @return configure a <code>Hashtable</code> with controller options
861    */

862   public Hashtable JavaDoc getConfiguration()
863   {
864     return configuration;
865   }
866
867   /**
868    * Check whether security is enabled or not
869    *
870    * @return true if there is not null controller security manager
871    */

872   public boolean isSecurityEnabled()
873   {
874     return security != null;
875   }
876
877   /**
878    * @return Returns the security.
879    */

880   public ControllerSecurityManager getSecurity()
881   {
882     return security;
883   }
884
885   /**
886    * @param security The security to set.
887    */

888   public void setSecurity(ControllerSecurityManager security)
889   {
890     this.security = security;
891   }
892
893   /**
894    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#generateReport()
895    */

896   public String JavaDoc generateReport() throws Exception JavaDoc
897   {
898     report.startReport();
899     return report.generate();
900   }
901   
902   /**
903    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#getLoggingConfiguration()
904    */

905   public String JavaDoc getLoggingConfiguration() throws Exception JavaDoc
906   {
907     return report.generate();
908   }
909
910   /**
911    * Sets the configuration value.
912    *
913    * @param configuration The configuration to set.
914    */

915   public void setConfiguration(Hashtable JavaDoc configuration)
916   {
917     this.configuration = configuration;
918   }
919
920   /**
921    * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#getVersionNumber()
922    */

923   public String JavaDoc getVersionNumber()
924   {
925     return Constants.VERSION;
926   }
927
928   /**
929    * @see org.objectweb.cjdbc.controller.jmx.AbstractStandardMBean#getAssociatedString()
930    */

931   public String JavaDoc getAssociatedString()
932   {
933     return "controller";
934   }
935
936   /**
937    * @see org.objectweb.cjdbc.common.xml.XmlComponent#getXml()
938    */

939   public String JavaDoc getXml()
940   {
941     try
942     {
943       String JavaDoc prettyXml = XmlTools.prettyXml(getXmlController());
944       return XmlTools.insertCjdbcControllerDoctype(prettyXml);
945     }
946     catch (Exception JavaDoc e)
947     {
948       logger.error(Translate.get("controller.xml.transformation.failed", e));
949       return e.getMessage();
950     }
951   }
952
953   /**
954    * Return the xml version of the controller.xml file without doc type
955    * declaration, just data.
956    *
957    * @return controller xml data
958    */

959   public String JavaDoc getXmlController()
960   {
961     StringBuffer JavaDoc info = new StringBuffer JavaDoc();
962     info.append("<C-JDBC-CONTROLLER>");
963     info.append("<" + ControllerXmlTags.ELT_CONTROLLER + " "
964         + ControllerXmlTags.ATT_CONTROLLER_IP + "=\"" + this.getIPAddress()
965         + "\" " + ControllerXmlTags.ATT_CONTROLLER_PORT + "=\""
966         + this.getPortNumber() + "\" " + ">");
967
968     info.append("<" + ControllerXmlTags.ELT_INTERNATIONALIZATION + " "
969         + ControllerXmlTags.ATT_LANGUAGE + "=\""
970         + Locale.getDefault().getLanguage() + "\"/>");
971
972     if (report.isReportEnabled())
973     {
974       info.append("<" + ControllerXmlTags.ELT_REPORT + " "
975           + ControllerXmlTags.ATT_REPORT_ENABLE_FILE_LOGGING + "=\""
976           + report.isEnableFileLogging() + "\" "
977           + ControllerXmlTags.ATT_REPORT_HIDE_SENSITIVE_DATA + "=\""
978           + report.isHideSensitiveData() + "\" "
979           + ControllerXmlTags.ATT_REPORT_GENERATE_ON_FATAL + "=\""
980           + report.isGenerateOnFatal() + "\" "
981           + ControllerXmlTags.ATT_REPORT_GENERATE_ON_SHUTDOWN + "=\""
982           + report.isGenerateOnShutdown() + "\" "
983           + ControllerXmlTags.ATT_REPORT_REPORT_LOCATION + "=\""
984           + report.getReportLocation() + "\" />");
985     }
986
987     if (getJmxEnable())
988     {
989       info.append("<" + ControllerXmlTags.ELT_JMX + ">");
990       if (configuration.containsKey(JmxConstants.ADAPTOR_TYPE_HTTP))
991       {
992         info.append("<" + ControllerXmlTags.ELT_HTTP_JMX_ADAPTOR + " "
993             + ControllerXmlTags.ATT_JMX_ADAPTOR_PORT + "=\""
994             + configuration.get(JmxConstants.ADAPTOR_TYPE_HTTP) + "\" />");
995       }
996       if (configuration.containsKey(JmxConstants.ADAPTOR_TYPE_RMI))
997       {
998         info.append("<" + ControllerXmlTags.ELT_RMI_JMX_ADAPTOR + " "
999             + ControllerXmlTags.ATT_JMX_ADAPTOR_PORT + "=\""
1000            + configuration.get(JmxConstants.ADAPTOR_TYPE_RMI) + "\" />");
1001      }
1002
1003      info.append("</" + ControllerXmlTags.ELT_JMX + ">");
1004    }
1005
1006    if (this.isSecurityEnabled())
1007      info.append(this.getSecurity().getXml());
1008    info.append("</" + ControllerXmlTags.ELT_CONTROLLER + ">");
1009    info.append("</C-JDBC-CONTROLLER>");
1010    return info.toString();
1011  }
1012
1013  /**
1014   * Same as above but for the virtual databases.
1015   *
1016   * @return xml virtual databases data.
1017   */

1018  public String JavaDoc getXmlVirtualDatabases()
1019  {
1020    try
1021    {
1022      StringBuffer JavaDoc info = new StringBuffer JavaDoc();
1023      info.append(XmlComponent.XML_VERSION);
1024      info.append("\n");
1025      info.append("<" + DatabasesXmlTags.ELT_CJDBC + ">");
1026      ArrayList JavaDoc vdbs = this.getVirtualDatabases();
1027      for (int i = 0, size = vdbs.size(); i < size; i++)
1028        info.append(((VirtualDatabase) vdbs.get(i)).getXml());
1029      info.append("</" + DatabasesXmlTags.ELT_CJDBC + ">");
1030      return info.toString();
1031    }
1032    catch (Exception JavaDoc e)
1033    {
1034      logger.error(e.getMessage(), e);
1035      return e.getMessage();
1036    }
1037  }
1038
1039  /**
1040   * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#generateLogReport()
1041   */

1042  public String JavaDoc generateLogReport() throws Exception JavaDoc
1043  {
1044    ReportManager logReport = new ReportManager(this, true);
1045    return logReport.generateJustLogs();
1046  }
1047
1048  //
1049
// Logging system
1050
//
1051

1052  /**
1053   * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#refreshLogConfiguration()
1054   */

1055  public void refreshLogConfiguration() throws ControllerException
1056  {
1057    try
1058    {
1059      LogManager.configure(URLDecoder.decode(this.getClass().getResource(
1060          ControllerConstants.LOG4J_RESOURCE).getFile()));
1061      if (logger.isDebugEnabled())
1062        logger.info(Translate.get("controller.refresh.log.success"));
1063    }
1064    catch (Exception JavaDoc e)
1065    {
1066      throw new ControllerException(Translate
1067          .get("controller.logconfigfile.not.found"));
1068    }
1069  }
1070
1071  /**
1072   * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#updateLogConfigurationFile(java.lang.String)
1073   */

1074  public void updateLogConfigurationFile(String JavaDoc newConfiguration)
1075      throws IOException JavaDoc, ControllerException
1076  {
1077    File JavaDoc logFile = new File JavaDoc(URLDecoder.decode(getClass().getResource(
1078        ControllerConstants.LOG4J_RESOURCE).getFile()));
1079    BufferedWriter JavaDoc writer = new BufferedWriter JavaDoc(new FileWriter JavaDoc(logFile));
1080    writer.write(newConfiguration);
1081    writer.flush();
1082    writer.close();
1083    refreshLogConfiguration();
1084  }
1085
1086  /**
1087   * @see org.objectweb.cjdbc.common.jmx.mbeans.ControllerMBean#viewLogConfigurationFile()
1088   */

1089  public String JavaDoc viewLogConfigurationFile() throws IOException JavaDoc
1090  {
1091    File JavaDoc logFile = new File JavaDoc(URLDecoder.decode(getClass().getResource(
1092        ControllerConstants.LOG4J_RESOURCE).getFile()));
1093    BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new FileReader JavaDoc(logFile));
1094    StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
1095    String JavaDoc line;
1096    while ((line = reader.readLine()) != null)
1097      buffer.append(line + System.getProperty("line.separator"));
1098    reader.close();
1099    return buffer.toString();
1100  }
1101
1102  /**
1103   * Returns the report value.
1104   *
1105   * @return Returns the report.
1106   */

1107  public ReportManager getReport()
1108  {
1109    return report;
1110  }
1111
1112  /**
1113   * Sets the report value.
1114   *
1115   * @param report The report to set.
1116   */

1117  public void setReport(ReportManager report)
1118  {
1119    this.report = report;
1120  }
1121}
Popular Tags