KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jaxb > JAXBContextImpl


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Adam Megacz
28  */

29
30 package com.caucho.jaxb;
31
32 import com.caucho.jaxb.skeleton.*;
33 import com.caucho.server.util.CauchoSystem;
34 import com.caucho.util.L10N;
35
36 import org.w3c.dom.Node JavaDoc;
37
38 import javax.xml.bind.*;
39 import javax.xml.datatype.*;
40 import javax.xml.namespace.QName JavaDoc;
41 import javax.xml.stream.XMLInputFactory;
42 import javax.xml.stream.XMLOutputFactory;
43 import javax.xml.stream.XMLStreamException;
44 import javax.xml.stream.XMLStreamReader;
45 import javax.xml.stream.XMLStreamWriter;
46 import javax.xml.transform.Result JavaDoc;
47 import java.io.IOException JavaDoc;
48 import java.io.InputStream JavaDoc;
49 import java.io.InputStreamReader JavaDoc;
50 import java.io.LineNumberReader JavaDoc;
51 import java.lang.reflect.ParameterizedType JavaDoc;
52 import java.lang.reflect.Type JavaDoc;
53 import java.math.BigDecimal JavaDoc;
54 import java.math.BigInteger JavaDoc;
55 import java.util.*;
56
57 /**
58  * Entry point to API
59  */

