001/* 002 * Copyright 2002-2012 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 * https://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 017package org.springframework.oxm.support; 018 019import java.io.IOException; 020import javax.xml.transform.Source; 021import javax.xml.transform.sax.SAXResult; 022import javax.xml.transform.sax.SAXSource; 023 024import org.xml.sax.ContentHandler; 025import org.xml.sax.DTDHandler; 026import org.xml.sax.EntityResolver; 027import org.xml.sax.ErrorHandler; 028import org.xml.sax.InputSource; 029import org.xml.sax.SAXException; 030import org.xml.sax.SAXNotRecognizedException; 031import org.xml.sax.SAXParseException; 032import org.xml.sax.XMLReader; 033import org.xml.sax.ext.LexicalHandler; 034 035import org.springframework.oxm.Marshaller; 036import org.springframework.util.Assert; 037 038/** 039 * {@link Source} implementation that uses a {@link Marshaller}.Can be constructed with a 040 * {@code Marshaller} and an object to be marshalled. 041 * 042 * <p>Even though {@code MarshallingSource} extends from {@code SAXSource}, calling the methods of 043 * {@code SAXSource} is <strong>not supported</strong>. In general, the only supported operation on this class is 044 * to use the {@code XMLReader} obtained via {@link #getXMLReader()} to parse the input source obtained via {@link 045 * #getInputSource()}. Calling {@link #setXMLReader(XMLReader)} or {@link #setInputSource(InputSource)} will result in 046 * {@code UnsupportedOperationException}s. 047 * 048 * @author Arjen Poutsma 049 * @since 3.0 050 * @see javax.xml.transform.Transformer 051 */ 052public class MarshallingSource extends SAXSource { 053 054 private final Marshaller marshaller; 055 056 private final Object content; 057 058 059 /** 060 * Create a new {@code MarshallingSource} with the given marshaller and content. 061 * @param marshaller the marshaller to use 062 * @param content the object to be marshalled 063 */ 064 public MarshallingSource(Marshaller marshaller, Object content) { 065 super(new MarshallingXMLReader(marshaller, content), new InputSource()); 066 Assert.notNull(marshaller, "'marshaller' must not be null"); 067 Assert.notNull(content, "'content' must not be null"); 068 this.marshaller = marshaller; 069 this.content = content; 070 } 071 072 073 /** 074 * Return the {@code Marshaller} used by this {@code MarshallingSource}. 075 */ 076 public Marshaller getMarshaller() { 077 return this.marshaller; 078 } 079 080 /** 081 * Return the object to be marshalled. 082 */ 083 public Object getContent() { 084 return this.content; 085 } 086 087 /** 088 * Throws a {@code UnsupportedOperationException}. 089 */ 090 @Override 091 public void setInputSource(InputSource inputSource) { 092 throw new UnsupportedOperationException("setInputSource is not supported"); 093 } 094 095 /** 096 * Throws a {@code UnsupportedOperationException}. 097 */ 098 @Override 099 public void setXMLReader(XMLReader reader) { 100 throw new UnsupportedOperationException("setXMLReader is not supported"); 101 } 102 103 104 private static class MarshallingXMLReader implements XMLReader { 105 106 private final Marshaller marshaller; 107 108 private final Object content; 109 110 private DTDHandler dtdHandler; 111 112 private ContentHandler contentHandler; 113 114 private EntityResolver entityResolver; 115 116 private ErrorHandler errorHandler; 117 118 private LexicalHandler lexicalHandler; 119 120 private MarshallingXMLReader(Marshaller marshaller, Object content) { 121 Assert.notNull(marshaller, "'marshaller' must not be null"); 122 Assert.notNull(content, "'content' must not be null"); 123 this.marshaller = marshaller; 124 this.content = content; 125 } 126 127 @Override 128 public void setContentHandler(ContentHandler contentHandler) { 129 this.contentHandler = contentHandler; 130 } 131 132 @Override 133 public ContentHandler getContentHandler() { 134 return this.contentHandler; 135 } 136 137 @Override 138 public void setDTDHandler(DTDHandler dtdHandler) { 139 this.dtdHandler = dtdHandler; 140 } 141 142 @Override 143 public DTDHandler getDTDHandler() { 144 return this.dtdHandler; 145 } 146 147 @Override 148 public void setEntityResolver(EntityResolver entityResolver) { 149 this.entityResolver = entityResolver; 150 } 151 152 @Override 153 public EntityResolver getEntityResolver() { 154 return this.entityResolver; 155 } 156 157 @Override 158 public void setErrorHandler(ErrorHandler errorHandler) { 159 this.errorHandler = errorHandler; 160 } 161 162 @Override 163 public ErrorHandler getErrorHandler() { 164 return this.errorHandler; 165 } 166 167 protected LexicalHandler getLexicalHandler() { 168 return this.lexicalHandler; 169 } 170 171 @Override 172 public boolean getFeature(String name) throws SAXNotRecognizedException { 173 throw new SAXNotRecognizedException(name); 174 } 175 176 @Override 177 public void setFeature(String name, boolean value) throws SAXNotRecognizedException { 178 throw new SAXNotRecognizedException(name); 179 } 180 181 @Override 182 public Object getProperty(String name) throws SAXNotRecognizedException { 183 if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { 184 return lexicalHandler; 185 } 186 else { 187 throw new SAXNotRecognizedException(name); 188 } 189 } 190 191 @Override 192 public void setProperty(String name, Object value) throws SAXNotRecognizedException { 193 if ("http://xml.org/sax/properties/lexical-handler".equals(name)) { 194 this.lexicalHandler = (LexicalHandler) value; 195 } 196 else { 197 throw new SAXNotRecognizedException(name); 198 } 199 } 200 201 @Override 202 public void parse(InputSource input) throws SAXException { 203 parse(); 204 } 205 206 @Override 207 public void parse(String systemId) throws SAXException { 208 parse(); 209 } 210 211 private void parse() throws SAXException { 212 SAXResult result = new SAXResult(getContentHandler()); 213 result.setLexicalHandler(getLexicalHandler()); 214 try { 215 this.marshaller.marshal(this.content, result); 216 } 217 catch (IOException ex) { 218 SAXParseException saxException = new SAXParseException(ex.getMessage(), null, null, -1, -1, ex); 219 ErrorHandler errorHandler = getErrorHandler(); 220 if (errorHandler != null) { 221 errorHandler.fatalError(saxException); 222 } 223 else { 224 throw saxException; 225 } 226 } 227 } 228 } 229 230}