KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > broker > metadata > RepositoryPersistor


1 package org.apache.ojb.broker.metadata;
2
3 /* Copyright 2002-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import javax.xml.parsers.ParserConfigurationException JavaDoc;
19 import javax.xml.parsers.SAXParser JavaDoc;
20 import javax.xml.parsers.SAXParserFactory JavaDoc;
21 import java.io.File JavaDoc;
22 import java.io.FileInputStream JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.OutputStream JavaDoc;
27 import java.io.PrintWriter JavaDoc;
28 import java.net.MalformedURLException JavaDoc;
29 import java.net.URL JavaDoc;
30 import java.net.URLConnection JavaDoc;
31 import java.util.Date JavaDoc;
32
33 import org.apache.commons.lang.SerializationUtils;
34 import org.apache.commons.lang.SystemUtils;
35 import org.apache.ojb.broker.util.ClassHelper;
36 import org.apache.ojb.broker.util.configuration.Configurable;
37 import org.apache.ojb.broker.util.configuration.Configuration;
38 import org.apache.ojb.broker.util.configuration.ConfigurationException;
39 import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
40 import org.apache.ojb.broker.util.logging.Logger;
41 import org.apache.ojb.broker.util.logging.LoggerFactory;
42 import org.xml.sax.ContentHandler JavaDoc;
43 import org.xml.sax.ErrorHandler JavaDoc;
44 import org.xml.sax.InputSource JavaDoc;
45 import org.xml.sax.SAXException JavaDoc;
46 import org.xml.sax.SAXParseException JavaDoc;
47 import org.xml.sax.XMLReader JavaDoc;
48
49 /**
50  * This class is responsible for reading and writing DescriptorRepository objects
51  * from and to persistent media.
52  * Currently only XML file based persistence is supported.
53  *
54  * @author <a HREF="mailto:thma@apache.org">Thomas Mahler<a>
55  * @author <a HREF="mailto:armin@codeAuLait.de">Armin Waibel</a>
56  * @version $Id: RepositoryPersistor.java,v 1.24.2.4 2005/12/21 22:26:11 tomdz Exp $
57  */

58 public class RepositoryPersistor implements Configurable
59 {
60     // TODO: Refactoring of the metadata reading/handling?
61

62     private static Logger log = LoggerFactory.getLogger(RepositoryPersistor.class);
63
64     private static final String JavaDoc SER_FILE_SUFFIX = "serialized";
65     private static final String JavaDoc SERIALIZED_REPOSITORY_PATH = "serializedRepositoryPath";
66
67     private boolean useSerializedRepository = false;
68
69     public RepositoryPersistor()
70     {
71         OjbConfigurator.getInstance().configure(this);
72     }
73
74     public void configure(Configuration pConfig) throws ConfigurationException JavaDoc
75     {
76         useSerializedRepository = ((MetadataConfiguration) pConfig).useSerializedRepository();
77     }
78
79     /**
80      * Write the {@link DescriptorRepository} to the given output object.
81      */

82     public void writeToFile(DescriptorRepository repository, ConnectionRepository conRepository, OutputStream JavaDoc out)
83     {
84         RepositoryTags tags = RepositoryTags.getInstance();
85         try
86         {
87             if (log.isDebugEnabled())
88                 log.debug("## Write repository file ##" +
89                         repository.toXML() +
90                         "## End of repository file ##");
91
92
93             String JavaDoc eol = SystemUtils.LINE_SEPARATOR;
94             StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
95             // 1. write XML header
96
buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + eol);
97
98             buf.append("<!DOCTYPE descriptor-repository SYSTEM \"repository.dtd\" >" + eol + eol);
99 // strReturn += "<!DOCTYPE descriptor-repository SYSTEM \"repository.dtd\" [" + eol;
100
// strReturn += "<!ENTITY database-metadata SYSTEM \""+ConnectionRepository.DATABASE_METADATA_FILENAME+"\">" + eol;
101
// strReturn += "<!ENTITY user SYSTEM \"repository_user.xml\">" + eol;
102
// strReturn += "<!ENTITY junit SYSTEM \"repository_junit.xml\">" + eol;
103
// strReturn += "<!ENTITY internal SYSTEM \"repository_internal.xml\"> ]>" + eol + eol;
104

105             buf.append("<!-- OJB RepositoryPersistor generated this file on " + new Date JavaDoc().toString() + " -->" + eol);
106
107             buf.append(tags.getOpeningTagNonClosingById(RepositoryElements.MAPPING_REPOSITORY) + eol);
108             buf.append(" " + tags.getAttribute(RepositoryElements.REPOSITORY_VERSION, DescriptorRepository.getVersion()) + eol);
109             buf.append(" " + tags.getAttribute(RepositoryElements.ISOLATION_LEVEL, repository.getIsolationLevelAsString()) + eol);
110             buf.append(">" + eol);
111
112             if(conRepository != null) buf.append(eol + eol + conRepository.toXML() + eol + eol);
113             if(repository != null) buf.append(repository.toXML());
114
115             buf.append(tags.getClosingTagById(RepositoryElements.MAPPING_REPOSITORY));
116
117             PrintWriter JavaDoc pw = new PrintWriter JavaDoc(out);
118             pw.print(buf.toString());
119             pw.flush();
120             pw.close();
121         }
122         catch (Exception JavaDoc e)
123         {
124             log.error("Could not write to output stream" + out, e);
125         }
126     }
127
128     /**
129      * Read the repository configuration file.
130      * <br>
131      * If configuration property <code>useSerializedRepository</code> is <code>true</code>
132      * all subsequent calls read a serialized version of the repository.
133      * The directory where the serialized repository is stored can be specified
134      * with the <code>serializedRepositoryPath</code> entry in OJB.properties.
135      * Once a serialized repository is found changes to repository.xml will be
136      * ignored. To force consideration of these changes the serialized repository
137      * must be deleted manually.
138      */

