KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > xml > ControllerParser


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: sequoia@continuent.org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Initial developer(s): Emmanuel Cecchet.
20  * Contributor(s): Mathieu Peltier, Sara Bouchenak.
21  */

22
23 package org.continuent.sequoia.controller.xml;
24
25 import java.io.BufferedReader JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileReader JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.io.StringReader JavaDoc;
31 import java.net.InetAddress JavaDoc;
32 import java.net.URL JavaDoc;
33 import java.net.URLDecoder JavaDoc;
34 import java.util.ArrayList JavaDoc;
35
36 import org.continuent.sequoia.common.i18n.Translate;
37 import org.continuent.sequoia.common.log.Trace;
38 import org.continuent.sequoia.common.net.SSLConfiguration;
39 import org.continuent.sequoia.common.xml.ControllerXmlTags;
40 import org.continuent.sequoia.common.xml.XmlValidator;
41 import org.continuent.sequoia.controller.core.Controller;
42 import org.continuent.sequoia.controller.core.ControllerConfiguration;
43 import org.continuent.sequoia.controller.core.ControllerConstants;
44 import org.continuent.sequoia.controller.core.ReportManager;
45 import org.xml.sax.Attributes JavaDoc;
46 import org.xml.sax.InputSource JavaDoc;
47 import org.xml.sax.SAXException JavaDoc;
48 import org.xml.sax.SAXParseException JavaDoc;
49 import org.xml.sax.XMLReader JavaDoc;
50 import org.xml.sax.helpers.DefaultHandler JavaDoc;
51 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
52
53 /**
54  * Allows to parse an XML content containing the description of the controller
55  * confirming to sequoia-controller.dtd.
56  *
57  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
58  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
59  * @version 1.0
60  */

