View Javadoc
1   /*
2    * #%L
3    * settings4j
4    * ===============================================================
5    * Copyright (C) 2008 - 2015 Brabenetz Harald, Austria
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   * #L%
19   */
20  package org.settings4j.objectresolver;
21  
22  import java.beans.ExceptionListener;
23  import java.beans.XMLDecoder;
24  import java.io.ByteArrayInputStream;
25  import java.util.Properties;
26  
27  import org.settings4j.ContentResolver;
28  
29  /**
30   * This ObjectResolver convert a byte[] to an Object with the {@link XMLDecoder}.
31   * <p>
32   * Example: The following code should return a {@link javax.sql.DataSource} Object:<br>
33   * <code>
34   * Settings4j.getObject("com/myCompany/myApp/MyDatasource");
35   * </code>
36   * </p>
37   * <p>
38   * In normal Cases the DataSource comes from the JNDI-Context (available in most Servlet Containers).<br>
39   * But in some environments there are no JNDI-Context (Commandline-Clients, UnitTests).<br>
40   * </p>
41   * <p>
42   * With Settings4j (default configuration) you can also place two Files into your Classpath:
43   * </p>
44   * <ol>
45   * <li><code>"com/myCompany/myApp/MyDatasource"</code>: The File which defines the DataSource
46   * <li><code>"com/myCompany/myApp/MyDatasource.properties"</code>: Some Properties, like which ObjectResolver should be use.
47   * </ol>
48   * <p>
49   * The File Content whould be the following: Classpath File "com/myCompany/myApp/MyDatasource.properties":
50   * </p>
51   *
52   * <pre style="border-width:1px;border-style:solid;">
53   * objectResolverKey=org.settings4j.objectresolver.JavaXMLBeansObjectResolver
54   * cached=true
55   * </pre>
56   * <p>
57   * Classpath File "com/myCompany/myApp/MyDatasource":
58   * </p>
59   *
60   * <pre style="border-width:1px;border-style:solid;">
61   * &lt;?xml version="1.0" encoding="UTF-8"?&gt;
62   * &lt;java version="1.6.0_05" class="java.beans.XMLDecoder"&gt;
63   *  &lt;object class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
64   *   &lt;void property="driverClassName"&gt;
65   *    &lt;string&gt;org.hsqldb.jdbcDriver&lt;/string&gt;
66   *   &lt;/void&gt;
67   *   &lt;void property="password"&gt;
68   *    &lt;string&gt;&lt;/string&gt;
69   *   &lt;/void&gt;
70   *   &lt;void property="url"&gt;
71   *    &lt;string&gt;jdbc:hsqldb:mem:test&lt;/string&gt;
72   *   &lt;/void&gt;
73   *   &lt;void property="username"&gt;
74   *    &lt;string&gt;sa&lt;/string&gt;
75   *   &lt;/void&gt;
76   *  &lt;/object&gt;
77   * &lt;/java&gt;
78   * </pre>
79   *
80   * @author Harald.Brabenetz
81   */
82  public class JavaXMLBeansObjectResolver extends AbstractObjectResolver {
83  
84      /** General Logger for this Class. */
85      private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(JavaXMLBeansObjectResolver.class);
86  
87      @Override
88      protected Object contentToObject(final String key, final Properties properties, final byte[] content,
89          final ContentResolver contentResolver) {
90          final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
91          XMLDecoder encoder = null;
92          try {
93              encoder = new XMLDecoder(byteArrayInputStream);
94              encoder.setExceptionListener(new LogDecoderExceptionListener(key));
95              return encoder.readObject();
96          } finally {
97              if (encoder != null) {
98                  encoder.close();
99              }
100         }
101     }
102 
103     /**
104      * Log out Exception during Encoding a byte[] to an Object<br>
105      * <br>
106      * Example:<br>
107      * The {@link org.springframework.jdbc.datasource.AbstractDataSource} Object<br>
108      * had Getter and Setter for "logWriter" who throws per default an {@link UnsupportedOperationException}.<br>
109      *
110      * @author Harald.Brabenetz
111      */
112     private static class LogDecoderExceptionListener implements ExceptionListener {
113 
114         private final String key;
115 
116         public LogDecoderExceptionListener(final String key) {
117             super();
118             this.key = key;
119         }
120 
121         @Override
122         public void exceptionThrown(final Exception e) {
123             LOG.warn(//
124                 "Ignore error on decoding Object from key: {}! {}: {}; Set Loglevel DEBUG for more informations.", //
125                 this.key, e.getClass().getName(), e.getMessage());
126             LOG.debug(e.getMessage(), e);
127         }
128     }
129 }