1 /**********************************************************************
2 * CastorAdapter.java
3 * created on 11.03.2005 by netseeker
4 * $Source: /cvsroot/ejoe/EJOE/src/de/netseeker/ejoe/adapter/CastorAdapter.java,v $
5 * $Date: 2007/11/17 11:20:34 $
6 * $Revision: 1.23 $
7 *********************************************************************/
8 package de.netseeker.ejoe.adapter;
9
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.io.InputStreamReader;
13 import java.io.OutputStream;
14 import java.io.OutputStreamWriter;
15 import java.io.Writer;
16 import java.net.URL;
17
18 import org.castor.mapping.BindingType;
19 import org.exolab.castor.mapping.Mapping;
20 import org.exolab.castor.mapping.MappingException;
21 import org.exolab.castor.xml.ClassDescriptorResolverFactory;
22 import org.exolab.castor.xml.Marshaller;
23 import org.exolab.castor.xml.Unmarshaller;
24 import org.exolab.castor.xml.util.XMLClassDescriptorResolverImpl;
25
26 import de.netseeker.ejoe.EJConstants;
27 import de.netseeker.ejoe.io.IOUtil;
28
29 /***
30 * An adapter for (de)serializing objects via the Castor XML library. This adapter implementation uses the performance
31 * hints described in the Castor Marshalling FAQ, that means it does:
32 * <ul>
33 * <li>reuse the castor mapping repository</li>
34 * <li>cache the class desciptors of already marshalled/unmarshalled objects</li>
35 * <li>disable validation per default</li>
36 * </ul>
37 * Furthermore it does reuse one Unmarshaller instance.
38 *
39 * @link http://castor.codehaus.org/xml-faq.html#How-can-I-speed-up-marshalling/unmarshalling-performance
40 * @link http://castor.codehaus.org/
41 * @author netseeker
42 */
43 public class CastorAdapter extends BaseAdapter
44 {
45 private static final long serialVersionUID = 1L;
46
47 private Mapping _mapping;
48
49 private transient Unmarshaller _unmarshaller;
50
51 private static XMLClassDescriptorResolverImpl _cdr;
52
53 private boolean _validate = false;
54
55 static
56 {
57 if ( _cdr == null )
58 {
59 _cdr = (XMLClassDescriptorResolverImpl) ClassDescriptorResolverFactory
60 .createClassDescriptorResolver( BindingType.XML );
61 }
62 }
63
64 /***
65 * Creates a new instance of this adapter.
66 */
67 public CastorAdapter()
68 {
69 try
70 {
71 initCastor( false );
72 }
73 catch ( MappingException e )
74 {
75
76 }
77 }
78
79 /***
80 * Creates a new instance of this adapter. Castor validation is enabled/disabled according to the given value.
81 *
82 * @param validate either Castor validation should be enabled or not.
83 */
84 public CastorAdapter(boolean validate)
85 {
86 try
87 {
88 initCastor( validate );
89 }
90 catch ( MappingException e )
91 {
92
93 }
94 }
95
96 /***
97 * Creates a new instance of this adapter using the given Castor mapping.
98 *
99 * @param mapping existing Castor mapping to use
100 * @throws MappingException
101 */
102 public CastorAdapter(Mapping mapping) throws MappingException
103 {
104 _mapping = mapping;
105 initCastor( false );
106 }
107
108 /***
109 * Creates a new instance of this adapter using the Castor mapping loaded from the given mapping file.
110 *
111 * @param pathToMappingFile path of the Castor mapping file to use
112 * @throws IOException
113 * @throws MappingException
114 */
115 public CastorAdapter(String pathToMappingFile) throws IOException, MappingException
116 {
117 this();
118 _mapping = new Mapping();
119 _mapping.loadMapping( pathToMappingFile );
120 initCastor( false );
121 }
122
123 /***
124 * Creates a new instance of this adapter using the Castor mapping loaded from the given mapping file.
125 *
126 * @param pathToMappingFile path of the Castor mapping file to use
127 * @throws IOException
128 * @throws MappingException
129 */
130 public CastorAdapter(URL pathToMappingFile) throws IOException, MappingException
131 {
132 this();
133 _mapping = new Mapping();
134 _mapping.loadMapping( pathToMappingFile );
135 initCastor( false );
136 }
137
138 /***
139 * Either enables or disables Castors validation feature.
140 *
141 * @param enable
142 */
143 public void setValidation( boolean enable )
144 {
145 _unmarshaller.setValidation( enable );
146 }
147
148 private void initCastor( boolean validate ) throws MappingException
149 {
150 _validate = validate;
151
152
153 if ( _mapping != null )
154 {
155 _unmarshaller = new Unmarshaller( _mapping );
156 }
157 else
158 {
159 _unmarshaller = new Unmarshaller();
160 }
161
162 _unmarshaller.setValidation( validate );
163
164 _unmarshaller.setResolver( _cdr );
165 }
166
167 private Unmarshaller getUnMarshaller()
168 {
169 if ( this._unmarshaller == null )
170 {
171 try
172 {
173 initCastor( _validate );
174 }
175 catch ( MappingException e )
176 {
177
178 }
179 }
180
181 return _unmarshaller;
182 }
183
184
185
186
187
188
189 public Object read( InputStream in ) throws Exception
190 {
191 InputStreamReader reader = new InputStreamReader( in, EJConstants.EJOE_DEFAULT_CHARSET );
192 try
193 {
194 return getUnMarshaller().unmarshal( reader );
195 }
196 finally
197 {
198 IOUtil.closeQuiet( reader );
199 }
200 }
201
202
203
204
205
206
207 public void write( Object obj, OutputStream out ) throws Exception
208 {
209 Writer writer = new OutputStreamWriter( out, EJConstants.EJOE_DEFAULT_CHARSET );
210 Marshaller marshaller = new Marshaller( writer );
211 try
212 {
213 if ( _mapping != null )
214 {
215 marshaller.setMapping( _mapping );
216 }
217
218 marshaller.setValidation( false );
219 marshaller.setSuppressXSIType( false );
220 marshaller.setUseXSITypeAtRoot( true );
221 marshaller.setMarshalExtendedType( true );
222 marshaller.setResolver( _cdr );
223 marshaller.marshal( obj );
224 }
225 finally
226 {
227 IOUtil.closeQuiet( writer );
228 }
229 }
230
231
232
233
234
235
236 public void handleClassLoaderChange( ClassLoader classLoader )
237 {
238 _unmarshaller.setClassLoader( classLoader );
239 }
240
241
242
243
244
245
246 public boolean requiresCustomEOFHandling()
247 {
248 return true;
249 }
250
251
252
253
254
255
256 public String getContentType()
257 {
258 return "text/xml";
259 }
260 }