61 public class ControllerParser extends DefaultHandler JavaDoc
62 {
63   /** Logger instance. */
64   static Trace logger = Trace
65                                                     .getLogger(ControllerParser.class
66                                                         .getName());
67   static Trace endUserLogger = Trace
68                                                     .getLogger("org.continuent.sequoia.enduser");
69
70   /** XML parser. */
71   private XMLReader JavaDoc parser;
72
73   /** Sequoia controller to setup. */
74   private ControllerConfiguration config;
75   private Controller controller;
76   private SSLConfiguration ssl;
77   private String JavaDoc controllerIP;
78   private ReportManager reportManager;
79
80   /**
81    * Creates a new <code>ControllerParser</code> instance. This method
82    * Instanciates also a new <code>ControllerHandler</code>.
83    *
84    * @param configure a <code>ControllerConfiguration</code> object that
85    * contains the configuration to update with values from xml parsing
86    * @throws Exception i private String doctype; f an error occurs
87    */

88   public ControllerParser(ControllerConfiguration configure) throws Exception JavaDoc
89   {
90     this.config = configure;
91     this.controller = configure.getController();
92
93     // Instantiate a new parser
94
parser = XMLReaderFactory.createXMLReader();
95
96     // Activate validation
97
parser.setFeature("http://xml.org/sax/features/validation", true);
98
99     // Install error handler
100
parser.setErrorHandler(this);
101
102     // Install document handler
103
parser.setContentHandler(this);
104
105     // Install local entity resolver
106
parser.setEntityResolver(this);
107   }
108
109   /**
110    * Parses an XML content according to SEQUOIA-CONTROLLER DTD.
111    *
112    * @param xml a <code>String</code> containing the XML content to parse
113    * @exception SAXException if an error occurs
114    * @exception IOException if an error occurs
115    */

116   public void readXML(String JavaDoc xml) throws IOException JavaDoc, SAXException JavaDoc
117   {
118     if (xml != null)
119     {
120       InputSource JavaDoc input = new InputSource JavaDoc(new StringReader JavaDoc(xml));
121       parser.parse(input);
122     }
123     else
124       throw new IOException JavaDoc("Input was null in input source.");
125   }
126
127   /**
128    * Parses an XML formatted string according to SEQUOIA-CONTROLLER DTD.
129    *
130    * @param xml a <code>String</code> reference to the xml to parse
131    * @param validateBeforeParsing if validation should be checked before parsing
132    * @exception SAXException if an error occurs
133    * @exception IOException if an error occurs
134    */

135   public void readXML(String JavaDoc xml, boolean validateBeforeParsing)
136       throws IOException JavaDoc, SAXException JavaDoc
137   {
138     if (validateBeforeParsing)
139     {
140       XmlValidator validator = new XmlValidator(
141           ControllerConstants.SEQUOIA_CONTROLLER_DTD_FILE, xml.toString());
142       if (logger.isDebugEnabled())
143       {
144         if (validator.isDtdValid())
145           logger.debug(Translate.get("controller.xml.dtd.validated"));
146         if (validator.isXmlValid())
147           logger.debug(Translate.get("controller.xml.document.validated"));
148       }
149
150       if (validator.getWarnings().size() > 0)
151       {
152         ArrayList JavaDoc warnings = validator.getWarnings();
153         for (int i = 0; i < warnings.size(); i++)
154           logger.warn(Translate.get("virtualdatabase.xml.parsing.warning",
155               warnings.get(i)));
156       }
157
158       if (!validator.isDtdValid())
159         logger.error(Translate.get("controller.xml.dtd.not.validated"));
160       if (!validator.isXmlValid())
161         logger.error(Translate.get("controller.xml.document.not.validated"));
162
163       ArrayList JavaDoc errors = validator.getExceptions();
164       for (int i = 0; i < errors.size(); i++)
165         logger.error(((Exception JavaDoc) errors.get(i)).getMessage());
166
167       if (!validator.isValid())
168         throw new SAXException JavaDoc(Translate
169             .get("controller.xml.document.not.valid"));
170     }
171     readXML(xml);
172   }
173
174   /**
175    * Parses an XML formatted file according to SEQUOIA-CONTROLLER DTD.
176    *
177    * @param fileReader a <code>FileReader</code> reference to the xml to parse
178    * @param validateBeforeParsing if validation should be checked before parsing
179    * @exception SAXException if an error occurs
180    * @exception IOException if an error occurs
181    */

182   public void readXML(FileReader JavaDoc fileReader, boolean validateBeforeParsing)
183       throws IOException JavaDoc, SAXException JavaDoc
184   {
185     if (fileReader != null)
186     {
187
188       // Read the file
189
BufferedReader JavaDoc in = new BufferedReader JavaDoc(fileReader);
190       StringBuffer JavaDoc xml = new StringBuffer JavaDoc();
191       String JavaDoc line;
192       do
193       {
194         line = in.readLine();
195         if (line != null)
196           xml.append(line);
197       }
198       while (line != null);
199
200       readXML(xml.toString(), validateBeforeParsing);
201     }
202     else
203     {
204       throw new IOException JavaDoc("Input was null in input source.");
205     }
206   }
207
208   /**
209    * Handles notification of a non-recoverable parser error.
210    *
211    * @param e the warning information encoded as an exception.
212    * @exception SAXException any SAX exception, possibly wrapping another
213    * exception.
214    */

215   public void fatalError(SAXParseException JavaDoc e) throws SAXException JavaDoc
216   {
217     String JavaDoc msg = Translate.get("controller.xml.parsing.fatal", new String JavaDoc[]{
218         e.getPublicId(), String.valueOf(e.getLineNumber()),
219         String.valueOf(e.getColumnNumber()), e.getMessage()});
220     logger.error(msg);
221     endUserLogger.fatal(msg);
222     throw e;
223   }
224
225   /**
226    * Handles notification of a recoverable parser error.
227    *
228    * @param e the warning information encoded as an exception.
229    * @exception SAXException any SAX exception, possibly wrapping another
230    * exception
231    */

232   public void error(SAXParseException JavaDoc e) throws SAXException JavaDoc
233   {
234     logger.error(Translate.get("controller.xml.parsing.error", new String JavaDoc[]{
235         e.getPublicId(), String.valueOf(e.getLineNumber()),
236         String.valueOf(e.getColumnNumber()), e.getMessage()}));
237     throw e;
238   }
239
240   /**
241    * Allows to parse the document with a local copy of the DTD whatever the
242    * original <code>DOCTYPE</code> found. Warning, this method is called only
243    * if the XML document contains a <code>DOCTYPE</code>.
244    *
245    * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String,
246    * java.lang.String)
247    */

248   public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
249       throws SAXException JavaDoc
250   {
251     logger.debug(Translate.get("controller.xml.dtd.using",
252         ControllerConstants.SEQUOIA_CONTROLLER_DTD_FILE));
253     InputStream JavaDoc stream = ControllerParser.class.getResourceAsStream("/"
254         + ControllerConstants.SEQUOIA_CONTROLLER_DTD_FILE);
255     if (stream == null)
256     {
257       throw new SAXException JavaDoc(Translate.get(
258           "controller.xml.dtd.not.found",
259           ControllerConstants.PRODUCT_NAME,
260           ControllerConstants.SEQUOIA_CONTROLLER_DTD_FILE));
261     }
262
263     return new InputSource JavaDoc(stream);
264   }
265
266   /**
267    * Initializes parsing of a document.
268    *
269    * @exception SAXException unspecialized error
270    */

271   public void startDocument() throws SAXException JavaDoc
272   {
273     logger.debug(Translate.get("controller.xml.parsing.document"));
274   }
275
276   /**
277    * Finalizes parsing of a document.
278    *
279    * @exception SAXException unspecialized error
280    */

281   public void endDocument() throws SAXException JavaDoc
282   {
283     logger.info(Translate.get("controller.xml.done"));
284   }
285
286   /**
287    * Analyzes an element first line.
288    *
289    * @param uri name space URI
290    * @param localName local name
291    * @param name element raw name
292    * @param atts element attributes
293    * @exception SAXException if an error occurs
294    */

295   public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc name,
296       Attributes JavaDoc atts) throws SAXException JavaDoc
297   {
298     logger.debug(Translate.get("controller.xml.parsing.start", name));
299     if (name.equalsIgnoreCase(ControllerXmlTags.ELT_CONTROLLER))
300       configureController(atts);
301     else if (name.equalsIgnoreCase(ControllerXmlTags.ELT_REPORT))
302       configureReport(atts);
303     else if (name.equalsIgnoreCase(ControllerXmlTags.ELT_JMX))
304       configureRmiJmxAdaptor(atts);
305     else if (name.equalsIgnoreCase(ControllerXmlTags.ELT_SSL))
306       configureSSL(atts);
307     else if (name.equalsIgnoreCase(ControllerXmlTags.ELT_VIRTUAL_DATABASE))
308       configureVirtualDatabase(atts);
309   }
310
311   /**
312    * DatabasesParser for end of element.
313    *
314    * @param uri name space URI
315    * @param localName local name
316    * @param name element raw name
317    * @exception SAXException if an error occurs
318    */