139     public DescriptorRepository readDescriptorRepository(String JavaDoc filename)
140             throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
141     {
142         DescriptorRepository result;
143         if (useSerializedRepository)
144         // use serialized repository
145
{
146             // build File object pointing to serialized repository location
147
Configuration config = OjbConfigurator.getInstance().getConfigurationFor(null);
148             String JavaDoc pathPrefix = config.getString(SERIALIZED_REPOSITORY_PATH, ".");
149             File JavaDoc serFile = new File JavaDoc(pathPrefix + File.separator + filename + "." + SER_FILE_SUFFIX);
150
151             if (serFile.exists() && serFile.length() > 0)
152             // if file exists load serialized version of repository
153
{
154                 try
155                 {
156                     long duration = System.currentTimeMillis();
157                     result = deserialize(serFile);
158                     log.info("Read serialized repository in " + (System.currentTimeMillis() - duration) + " ms");
159                 }
160                 catch (Exception JavaDoc e)
161                 {
162                     log.error("error in loading serialized repository. Will try to use XML version.", e);
163                     result = (DescriptorRepository) buildRepository(filename, DescriptorRepository.class);
164                 }
165             }
166             else
167             // if no serialized version exists, read it from xml and write serialized file
168
{
169                 long duration = System.currentTimeMillis();
170                 result = (DescriptorRepository) buildRepository(filename, DescriptorRepository.class);
171                 log.info("Read repository from file took " + (System.currentTimeMillis() - duration) + " ms");
172                 serialize(result, serFile);
173             }
174         }
175         // don't use serialized repository
176
else
177         {
178             long duration = System.currentTimeMillis();
179             result = (DescriptorRepository) buildRepository(filename, DescriptorRepository.class);
180             log.info("Read class descriptors took " + (System.currentTimeMillis() - duration) + " ms");
181         }
182         return result;
183     }
184
185     public DescriptorRepository readDescriptorRepository(InputStream JavaDoc inst)
186             throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
187     {
188         long duration = System.currentTimeMillis();
189         InputSource JavaDoc inSource = new InputSource JavaDoc(inst);
190         DescriptorRepository result = (DescriptorRepository) readMetadataFromXML(inSource, DescriptorRepository.class);
191         log.info("Read class descriptors took " + (System.currentTimeMillis() - duration) + " ms");
192         return result;
193     }
194
195     /**
196      * Read the repository configuration file and extract connection handling information.
197      */

198     public ConnectionRepository readConnectionRepository(String JavaDoc filename)
199             throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
200     {
201         long duration = System.currentTimeMillis();
202         ConnectionRepository result = (ConnectionRepository) buildRepository(filename, ConnectionRepository.class);
203         log.info("Read connection repository took " + (System.currentTimeMillis() - duration) + " ms");
204         return result;
205     }
206
207     /**
208      * Read the repository configuration file and extract connection handling information.
209      */

210     public ConnectionRepository readConnectionRepository(InputStream JavaDoc inst)
211             throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
212     {
213         long duration = System.currentTimeMillis();
214         InputSource JavaDoc inSource = new InputSource JavaDoc(inst);
215         ConnectionRepository result = (ConnectionRepository) readMetadataFromXML(inSource, ConnectionRepository.class);
216         log.info("Read connection repository took " + (System.currentTimeMillis() - duration) + " ms");
217         return result;
218     }
219
220     protected DescriptorRepository deserialize(File JavaDoc serFile)
221     {
222         DescriptorRepository result = null;
223         try
224         {
225             FileInputStream JavaDoc fis = new FileInputStream JavaDoc(serFile);
226             // deserialize repository
227
result = (DescriptorRepository) SerializationUtils.deserialize(fis);
228         }
229         catch (Exception JavaDoc e)
230         {
231             log.error("Deserialisation failed, using input path: " + serFile.getAbsolutePath(), e);
232         }
233         return result;
234     }
235
236     protected void serialize(DescriptorRepository repository, File JavaDoc file)
237     {
238         try
239         {
240             FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(file);
241             // serialize repository
242
SerializationUtils.serialize(repository, fos);
243         }
244         catch (Exception JavaDoc e)
245         {
246             log.error("Serialization failed, using output path: " + file.getAbsolutePath(), e);
247         }
248     }
249
250     /**
251      *
252      * TODO: We should re-design the configuration file reading
253      */

