1 package com.sun.tools.xjc.runtime; 2 3 import java.util.HashSet ; 4 import java.util.Iterator ; 5 import java.util.Set ; 6 7 import javax.xml.bind.JAXBException; 8 import javax.xml.bind.ValidationEvent; 9 import javax.xml.bind.ValidationEventHandler; 10 import javax.xml.bind.helpers.NotIdentifiableEventImpl; 11 import javax.xml.bind.helpers.ValidationEventLocatorImpl; 12 13 import org.xml.sax.ContentHandler ; 14 import org.xml.sax.SAXException ; 15 import org.xml.sax.helpers.AttributesImpl ; 16 17 import com.sun.xml.bind.JAXBAssertionError; 18 import com.sun.xml.bind.JAXBObject; 19 import com.sun.xml.bind.marshaller.IdentifiableObject; 20 import com.sun.xml.bind.marshaller.Messages; 21 import com.sun.xml.bind.marshaller.NamespacePrefixMapper; 22 import com.sun.xml.bind.serializer.AbortSerializationException; 23 import com.sun.xml.bind.serializer.Util; 24 25 34 public class SAXMarshaller implements XMLSerializer 35 { 36 40 private final AttributesImpl attributes = new AttributesImpl (); 41 42 43 private final ContentHandler writer; 44 45 46 private final MarshallerImpl owner; 47 48 49 private final Set idReferencedObjects = new HashSet (); 50 51 52 private final Set objectsWithId = new HashSet (); 53 54 55 private JAXBObject currentTarget; 56 57 61 public SAXMarshaller( ContentHandler _writer, NamespacePrefixMapper prefixMapper, MarshallerImpl _owner ) { 62 this.writer = _writer; 63 this.owner = _owner; 64 this.nsContext = new NamespaceContextImpl( 65 prefixMapper!=null?prefixMapper:defaultNamespacePrefixMapper); 66 } 67 68 69 private final NamespaceContextImpl nsContext; 70 71 public NamespaceContext2 getNamespaceContext() { return nsContext; } 72 73 79 80 private String [] elementStack = new String [16];; 81 private int elementLen=0; 82 83 84 85 private void pushElement( String uri, String local ) { 86 if(elementStack.length==elementLen) { 87 String [] buf = new String [elementStack.length*2]; 89 System.arraycopy( elementStack, 0, buf, 0, elementStack.length ); 90 elementStack = buf; 91 } 92 elementStack[elementLen++] = uri; 93 elementStack[elementLen++] = local; 94 } 95 96 private void popElement() { elementLen-=2; } 97 98 private String getCurrentElementUri() { return elementStack[elementLen-2]; } 99 private String getCurrentElementLocal() { return elementStack[elementLen-1]; } 100 101 102 103 104 105 110 public void startElement( String uri, String local ) throws SAXException { 111 boolean isRoot = false; 112 String suggestion = null; 113 if( elementLen==0 ) { 114 isRoot = true; 115 suggestion = ""; 117 } 118 119 writePendingText(); 120 nsContext.startElement(); 121 pushElement(uri,local); 123 nsContext.declareNamespace(uri,suggestion,false); 125 126 if( isRoot ) { 128 String [] uris = nsContext.getNamespacePrefixMapper().getPreDeclaredNamespaceUris(); 130 if( uris!=null ) { 131 for( int i=0; i<uris.length; i++ ) { 132 if( uris[i]!=null ) 133 nsContext.declareNamespace(uris[i],null,false); 134 } 135 } 136 } 137 } 138 139 140 private final PrefixCallback startPrefixCallback = new PrefixCallback() { 141 public void onPrefixMapping( String prefix, String nsUri ) throws SAXException { 142 writer.startPrefixMapping(prefix,nsUri); 143 } 144 }; 145 private final PrefixCallback endPrefixCallback = new PrefixCallback() { 146 public void onPrefixMapping( String prefix, String nsUri ) throws SAXException { 147 writer.endPrefixMapping(prefix); 148 } 149 }; 150 151 public void endNamespaceDecls() throws SAXException { 152 nsContext.endNamespaceDecls(); 153 } 154 155 159 public void endAttributes() throws SAXException { 160 String uri = getCurrentElementUri(); 162 String local = getCurrentElementLocal(); 163 164 String prefix = nsContext.getPrefix(uri); 165 _assert(prefix!=null); 167 String qname; 168 if(prefix.length()!=0 ) 169 qname = prefix+':'+local; 170 else 171 qname = local; 172 173 nsContext.iterateDeclaredPrefixes(startPrefixCallback); 175 176 writer.startElement( uri, local, qname, attributes ); 178 179 180 attributes.clear(); 182 183 textBuf.setLength(0); 185 } 186 187 191 public void endElement() throws SAXException { 192 writePendingText(); 193 194 String uri = getCurrentElementUri(); 195 String local = getCurrentElementLocal(); 196 197 String prefix = nsContext.getPrefix(uri); 198 _assert(prefix!=null); 200 String qname; 201 if(prefix.length()!=0) 202 qname = prefix+':'+local; 203 else 204 qname = local; 205 206 writer.endElement( uri, local, qname ); 207 208 nsContext.iterateDeclaredPrefixes(endPrefixCallback); 211 212 popElement(); 213 214 textBuf.setLength(0); 216 217 nsContext.endElement(); 218 } 219 220 221 222 private final StringBuffer textBuf = new StringBuffer (); 223 224 261 public void text( String text, String fieldName ) throws SAXException { 262 if(text==null) { 265 reportError(Util.createMissingObjectError(currentTarget,fieldName)); 266 return; 267 } 268 269 if(textBuf.length()!=0) 270 textBuf.append(' '); 271 textBuf.append(text); 272 } 273 274 278 private void writePendingText() throws SAXException { 279 int len = textBuf.length(); 281 282 if(len!=0) 283 writer.characters( textBuf.toString().toCharArray(), 0, len ); 284 } 285 286 300 public void startAttribute( String uri, String local ) { 301 textBuf.setLength(0); 303 304 this.attNamespaceUri = uri; 306 this.attLocalName = local; 307 } 308 309 private String attNamespaceUri; 311 private String attLocalName; 312 313 public void endAttribute() { 314 325 String qname; 326 if(attNamespaceUri.length()==0) { 327 qname = attLocalName; 329 } else { 330 qname = nsContext.declareNamespace(attNamespaceUri,null,true)+':'+attLocalName; 331 } 332 333 attributes.addAttribute(attNamespaceUri,attLocalName,qname,"CDATA",textBuf.toString()); 334 } 335 336 public String onID( IdentifiableObject owner, String value ) throws SAXException { 337 objectsWithId.add(owner); 338 return value; 339 } 340 public String onIDREF( IdentifiableObject obj ) throws SAXException { 341 idReferencedObjects.add(obj); 342 String id = obj.____jaxb____getId(); 343 if(id==null) { 344 reportError( new NotIdentifiableEventImpl( 345 ValidationEvent.ERROR, 346 Messages.format(Messages.ERR_NOT_IDENTIFIABLE), 347 new ValidationEventLocatorImpl(obj) ) ); 348 } 349 return id; 350 } 351 352 void reconcileID() throws AbortSerializationException { 353 idReferencedObjects.removeAll(objectsWithId); 355 356 for( Iterator itr=idReferencedObjects.iterator(); itr.hasNext(); ) { 357 IdentifiableObject o = (IdentifiableObject)itr.next(); 358 reportError( new NotIdentifiableEventImpl( 359 ValidationEvent.ERROR, 360 Messages.format(Messages.ERR_DANGLING_IDREF,o.____jaxb____getId()), 361 new ValidationEventLocatorImpl(o) ) ); 362 } 363 364 idReferencedObjects.clear(); 366 objectsWithId.clear(); 367 } 368 369 370 371 public void childAsBody( JAXBObject o, String fieldName ) throws SAXException { 372 if(o==null) { 373 reportMissingObjectError(fieldName); 376 return; 379 } 380 381 JAXBObject oldTarget = currentTarget; 382 currentTarget = o; 383 384 owner.context.getGrammarInfo().castToXMLSerializable(o).serializeBody(this); 385 386 currentTarget = oldTarget; 387 } 388 389 public void childAsAttributes( JAXBObject o, String fieldName ) throws SAXException { 390 if(o==null) { 391 reportMissingObjectError(fieldName); 392 return; 393 } 394 395 JAXBObject oldTarget = currentTarget; 396 currentTarget = o; 397 398 owner.context.getGrammarInfo().castToXMLSerializable(o).serializeAttributes(this); 399 400 currentTarget = oldTarget; 401 } 402 403 public void childAsURIs( JAXBObject o, String fieldName ) throws SAXException { 404 if(o==null) { 405 reportMissingObjectError(fieldName); 406 return; 407 } 408 409 JAXBObject oldTarget = currentTarget; 410 currentTarget = o; 411 412 owner.context.getGrammarInfo().castToXMLSerializable(o).serializeURIs(this); 413 414 currentTarget = oldTarget; 415 } 416 417 418 public void reportError( ValidationEvent ve ) throws AbortSerializationException { 419 ValidationEventHandler handler; 420 421 try { 422 handler = owner.getEventHandler(); 423 } catch( JAXBException e ) { 424 throw new AbortSerializationException(e); 425 } 426 427 if(!handler.handleEvent(ve)) { 428 if(ve.getLinkedException() instanceof Exception ) 429 throw new AbortSerializationException((Exception )ve.getLinkedException()); 430 else 431 throw new AbortSerializationException(ve.getMessage()); 432 } 433 } 434 435 436 public void reportMissingObjectError(String fieldName) throws SAXException { 437 reportError(Util.createMissingObjectError(currentTarget,fieldName)); 438 } 439 440 441 private static void _assert( boolean b ) { 442 if(!b) 443 throw new JAXBAssertionError(); 444 } 445 446 450 private static NamespacePrefixMapper defaultNamespacePrefixMapper = new NamespacePrefixMapper() { 451 public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { 452 if( namespaceUri.equals("http://www.w3.org/2001/XMLSchema-instance") ) 453 return "xsi"; 454 return suggestion; 455 } 456 }; 457 } 458 | Popular Tags |