319   public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc name)
320       throws SAXException JavaDoc
321   {
322     // We need information on what configuration are for jmx
323
if (name.equalsIgnoreCase(ControllerXmlTags.ELT_JMX))
324     {
325       config.setUpJmx(ssl);
326       ssl = null;
327     }
328
329     if (name.equalsIgnoreCase(ControllerXmlTags.ELT_CONTROLLER))
330     {
331       if (ssl != null)
332       {
333         // Setup SSL for JDBC connections
334
controller.setSslConfiguration(ssl);
335       }
336
337       // Be sure no settings are used for report
338
if (reportManager == null)
339       {
340         reportManager = new ReportManager(controller);
341         reportManager.setSettings(null);
342         controller.setReport(reportManager);
343       }
344     }
345     logger.debug(Translate.get("controller.xml.parsing.end", name));
346   }
347
348   /**
349    * Configure a <code>ControllerXmlTags.ELT_CONTROLLER</code> element.
350    *
351    * @param atts the parser attributes
352    * @throws SAXException if an error occurs
353    */

354   private void configureController(Attributes JavaDoc atts) throws SAXException JavaDoc
355   {
356     // warning: this code is insanely complex, but in the end it does little
357
try
358     {
359       String JavaDoc controllerPort = atts
360           .getValue(ControllerXmlTags.ATT_CONTROLLER_PORT);
361       if (controllerPort == null)
362         config.put(ControllerXmlTags.ATT_CONTROLLER_PORT, String
363             .valueOf(ControllerConstants.DEFAULT_PORT));
364       else
365         config.put(ControllerXmlTags.ATT_CONTROLLER_PORT, controllerPort);
366       config.getController().setJdbcPortNumber(
367           Integer.parseInt((String JavaDoc) config
368               .get(ControllerXmlTags.ATT_CONTROLLER_PORT)));
369
370       controllerIP = atts.getValue(ControllerXmlTags.ATT_CONTROLLER_IP);
371       if (controllerIP == null)
372       {
373         try
374         {
375           /**
376            * leaving "null" would be ok for
377            *
378            * @see org.continuent.sequoia.controller.core.ControllerServerThread#ControllerServerThread(Controller)
379            * but JMX/RMI naming scheme would not like it, so we use
380            * getLocalHost().getHostAddress() as a pseudo-empty/default
381            * value.
382            */

383           String JavaDoc localIP = InetAddress.getLocalHost().getHostAddress();
384           config.put(ControllerXmlTags.ATT_CONTROLLER_IP, localIP);
385         }
386         catch (RuntimeException JavaDoc e1)
387         {
388           logger
389               .warn("Unable to obtain IP address of controller, setting default address: "
390                   + ControllerConstants.DEFAULT_IP);
391           config.put(ControllerXmlTags.ATT_CONTROLLER_IP,
392               ControllerConstants.DEFAULT_IP);
393         }
394       }
395       else
396         config.put(ControllerXmlTags.ATT_CONTROLLER_IP, controllerIP);
397       config.getController().setIPAddress(
398           (String JavaDoc) config.get(ControllerXmlTags.ATT_CONTROLLER_IP));
399
400       String JavaDoc name = atts.getValue(ControllerXmlTags.ATT_CONTROLLER_NAME);
401       // setControllerName() will substitute name==null by something else
402
config.getController().setControllerName(name);
403       config.put(ControllerXmlTags.ATT_CONTROLLER_NAME, config.getController()
404           .getControllerName());
405
406       String JavaDoc controllerBacklog = atts
407           .getValue(ControllerXmlTags.ATT_BACKLOG_SIZE);
408       if (controllerBacklog == null)
409         config.put(ControllerXmlTags.ATT_BACKLOG_SIZE, String
410             .valueOf(ControllerConstants.DEFAULT_BACKLOG_SIZE));
411       else
412         config.put(ControllerXmlTags.ATT_BACKLOG_SIZE, controllerBacklog);
413       config.getController().setBacklogSize(
414           Integer.parseInt((String JavaDoc) config
415               .get(ControllerXmlTags.ATT_BACKLOG_SIZE)));
416
417       config.put(ControllerXmlTags.ATT_ALLOW_ADDITIONAL_DRIVER, atts
418           .getValue(ControllerXmlTags.ATT_ALLOW_ADDITIONAL_DRIVER));
419     }
420     catch (Exception JavaDoc e)
421     {
422       logger.warn("Error while configuring controller", e);
423       throw new SAXException JavaDoc(e.getMessage());
424     }
425   }
426
427   /**
428    * Configure a <code>ControllerXmlTags.ELT_REPORT</code> element.
429    *
430    * @param atts the parser attributes
431    */