60 public class JAXBContextImpl extends JAXBContext {
61   private static final L10N L = new L10N(JAXBContextImpl.class);
62
63   private static final HashSet<Class JavaDoc> _specialClasses = new HashSet<Class JavaDoc>();
64
65   static {
66     _specialClasses.add(Object JavaDoc.class);
67     _specialClasses.add(Class JavaDoc.class);
68     _specialClasses.add(String JavaDoc.class);
69     _specialClasses.add(Double JavaDoc.class);
70     _specialClasses.add(Float JavaDoc.class);
71     _specialClasses.add(Integer JavaDoc.class);
72     _specialClasses.add(Long JavaDoc.class);
73     _specialClasses.add(Boolean JavaDoc.class);
74     _specialClasses.add(Character JavaDoc.class);
75     _specialClasses.add(Short JavaDoc.class);
76     _specialClasses.add(Byte JavaDoc.class);
77     _specialClasses.add(BigDecimal JavaDoc.class);
78     _specialClasses.add(BigInteger JavaDoc.class);
79     _specialClasses.add(QName JavaDoc.class);
80     _specialClasses.add(Date.class);
81     _specialClasses.add(Calendar.class);
82     _specialClasses.add(XMLGregorianCalendar.class);
83   }
84
85   private String JavaDoc[] _packages;
86   private ClassLoader JavaDoc _classLoader;
87   private JAXBIntrospector _jaxbIntrospector;
88
89   private XMLInputFactory _staxInputFactory;
90   private XMLOutputFactory _staxOutputFactory;
91
92   private ArrayList<ObjectFactorySkeleton> _objectFactories
93     = new ArrayList<ObjectFactorySkeleton>();
94
95   private HashMap<String JavaDoc,Object JavaDoc> _properties
96     = new HashMap<String JavaDoc,Object JavaDoc>();
97
98   private LinkedHashMap<Class JavaDoc,ClassSkeleton> _classSkeletons
99     = new LinkedHashMap<Class JavaDoc,ClassSkeleton>();
100
101   private HashMap<QName JavaDoc,Skeleton> _roots
102     = new HashMap<QName JavaDoc,Skeleton>();
103
104   public JAXBContextImpl(String JavaDoc contextPath,
105                          ClassLoader JavaDoc classLoader,
106                          Map<String JavaDoc,?> properties)
107     throws JAXBException
108   {
109     _jaxbIntrospector = new JAXBIntrospectorImpl(this);
110     _classLoader = classLoader;
111
112     StringTokenizer st = new StringTokenizer(contextPath, ":");
113
114     do {
115       String JavaDoc packageName = st.nextToken();
116       loadPackage(packageName);
117     }
118     while (st.hasMoreTokens());
119
120     if (properties != null)
121       for(Map.Entry<String JavaDoc,?> e : properties.entrySet())
122         setProperty(e.getKey(), e.getValue());
123
124     DatatypeConverter.setDatatypeConverter(new DatatypeConverterImpl());
125   }
126
127   public static JAXBContext createContext(Class JavaDoc []classes,
128                                           Map<String JavaDoc,?> properties)
129     throws JAXBException
130   {
131     return new JAXBContextImpl(classes, properties);
132   }
133
134   public JAXBContextImpl(Class JavaDoc[] classes, Map<String JavaDoc,?> properties)
135     throws JAXBException
136   {
137     _jaxbIntrospector = new JAXBIntrospectorImpl(this);
138     _packages = new String JavaDoc[0];
139     _classLoader = null;
140
141     for(Class JavaDoc c : classes) {
142       // XXX pull out to JAX-WS?
143
if (! c.isPrimitive() &&
144           ! c.isArray() &&
145           ! _specialClasses.contains(c))
146         createSkeleton(c);
147     }
148
149     if (properties != null) {
150       for(Map.Entry<String JavaDoc,?> e : properties.entrySet())
151         setProperty(e.getKey(), e.getValue());
152     }
153
154     DatatypeConverter.setDatatypeConverter(new DatatypeConverterImpl());
155   }
156
157   public Marshaller createMarshaller()
158     throws JAXBException
159   {
160     return new MarshallerImpl(this);
161   }
162
163   public Unmarshaller createUnmarshaller()
164     throws JAXBException
165   {
166     return new UnmarshallerImpl(this);
167   }
168
169   public Validator createValidator()
170     throws JAXBException
171   {
172     throw new UnsupportedOperationException JavaDoc();
173   }
174
175   XMLStreamReader getXMLStreamReader(InputStream JavaDoc is)
176     throws XMLStreamException
177   {
178     if (_staxInputFactory == null)
179       _staxInputFactory = XMLInputFactory.newInstance();
180
181     return _staxInputFactory.createXMLStreamReader(is);
182   }
183
184   XMLInputFactory getXMLInputFactory()
185   {
186     if (_staxInputFactory == null)
187       _staxInputFactory = XMLInputFactory.newInstance();
188
189     return _staxInputFactory;
190   }
191
192   XMLOutputFactory getXMLOutputFactory()
193   {
194     if (_staxOutputFactory == null)
195       _staxOutputFactory = XMLOutputFactory.newInstance();
196
197     return _staxOutputFactory;
198   }
199
200   public String JavaDoc toString() {
201     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
202     sb.append("JAXBContext[");
203
204     for (Class JavaDoc c : _classSkeletons.keySet())
205       sb.append(c.getName() + ":");
206
207     for (int i = 0; i < _packages.length; i++) {
208       String JavaDoc p = _packages[i];
209       sb.append(p + (i < _packages.length - 1 ? ":" : ""));
210     }
211
212     sb.append("]");
213     return sb.toString();
214   }
215
216   private void setProperty(String JavaDoc key, Object JavaDoc val)
217   {
218     _properties.put(key, val);
219   }
220
221   public Binder<Node JavaDoc> createBinder()
222   {
223     throw new UnsupportedOperationException JavaDoc("XML Infoset not supported");
224   }
225
226   public <T> Binder<T> createBinder(Class JavaDoc<T> domType)
227   {
228     throw new UnsupportedOperationException JavaDoc("XML Infoset not supported");
229   }
230   
231   public JAXBIntrospector createJAXBIntrospector()
232   {
233     return _jaxbIntrospector;
234   }
235
236   public void generateSchema(SchemaOutputResolver outputResolver)
237     throws IOException JavaDoc
238   {
239     Result JavaDoc result = outputResolver.createOutput("", "schema1.xsd");
240
241     try {
242       XMLOutputFactory factory = getXMLOutputFactory();
243       XMLStreamWriter out = factory.createXMLStreamWriter(result);
244
245       out.writeStartDocument("UTF-8", "1.0");
246
247       generateSchemaWithoutHeader(out);
248     }
249     catch (Exception JavaDoc e) {
250       IOException JavaDoc ioException = new IOException JavaDoc();
251
252       ioException.initCause(e);
253
254       throw ioException;
255     }
256   }
257
258   public void generateSchemaWithoutHeader(XMLStreamWriter out)
259     throws JAXBException, XMLStreamException
260   {
261     out.writeStartElement("xsd", "schema", "http://www.w3.org/2001/XMLSchema");
262     out.writeAttribute("version", "1.0");
263
264     for (Skeleton skeleton : _classSkeletons.values())
265       skeleton.generateSchema(out);
266
267     out.writeEndElement(); // schema
268
}
269
270   public void createSkeleton(Class JavaDoc c)
271     throws JAXBException
272   {
273     if (_classSkeletons.containsKey(c))
274       return;
275
276     // XXX
277
if (c.isEnum() || c.isInterface())
278       return;
279
280     // Breadcrumb to prevent problems with recursion
281
_classSkeletons.put(c, null);
282
283     ClassSkeleton skeleton = new ClassSkeleton(this, c);
284     _classSkeletons.put(c, skeleton);
285   }
286
287   public Skeleton getSkeleton(Class JavaDoc c)
288     throws JAXBException
289   {
290     createSkeleton(c);
291
292     return _classSkeletons.get(c);
293   }
294
295   public ClassSkeleton findSkeletonForObject(Object JavaDoc obj)
296     throws JAXBException
297   {
298     Class JavaDoc cl = obj.getClass();
299
300     while (! cl.equals(Object JavaDoc.class)) {
301       ClassSkeleton skeleton = _classSkeletons.get(cl);
302
303       if (skeleton != null)
304         return skeleton;
305
306       cl = cl.getSuperclass();
307     }
308
309     throw new JAXBException(L.l("Class {0} unknown to this JAXBContext", cl));
310   }
311
312   public Property createProperty(Type JavaDoc type)
313     throws JAXBException
314   {
315     if (type instanceof Class JavaDoc) {
316       if (String JavaDoc.class.equals(type))
317         return StringProperty.PROPERTY;
318
319       if (Double JavaDoc.class.equals(type))
320         return DoubleProperty.OBJECT_PROPERTY;
321
322       if (Double.TYPE.equals(type))
323         return DoubleProperty.PRIMITIVE_PROPERTY;
324
325       if (Float JavaDoc.class.equals(type))
326         return FloatProperty.OBJECT_PROPERTY;
327
328       if (Float.TYPE.equals(type))
329         return FloatProperty.PRIMITIVE_PROPERTY;
330
331       if (Integer JavaDoc.class.equals(type))
332         return IntProperty.OBJECT_PROPERTY;
333
334       if (Integer.TYPE.equals(type))
335         return IntProperty.PRIMITIVE_PROPERTY;
336
337       if (Long JavaDoc.class.equals(type))
338         return LongProperty.OBJECT_PROPERTY;
339
340       if (Long.TYPE.equals(type))
341         return LongProperty.PRIMITIVE_PROPERTY;
342
343       if (Boolean JavaDoc.class.equals(type))
344         return BooleanProperty.OBJECT_PROPERTY;
345
346       if (Boolean.TYPE.equals(type))
347         return BooleanProperty.PRIMITIVE_PROPERTY;
348
349       if (Character JavaDoc.class.equals(type))
350         return CharacterProperty.OBJECT_PROPERTY;
351
352       if (Character.TYPE.equals(type))
353         return CharacterProperty.PRIMITIVE_PROPERTY;
354
355       if (Short JavaDoc.class.equals(type))
356         return ShortProperty.OBJECT_PROPERTY;
357
358       if (Short.TYPE.equals(type))
359         return ShortProperty.PRIMITIVE_PROPERTY;
360
361       if (Byte JavaDoc.class.equals(type))
362         return ByteProperty.OBJECT_PROPERTY;
363
364       if (Byte.TYPE.equals(type))
365         return ByteProperty.PRIMITIVE_PROPERTY;
366
367       if (BigDecimal JavaDoc.class.equals(type))
368         return BigDecimalProperty.PROPERTY;
369
370       if (BigInteger JavaDoc.class.equals(type))
371         return BigIntegerProperty.PROPERTY;
372
373       if (QName JavaDoc.class.equals(type))
374         return QNameProperty.PROPERTY;
375
376       if (Date.class.equals(type))
377         return DateTimeProperty.PROPERTY;
378
379       if (Calendar.class.equals(type))
380         return CalendarProperty.PROPERTY;
381
382       if (XMLGregorianCalendar.class.equals(type))
383         return XMLGregorianCalendarProperty.PROPERTY;
384
385       if (byte[].class.equals(type))
386         return ByteArrayProperty.PROPERTY;
387
388       Class JavaDoc cl = (Class JavaDoc) type;
389
390       if (cl.isArray()) {
391         Property componentProperty = createProperty(cl.getComponentType());
392         return ArrayProperty.createArrayProperty(componentProperty,
393                                                  cl.getComponentType());
394       }
395
396       if (cl.isEnum())
397         return new EnumProperty();
398
399       return new SkeletonProperty(getSkeleton(cl));
400     }
401     else if (type instanceof ParameterizedType JavaDoc) {
402       ParameterizedType JavaDoc ptype = (ParameterizedType JavaDoc) type;
403       Type JavaDoc rawType = ptype.getRawType();
404
405       if (rawType instanceof Class JavaDoc) {
406         Class JavaDoc rawClass = (Class JavaDoc) rawType;
407
408         if (Map.class.equals(rawClass))
409           return new MapProperty();
410
411         if (List.class.equals(rawClass)) {
412           Type JavaDoc[] args = ptype.getActualTypeArguments();
413
414           if (args.length != 1)
415             throw new JAXBException(L.l("unexpected number of generic arguments for List<>: {0}", args.length));
416
417           Property componentProperty = createProperty(args[0]);
418           return new ListProperty(componentProperty);
419         }
420
421         if (Collection.class.isAssignableFrom(rawClass))
422           return new CollectionProperty();
423       }
424     }
425
426     throw new JAXBException(L.l("Unrecognized type: {0}", type.toString()));
427   }
428
429   public void addRootElement(Skeleton s)
430   {
431     _roots.put(s.getTypeName(), s);
432   }
433
434   public Skeleton getRootElement(QName JavaDoc q)
435   {
436     return _roots.get(q);
437   }
438
439   private void loadPackage(String JavaDoc packageName)
440     throws JAXBException
441   {
442     boolean success = false;
443
444     try {
445       Class JavaDoc cl = CauchoSystem.loadClass(packageName + ".ObjectFactory");
446       _objectFactories.add(new ObjectFactorySkeleton(cl));
447
448       success = true;
449     }
450     catch (ClassNotFoundException JavaDoc e) {
451       // we can still try for jaxb.index
452
}
453
454     try {
455       String JavaDoc resourceName = packageName.replace('.', '/') + "/jaxb.index";
456
457       // For some reason, this approach works when running resin...
458
InputStream JavaDoc is = this.getClass().getResourceAsStream('/' + resourceName);
459
460       // ...and this approach works in QA
461
if (is == null) {
462         ClassLoader JavaDoc classLoader =
463           Thread.currentThread().getContextClassLoader();
464
465         is = classLoader.getResourceAsStream(resourceName);
466       }
467
468       InputStreamReader JavaDoc isr = new InputStreamReader JavaDoc(is, "utf-8");
469       LineNumberReader JavaDoc in = new LineNumberReader JavaDoc(isr);
470
471       for (String JavaDoc line = in.readLine();
472            line != null;
473            line = in.readLine()) {
474         String JavaDoc[] parts = line.split("#", 2);
475         String JavaDoc className = parts[0].trim();
476
477         if (! "".equals(className)) {
478           Class JavaDoc cl = CauchoSystem.loadClass(packageName + "." + className);
479
480           createSkeleton(cl);
481         }
482       }
483
484       success = true;
485     }
486     catch (Throwable JavaDoc t) {
487       if (! success) {
488         throw new JAXBException(L.l("Unable to open jaxb.index for package {0}",
489                                     packageName), t);
490       }
491     }
492   }
493 }
494
495
Popular Tags