View Javadoc

1   /*
2    * Copyright 2005 the original author or authors.
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  package org.springframework.oxm.jaxb;
17  
18  import javax.xml.bind.Element;
19  import javax.xml.bind.JAXBContext;
20  import javax.xml.bind.JAXBException;
21  import javax.xml.bind.Unmarshaller;
22  import javax.xml.stream.XMLEventReader;
23  import javax.xml.stream.XMLEventWriter;
24  import javax.xml.stream.XMLStreamReader;
25  import javax.xml.stream.XMLStreamWriter;
26  import javax.xml.transform.Result;
27  import javax.xml.transform.Source;
28  
29  import org.springframework.beans.factory.BeanClassLoaderAware;
30  import org.springframework.util.ClassUtils;
31  import org.springframework.util.StringUtils;
32  import org.springframework.xml.transform.StaxResult;
33  import org.springframework.xml.transform.StaxSource;
34  import org.springframework.xml.transform.TraxUtils;
35  
36  /**
37   * Implementation of the <code>Marshaller</code> interface for JAXB 1.0.
38   * <p/>
39   * The typical usage will be to set the <code>contextPath</code> property on this bean, possibly customize the
40   * marshaller and unmarshaller by setting properties, and validations, and to refer to it.
41   *
42   * @author Arjen Poutsma
43   * @see #setContextPath(String)
44   * @see #setMarshallerProperties(java.util.Map)
45   * @see #setUnmarshallerProperties(java.util.Map)
46   * @see #setValidating(boolean)
47   * @since 1.0.0
48   */
49  public class Jaxb1Marshaller extends AbstractJaxbMarshaller implements BeanClassLoaderAware {
50  
51      private boolean validating = false;
52  
53      private ClassLoader classLoader;
54  
55      public void setBeanClassLoader(ClassLoader classLoader) {
56          this.classLoader = classLoader;
57      }
58  
59      /** Set if the JAXB <code>Unmarshaller</code> should validate the incoming document. Default is <code>false</code>. */
60      public void setValidating(boolean validating) {
61          this.validating = validating;
62      }
63  
64      public boolean supports(Class clazz) {
65          if (!Element.class.isAssignableFrom(clazz)) {
66              return false;
67          }
68          if (StringUtils.hasLength(getContextPath())) {
69              String className = ClassUtils.getQualifiedName(clazz);
70              int lastDotIndex = className.lastIndexOf('.');
71              if (lastDotIndex == -1) {
72                  return false;
73              }
74              String packageName = className.substring(0, lastDotIndex);
75              String[] contextPaths = StringUtils.tokenizeToStringArray(getContextPath(), ":");
76              for (int i = 0; i < contextPaths.length; i++) {
77                  if (contextPaths[i].equals(packageName)) {
78                      return true;
79                  }
80              }
81              return false;
82          }
83          return false;
84  
85      }
86  
87      protected final JAXBContext createJaxbContext() throws JAXBException {
88          if (!StringUtils.hasLength(getContextPath())) {
89              throw new IllegalArgumentException("contextPath is required");
90          }
91          if (logger.isInfoEnabled()) {
92              logger.info("Creating JAXBContext with context path [" + getContextPath() + "]");
93          }
94          return classLoader != null ? JAXBContext.newInstance(getContextPath(), classLoader) :
95                  JAXBContext.newInstance(getContextPath());
96      }
97  
98      protected void initJaxbUnmarshaller(Unmarshaller unmarshaller) throws JAXBException {
99          unmarshaller.setValidating(validating);
100     }
101 
102     public void marshal(Object graph, Result result) {
103         if (TraxUtils.isStaxResult(result)) {
104             XMLStreamWriter streamWriter = TraxUtils.getXMLStreamWriter(result);
105             if (streamWriter != null) {
106                 result = new StaxResult(streamWriter);
107             }
108             else {
109                 XMLEventWriter eventWriter = TraxUtils.getXMLEventWriter(result);
110                 if (eventWriter != null) {
111                     result = new StaxResult(eventWriter);
112                 }
113                 else {
114                     throw new IllegalArgumentException(
115                             "StAXResult contains neither XMLStreamWriter nor XMLEventWriter");
116                 }
117             }
118         }
119         try {
120             createMarshaller().marshal(graph, result);
121         }
122         catch (JAXBException ex) {
123             throw convertJaxbException(ex);
124         }
125     }
126 
127     public Object unmarshal(Source source) {
128         if (TraxUtils.isStaxSource(source)) {
129             XMLStreamReader streamReader = TraxUtils.getXMLStreamReader(source);
130             if (streamReader != null) {
131                 source = new StaxSource(streamReader);
132             }
133             else {
134                 XMLEventReader eventReader = TraxUtils.getXMLEventReader(source);
135                 if (eventReader != null) {
136                     source = new StaxSource(eventReader);
137                 }
138                 else {
139                     throw new IllegalArgumentException(
140                             "StAXSource contains neither XMLStreamReader nor XMLEventReader");
141                 }
142             }
143         }
144         try {
145             return createUnmarshaller().unmarshal(source);
146         }
147         catch (JAXBException ex) {
148             throw convertJaxbException(ex);
149         }
150     }
151 
152 }