View Javadoc
1   /* ***************************************************************************
2    * Copyright (c) 2008 Brabenetz Harald, Austria.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   * 
16   *****************************************************************************/
17  
18  package org.settings4j.objectresolver;
19  
20  import java.beans.ExceptionListener;
21  import java.beans.XMLDecoder;
22  import java.io.ByteArrayInputStream;
23  import java.util.Properties;
24  
25  import org.settings4j.ContentResolver;
26  
27  /**
28   * This ObjectResolver convert a byte[] to an Object with the {@link XMLDecoder}.
29   * <p>
30   * Example: The following code should return a {@link javax.sql.DataSource} Object:<br/>
31   * <code>
32   * Settings4j.getObject("com/myCompany/myApp/MyDatasource");
33   * </code>
34   * <p>
35   * In normal Cases the DataSource comes from the JNDI-Context (available in most Servlet Containers).<br/>
36   * But in some environments there are no JNDI-Context (Commandline-Clients, UnitTests).<br/>
37   * <p>
38   * With Settings4j (default configuration) you can also place two Files into your Classpath:
39   * <ol>
40   * <li><code>"com/myCompany/myApp/MyDatasource"</code>: The File which defines the DataSource
41   * <li><code>"com/myCompany/myApp/MyDatasource.properties"</code>: Some Properties,
42   * like which ObjectResolver should be use.
43   * </ol>
44   * <p>
45   * The File Content whould be the following:
46   * <pre>
47   * Classpath File "com/myCompany/myApp/MyDatasource.properties":
48   * <div style="border-width:1px;border-style:solid;">
49   * objectResolverKey=org.settings4j.objectresolver.JavaXMLBeansObjectResolver
50   * cached=true
51   * </div></pre>
52   * 
53   * <pre>
54   * Classpath File "com/myCompany/myApp/MyDatasource":
55   * <div style="border-width:1px;border-style:solid;">
56   * &lt;?xml version="1.0" encoding="UTF-8"?&gt; 
57   * &lt;java version="1.6.0_05" class="java.beans.XMLDecoder"&gt; 
58   *  &lt;object class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt; 
59   *   &lt;void property="driverClassName"&gt; 
60   *    &lt;string&gt;org.hsqldb.jdbcDriver&lt;/string&gt; 
61   *   &lt;/void&gt; 
62   *   &lt;void property="password"&gt; 
63   *    &lt;string&gt;&lt;/string&gt; 
64   *   &lt;/void&gt; 
65   *   &lt;void property="url"&gt; 
66   *    &lt;string&gt;jdbc:hsqldb:mem:test&lt;/string&gt; 
67   *   &lt;/void&gt; 
68   *   &lt;void property="username"&gt; 
69   *    &lt;string&gt;sa&lt;/string&gt; 
70   *   &lt;/void&gt; 
71   *  &lt;/object&gt; 
72   * &lt;/java&gt; 
73   * </div></pre>
74   * 
75   * <p>
76   * 
77   * 
78   * @author Harald.Brabenetz
79   */
80  public class JavaXMLBeansObjectResolver extends AbstractObjectResolver {
81  
82      /** General Logger for this Class. */
83      private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(JavaXMLBeansObjectResolver.class);
84  
85      /** {@inheritDoc} */
86      @Override
87      protected Object contentToObject(final String key, final Properties properties, final byte[] content,
88              final ContentResolver contentResolver) {
89          final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
90          final XMLDecoder encoder = new XMLDecoder(byteArrayInputStream);
91          encoder.setExceptionListener(new LogDecoderExceptionListener(key));
92          return encoder.readObject();
93      }
94  
95      /**
96       * Log out Exception during Encoding a byte[] to an Object<br />
97       * <br />
98       * Example:<br />
99       * The {@link org.springframework.jdbc.datasource.AbstractDataSource} Object<br />
100      * had Getter and Setter for "logWriter" who throws per default an {@link UnsupportedOperationException}.<br />
101      * 
102      * @author Harald.Brabenetz
103      */
104     private static class LogDecoderExceptionListener implements ExceptionListener {
105 
106         private final String key;
107 
108         public LogDecoderExceptionListener(final String key) {
109             super();
110             this.key = key;
111         }
112 
113         /** {@inheritDoc} */
114         public void exceptionThrown(final Exception e) {
115             LOG.warn(//
116                 "Ignore error on decoding Object from key: {}! {}: {}; Set Loglevel DEBUG for more informations.", //
117                 this.key, e.getClass().getName(), e.getMessage());
118             LOG.debug(e.getMessage(), e);
119         }
120     }
121 }