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