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 * <?xml version="1.0" encoding="UTF-8"?>
57 * <java version="1.6.0_05" class="java.beans.XMLDecoder">
58 * <object class="org.springframework.jdbc.datasource.DriverManagerDataSource">
59 * <void property="driverClassName">
60 * <string>org.hsqldb.jdbcDriver</string>
61 * </void>
62 * <void property="password">
63 * <string></string>
64 * </void>
65 * <void property="url">
66 * <string>jdbc:hsqldb:mem:test</string>
67 * </void>
68 * <void property="username">
69 * <string>sa</string>
70 * </void>
71 * </object>
72 * </java>
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 }