432   private void configureReport(Attributes JavaDoc atts)
433   {
434     config.put(ControllerXmlTags.ATT_REPORT_ENABLED, "true");
435     config.put(ControllerXmlTags.ATT_REPORT_HIDE_SENSITIVE_DATA, atts
436         .getValue(ControllerXmlTags.ATT_REPORT_HIDE_SENSITIVE_DATA));
437     config.put(ControllerXmlTags.ATT_REPORT_GENERATE_ON_SHUTDOWN, atts
438         .getValue(ControllerXmlTags.ATT_REPORT_GENERATE_ON_SHUTDOWN));
439     config.put(ControllerXmlTags.ATT_REPORT_GENERATE_ON_FATAL, atts
440         .getValue(ControllerXmlTags.ATT_REPORT_GENERATE_ON_FATAL));
441     config.put(ControllerXmlTags.ATT_REPORT_DELETE_ON_SHUTDOWN, atts
442         .getValue(ControllerXmlTags.ATT_REPORT_DELETE_ON_SHUTDOWN));
443     String JavaDoc reportLocation = atts
444         .getValue(ControllerXmlTags.ATT_REPORT_REPORT_LOCATION);
445
446     if ((reportLocation == null) || reportLocation.equals(""))
447     {
448       reportLocation = System.getProperty("sequoia.log");
449       if (reportLocation == null)
450         reportLocation = ".";
451     }
452     config.put(ControllerXmlTags.ATT_REPORT_REPORT_LOCATION, reportLocation);
453
454     config.put(ControllerXmlTags.ATT_REPORT_ENABLE_FILE_LOGGING, atts
455         .getValue(ControllerXmlTags.ATT_REPORT_ENABLE_FILE_LOGGING));
456     reportManager = new ReportManager(controller);
457     reportManager.setSettings(config);
458     controller.setReport(reportManager);
459   }
460
461   /**
462    * Configure a <code>ControllerXmlTags.ELT_RMI_JMX_ADAPTOR</code> element.
463    *
464    * @param atts the parser attributes
465    */

