001: /*
002: * Copyright 2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.oxm.jaxb;
018:
019: import java.util.Iterator;
020: import java.util.Map;
021: import javax.xml.bind.JAXBContext;
022: import javax.xml.bind.JAXBException;
023: import javax.xml.bind.Marshaller;
024: import javax.xml.bind.Unmarshaller;
025: import javax.xml.bind.ValidationEventHandler;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.springframework.beans.factory.InitializingBean;
030: import org.springframework.oxm.XmlMappingException;
031:
032: /**
033: * Abstract base class for implementations of the <code>Marshaller</code> and <code>Unmarshaller</code> interfaces that
034: * use JAXB. This base class is responsible for creating JAXB marshallers from a <code>JAXBContext</code>.
035: * <p/>
036: * JAXB 2.0 added breaking API changes, so specific subclasses must be used for JAXB 1.0 and 2.0
037: * (<code>Jaxb1Marshaller</code> and <code>Jaxb2Marshaller</code> respectivaly).
038: *
039: * @author Arjen Poutsma
040: * @see Jaxb1Marshaller
041: * @see Jaxb2Marshaller
042: * @since 1.0.0
043: */
044: public abstract class AbstractJaxbMarshaller implements
045: org.springframework.oxm.Marshaller,
046: org.springframework.oxm.Unmarshaller, InitializingBean {
047:
048: /** Logger available to subclasses. */
049: protected final Log logger = LogFactory.getLog(getClass());
050:
051: private String contextPath;
052:
053: private Map marshallerProperties;
054:
055: private Map unmarshallerProperties;
056:
057: private JAXBContext jaxbContext;
058:
059: private ValidationEventHandler validationEventHandler;
060:
061: /** Returns the JAXB Context path. */
062: protected String getContextPath() {
063: return contextPath;
064: }
065:
066: /** Sets the JAXB Context path. */
067: public void setContextPath(String contextPath) {
068: this .contextPath = contextPath;
069: }
070:
071: /**
072: * Sets the JAXB <code>Marshaller</code> properties. These properties will be set on the underlying JAXB
073: * <code>Marshaller</code>, and allow for features such as indentation.
074: *
075: * @param properties the properties
076: * @see javax.xml.bind.Marshaller#setProperty(String,Object)
077: * @see javax.xml.bind.Marshaller#JAXB_ENCODING
078: * @see javax.xml.bind.Marshaller#JAXB_FORMATTED_OUTPUT
079: * @see javax.xml.bind.Marshaller#JAXB_NO_NAMESPACE_SCHEMA_LOCATION
080: * @see javax.xml.bind.Marshaller#JAXB_SCHEMA_LOCATION
081: */
082: public void setMarshallerProperties(Map properties) {
083: this .marshallerProperties = properties;
084: }
085:
086: /**
087: * Sets the JAXB <code>Unmarshaller</code> properties. These properties will be set on the underlying JAXB
088: * <code>Unmarshaller</code>.
089: *
090: * @param properties the properties
091: * @see javax.xml.bind.Unmarshaller#setProperty(String,Object)
092: */
093: public void setUnmarshallerProperties(Map properties) {
094: this .unmarshallerProperties = properties;
095: }
096:
097: /**
098: * Sets the JAXB validation event handler. This event handler will be called by JAXB if any validation errors are
099: * encountered during calls to any of the marshal API's.
100: *
101: * @param validationEventHandler the event handler
102: */
103: public void setValidationEventHandler(
104: ValidationEventHandler validationEventHandler) {
105: this .validationEventHandler = validationEventHandler;
106: }
107:
108: /** Returns the {@link JAXBContext} created in {@link #afterPropertiesSet()}. */
109: public JAXBContext getJaxbContext() {
110: return jaxbContext;
111: }
112:
113: public final void afterPropertiesSet() throws Exception {
114: try {
115: jaxbContext = createJaxbContext();
116: } catch (JAXBException ex) {
117: throw convertJaxbException(ex);
118: }
119: }
120:
121: /**
122: * Convert the given <code>JAXBException</code> to an appropriate exception from the
123: * <code>org.springframework.oxm</code> hierarchy.
124: * <p/>
125: * The default implementation delegates to <code>JaxbUtils</code>. Can be overridden in subclasses.
126: *
127: * @param ex <code>JAXBException</code> that occured
128: * @return the corresponding <code>XmlMappingException</code> instance
129: * @see JaxbUtils#convertJaxbException
130: */
131: protected XmlMappingException convertJaxbException(JAXBException ex) {
132: return JaxbUtils.convertJaxbException(ex);
133: }
134:
135: /** Returns a newly created JAXB marshaller. JAXB marshallers are not necessarily thread safe. */
136: protected Marshaller createMarshaller() {
137: try {
138: Marshaller marshaller = jaxbContext.createMarshaller();
139: if (marshallerProperties != null) {
140: for (Iterator iterator = marshallerProperties.keySet()
141: .iterator(); iterator.hasNext();) {
142: String name = (String) iterator.next();
143: marshaller.setProperty(name, marshallerProperties
144: .get(name));
145: }
146: }
147: if (validationEventHandler != null) {
148: marshaller.setEventHandler(validationEventHandler);
149: }
150: initJaxbMarshaller(marshaller);
151: return marshaller;
152: } catch (JAXBException ex) {
153: throw convertJaxbException(ex);
154: }
155: }
156:
157: /** Returns a newly created JAXB unmarshaller. JAXB unmarshallers are not necessarily thread safe. */
158: protected Unmarshaller createUnmarshaller() {
159: try {
160: Unmarshaller unmarshaller = jaxbContext
161: .createUnmarshaller();
162: if (unmarshallerProperties != null) {
163: for (Iterator iterator = unmarshallerProperties
164: .keySet().iterator(); iterator.hasNext();) {
165: String name = (String) iterator.next();
166: unmarshaller.setProperty(name,
167: unmarshallerProperties.get(name));
168: }
169: }
170: if (validationEventHandler != null) {
171: unmarshaller.setEventHandler(validationEventHandler);
172: }
173: initJaxbUnmarshaller(unmarshaller);
174: return unmarshaller;
175: } catch (JAXBException ex) {
176: throw convertJaxbException(ex);
177: }
178: }
179:
180: /**
181: * Template method that can be overridden by concrete JAXB marshallers for custom initialization behavior. Gets
182: * called after creation of JAXB <code>Marshaller</code>, and after the respective properties have been set.
183: * <p/>
184: * Default implementation does nothing.
185: */
186: protected void initJaxbMarshaller(Marshaller marshaller)
187: throws JAXBException {
188: }
189:
190: /**
191: * Template method that can overridden by concrete JAXB marshallers for custom initialization behavior. Gets called
192: * after creation of JAXB <code>Unmarshaller</code>, and after the respective properties have been set.
193: * <p/>
194: * Default implementation does nothing.
195: */
196: protected void initJaxbUnmarshaller(Unmarshaller unmarshaller)
197: throws JAXBException {
198: }
199:
200: /** Template method that returns a newly created JAXB context. Called from <code>afterPropertiesSet()</code>. */
201: protected abstract JAXBContext createJaxbContext() throws Exception;
202: }
|