254     private Object JavaDoc buildRepository(String JavaDoc repositoryFileName, Class JavaDoc targetRepository)
255             throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
256     {
257         URL JavaDoc url = buildURL(repositoryFileName);
258         /*
259         arminw:
260         strange, when using 'url.openStream()' argument repository
261         could not be parsed
262         ipriha:
263         parser needs a base url to find referenced entities.
264         */

265         // InputSource source = new InputSource(url.openStream());
266

267         String JavaDoc pathName = url.toExternalForm();
268
269         log.info("Building repository from :" + pathName);
270         InputSource JavaDoc source = new InputSource JavaDoc(pathName);
271         URLConnection JavaDoc conn = url.openConnection();
272         conn.setUseCaches(false);
273         conn.connect();
274         InputStream JavaDoc in = conn.getInputStream();
275         source.setByteStream(in);
276         try
277         {
278             return readMetadataFromXML(source, targetRepository);
279         }
280         finally
281         {
282             try
283             {
284                 in.close();
285             }
286             catch (IOException JavaDoc x)
287             {
288                 log.warn("unable to close repository input stream [" + x.getMessage() + "]", x);
289             }
290         }
291     }
292
293     /**
294      * Read metadata by populating an instance of the target class
295      * using SAXParser.
296      */

297     private Object JavaDoc readMetadataFromXML(InputSource JavaDoc source, Class JavaDoc target)
298             throws MalformedURLException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc, IOException JavaDoc
299     {
300         // TODO: make this configurable
301
boolean validate = false;
302         
303         // get a xml reader instance:
304
SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance();
305         log.info("RepositoryPersistor using SAXParserFactory : " + factory.getClass().getName());
306         if (validate)
307         {
308             factory.setValidating(true);
309         }
310         SAXParser JavaDoc p = factory.newSAXParser();
311         XMLReader JavaDoc reader = p.getXMLReader();
312         if (validate)
313         {
314             reader.setErrorHandler(new OJBErrorHandler());
315         }
316
317         Object JavaDoc result;
318         if (DescriptorRepository.class.equals(target))
319         {
320             // create an empty repository:
321
DescriptorRepository repository = new DescriptorRepository();
322             // create handler for building the repository structure
323
ContentHandler JavaDoc handler = new RepositoryXmlHandler(repository);
324             // tell parser to use our handler:
325
reader.setContentHandler(handler);
326             reader.parse(source);
327             result = repository;
328         }
329         else if (ConnectionRepository.class.equals(target))
330         {
331             // create an empty repository:
332
ConnectionRepository repository = new ConnectionRepository();
333             // create handler for building the repository structure
334
ContentHandler JavaDoc handler = new ConnectionDescriptorXmlHandler(repository);
335             // tell parser to use our handler:
336
reader.setContentHandler(handler);
337             reader.parse(source);
338             //LoggerFactory.getBootLogger().info("loading XML took " + (stop - start) + " msecs");
339
result = repository;
340         }
341         else
342             throw new MetadataException("Could not build a repository instance for '" + target +
343                     "', using source " + source);
344         return result;
345     }
346
347     private URL JavaDoc buildURL(String JavaDoc repositoryFileName) throws MalformedURLException JavaDoc
348     {
349         //j2ee compliant lookup of resources
350
URL JavaDoc url = ClassHelper.getResource(repositoryFileName);
351
352         // don't be too strict: if resource is not on the classpath, try ordinary file lookup
353
if (url == null)
354         {
355             try
356             {
357                 url = new File JavaDoc(repositoryFileName).toURL();
358             }
359             catch (MalformedURLException JavaDoc ignore)
360             {
361             }
362         }
363
364         if (url != null)
365         {
366             log.info("OJB Descriptor Repository: " + url);
367         }
368         else
369         {
370             throw new MalformedURLException JavaDoc("did not find resource " + repositoryFileName);
371         }
372         return url;
373     }
374
375     // inner class
376
class OJBErrorHandler implements ErrorHandler JavaDoc
377     {
378         public void warning(SAXParseException JavaDoc exception)
379                 throws SAXException JavaDoc
380         {
381             logMessage(exception, false);
382         }
383
384         public void error(SAXParseException JavaDoc exception)
385                 throws SAXException JavaDoc
386         {
387             logMessage(exception, false);
388         }
389
390         public void fatalError(SAXParseException JavaDoc exception)
391                 throws SAXException JavaDoc
392         {
393             logMessage(exception, true);
394         }
395
396         void logMessage(SAXParseException JavaDoc e, boolean isFatal)
397         {
398             String JavaDoc msg = e.getMessage();
399             if (isFatal)
400             {
401                 log.error("## " + e.getSystemId() + " - line " + e.getLineNumber() + ": " + msg + " ##");
402             }
403             else
404             {
405                 log.warn(e.getSystemId() + " - line " + e.getLineNumber() + ": " + msg);
406             }
407         }
408     }
409 }
410
Popular Tags