466   private void configureRmiJmxAdaptor(Attributes JavaDoc atts)
467   {
468     config.put(ControllerXmlTags.ATT_JMX_ADAPTOR_IP, atts
469         .getValue(ControllerXmlTags.ATT_JMX_ADAPTOR_IP));
470     config.put(ControllerXmlTags.ATT_JMX_ADAPTOR_PORT, atts
471         .getValue(ControllerXmlTags.ATT_JMX_ADAPTOR_PORT));
472
473     String JavaDoc username = atts
474         .getValue(ControllerXmlTags.ATT_JMX_CONNECTOR_USERNAME);
475     String JavaDoc password = atts
476         .getValue(ControllerXmlTags.ATT_JMX_CONNECTOR_PASSWORD);
477     if (username != null)
478       config.put(ControllerXmlTags.ATT_JMX_CONNECTOR_USERNAME, username);
479     if (password != null)
480       config.put(ControllerXmlTags.ATT_JMX_CONNECTOR_PASSWORD, password);
481   }
482
483   /**
484    * Configure a <code>ControllerXmlTags.ELT_SSL</code> element.
485    *
486    * @param atts the parser attributes
487    */

488   private void configureSSL(Attributes JavaDoc atts)
489   {
490     ssl = new SSLConfiguration();
491     String JavaDoc keyStore = atts.getValue(ControllerXmlTags.ATT_SSL_KEYSTORE);
492     String JavaDoc keyStorePassword = atts
493         .getValue(ControllerXmlTags.ATT_SSL_KEYSTORE_PASSWORD);
494     String JavaDoc keyStoreKeyPassword = atts
495         .getValue(ControllerXmlTags.ATT_SSL_KEYSTORE_KEYPASSWORD);
496     String JavaDoc trustStore = atts.getValue(ControllerXmlTags.ATT_SSL_TRUSTSTORE);
497     String JavaDoc trustStorePassword = atts
498         .getValue(ControllerXmlTags.ATT_SSL_TRUSTSTORE_PASSWORD);
499     ssl.setKeyStore(new File JavaDoc(keyStore));
500
501     // Sanity checks, default to SSL_KEYSTORE values
502
if (keyStoreKeyPassword == null)
503       keyStoreKeyPassword = keyStorePassword;
504     if (trustStore == null)
505       trustStore = keyStore;
506     if (trustStorePassword == null)
507       trustStorePassword = keyStorePassword;
508
509     ssl.setKeyStorePassword(keyStorePassword);
510     ssl.setKeyStoreKeyPassword(keyStoreKeyPassword);
511     ssl.setClientAuthenticationRequired("true".equals(atts
512         .getValue(ControllerXmlTags.ATT_SSL_NEED_CLIENT_AUTH)));
513     ssl.setTrustStore(new File JavaDoc(trustStore));
514     ssl.setTrustStorePassword(trustStorePassword);
515   }
516
517   /**
518    * Configure a <code>ControllerXmlTags.ELT_VIRTUAL_DATABASE</code> element.
519    *
520    * @param atts the parser attributes
521    * @throws SAXException if an error occurs
522    */

523   private void configureVirtualDatabase(Attributes JavaDoc atts) throws SAXException JavaDoc
524   {
525     String JavaDoc virtualName = atts
526         .getValue(ControllerXmlTags.ATT_VIRTUAL_DATABASE_NAME);
527     String JavaDoc file = atts.getValue(ControllerXmlTags.ATT_VIRTUAL_DATABASE_FILE);
528
529     // Try to find the file on the path (usually config directory) if no file
530
// separator is found
531
if (file.indexOf(File.separator) == -1)
532     {
533       try
534       {
535         URL JavaDoc url = this.getClass().getResource("/" + file);
536         file = url.getFile();
537         logger.info(Translate.get("controller.configure.using", file));
538       }
539       catch (Exception JavaDoc e)
540       {
541         throw new SAXException JavaDoc(Translate.get(
542             "controller.configure.file.not.found", file));
543       }
544     }
545
546     file = URLDecoder.decode(file);
547
548     File JavaDoc checkExist = new File JavaDoc(file);
549     if (checkExist.exists() == false)
550       throw new SAXException JavaDoc(Translate.get(
551           "controller.configure.file.not.found", file));
552
553     int autoLoad = -1;
554     String JavaDoc autoLoadString = atts
555         .getValue(ControllerXmlTags.ATT_VIRTUAL_DATABASE_AUTO_ENABLE);
556
557     if (autoLoadString.equalsIgnoreCase(ControllerXmlTags.VAL_true))
558       autoLoad = ControllerConstants.AUTO_ENABLE_TRUE;
559     else
560       autoLoad = ControllerConstants.AUTO_ENABLE_FALSE;
561
562     logger.info(Translate.get("controller.configure.setup", new String JavaDoc[]{
563         virtualName, String.valueOf(autoLoad)}));
564     config.setUpVirtualDatabase(file, virtualName, autoLoad);
565   }
566
567 }
Popular Tags