1 16 package org.apache.cocoon.components.source.impl; 17 18 19 import java.io.InputStream ; 20 import java.io.IOException ; 21 import java.io.OutputStream ; 22 import java.io.ByteArrayOutputStream ; 23 import java.io.ByteArrayInputStream ; 24 import java.net.MalformedURLException ; 25 import java.util.Map ; 26 27 import org.apache.avalon.framework.configuration.ConfigurationException; 28 import org.apache.avalon.framework.logger.Logger; 29 import org.apache.avalon.framework.service.ServiceException; 30 import org.apache.avalon.framework.service.ServiceManager; 31 import org.apache.avalon.framework.service.ServiceSelector; 32 33 import org.apache.excalibur.source.ModifiableSource; 34 import org.apache.excalibur.source.SourceException; 35 import org.apache.excalibur.source.impl.AbstractSource; 36 import org.apache.excalibur.xml.sax.SAXParser; 37 import org.apache.excalibur.xml.sax.XMLizable; 38 39 import org.apache.cocoon.components.modules.input.InputModule; 40 import org.apache.cocoon.components.modules.output.OutputModule; 41 import org.apache.cocoon.serialization.XMLSerializer; 42 import org.apache.cocoon.util.jxpath.DOMFactory; 43 import org.apache.cocoon.xml.dom.DOMBuilder; 44 import org.apache.cocoon.xml.dom.DOMStreamer; 45 46 import org.apache.commons.jxpath.JXPathContext; 47 48 import org.w3c.dom.Document ; 49 import org.w3c.dom.Node ; 50 51 import org.xml.sax.ContentHandler ; 52 import org.xml.sax.InputSource ; 53 import org.xml.sax.SAXException ; 54 55 72 73 public class XModuleSource 74 extends AbstractSource 75 implements ModifiableSource, XMLizable, DOMBuilder.Listener { 76 77 private final static String SCHEME = "xmodule"; 78 private String attributeType; 79 private String attributeName; 80 private String xPath; 81 private ServiceManager manager; 82 private Map objectModel; 83 private Logger logger; 84 85 89 public XModuleSource( Map objectModel, String uri, 90 ServiceManager manager, Logger logger ) 91 throws MalformedURLException { 92 93 this.objectModel = objectModel; 94 this.manager = manager; 95 this.logger = logger; 96 97 setSystemId( uri ); 98 99 int start = 0; 101 int end = uri.indexOf( ':' ); 102 if ( end == -1 ) 103 throw new MalformedURLException ("Malformed uri for xmodule source (cannot find scheme) : " + uri); 104 105 String scheme = uri.substring( start, end ); 106 if ( !SCHEME.equals( scheme ) ) 107 throw new MalformedURLException ("Malformed uri for a xmodule source : " + uri); 108 109 setScheme( scheme ); 110 111 start = end + 1; 113 end = uri.indexOf( ':', start ); 114 if ( end == -1 ) { 115 throw new MalformedURLException ("Malformed uri for xmodule source (cannot find attribute type) : " + uri); 116 } 117 this.attributeType = uri.substring( start, end ); 118 119 start = end + 1; 121 end = uri.indexOf( '#', start ); 122 123 if ( end == -1 ) 124 end = uri.length(); 125 126 if ( end == start ) 127 throw new MalformedURLException ("Malformed uri for xmodule source (cannot find attribute name) : " + uri); 128 129 this.attributeName = uri.substring( start, end ); 130 131 start = end + 1; 133 this.xPath = start < uri.length() ? uri.substring( start ) : ""; 134 } 135 136 140 141 public void toSAX(ContentHandler handler) 142 throws SAXException { 143 144 Object obj = getInputAttribute( this.attributeType, this.attributeName ); 145 if ( obj == null ) 146 throw new SAXException ( " The attribute: " + this.attributeName + 147 " is empty" ); 148 149 if ( !(this.xPath.length() == 0 || this.xPath.equals( "/" )) ) { 150 JXPathContext context = JXPathContext.newContext( obj ); 151 152 obj = context.getPointer( this.xPath ).getNode(); 153 154 if ( obj == null ) 155 throw new SAXException ( "the xpath: " + this.xPath + 156 " applied on the attribute: " + 157 this.attributeName + 158 " returns null"); 159 } 160 161 if ( obj instanceof Document ) { 162 DOMStreamer domStreamer = new DOMStreamer( handler ); 163 domStreamer.stream( (Document )obj ); 164 } else if ( obj instanceof Node ) { 165 DOMStreamer domStreamer = new DOMStreamer( handler ); 166 handler.startDocument(); 167 domStreamer.stream( (Node )obj ); 168 handler.endDocument(); 169 } else if ( obj instanceof XMLizable ) { 170 ((XMLizable)obj).toSAX( handler ); 171 } else { 172 throw new SAXException ( "The object type: " + obj.getClass() + 173 " could not be serialized to XML: " + obj ); 174 } 175 } 176 177 182 public InputStream getInputStream() throws IOException , SourceException { 184 if ( this.logger.isDebugEnabled() ) { 185 this.logger.debug( "Getting InputStream for " + getURI() ); 186 } 187 188 190 XMLSerializer serializer = new XMLSerializer(); 191 ByteArrayInputStream inputStream = null; 192 193 try { 194 ByteArrayOutputStream outputStream = new ByteArrayOutputStream ( 2048 ); 195 serializer.setOutputStream( outputStream ); 196 toSAX( serializer ); 197 inputStream = new ByteArrayInputStream ( outputStream.toByteArray() ); 198 } catch ( SAXException se ) { 199 logger.error( "SAX exception!", se ); 200 throw new SourceException( "Serializing SAX to a ByteArray failed!", se ); 201 } 202 203 return inputStream; 204 } 205 206 212 public boolean exists() { 213 boolean exists = false; 214 try { 215 exists = getInputAttribute( this.attributeType, this.attributeName ) != null; 216 } catch ( SAXException e ) { 217 exists = false; 218 } 219 return exists; 220 } 221 222 229 public OutputStream getOutputStream() throws IOException { 230 return new DOMOutputStream(); 231 } 232 233 236 public void delete() throws SourceException { 237 if ( !(this.xPath.length() == 0 || this.xPath.equals( "/" )) ) { 238 Object value; 239 try { 240 value = getInputAttribute( this.attributeType, this.attributeName ); 241 } catch ( SAXException e ) { 242 throw new SourceException( "delete: ", e ); 243 } 244 if ( value == null ) 245 throw new SourceException( " The attribute: " + this.attributeName + 246 " is empty" ); 247 248 JXPathContext context = JXPathContext.newContext( value ); 249 context.removeAll( this.xPath ); 250 } else { 251 try { 252 setOutputAttribute( this.attributeType, this.attributeName, null ); 253 } catch ( SAXException e ) { 254 throw new SourceException( "delete: ", e ); 255 } 256 } 257 } 258 259 264 public void deleteTest() throws SourceException { 265 delete(); 266 } 267 268 274 public boolean canCancel( OutputStream stream ) { return false; } 275 276 282 public void cancel(OutputStream stream) throws IOException {} 283 284 294 public ContentHandler getContentHandler() { 295 return new DOMBuilder( this ); 296 } 297 298 public void notify( Document insertDoc ) throws SAXException { 299 300 if ( !(this.xPath.length() == 0 || this.xPath.equals( "/" )) ) { 303 304 Object value = getInputAttribute( this.attributeType, this.attributeName ); 305 if ( value == null ) 306 throw new SAXException ( " The attribute: " + this.attributeName + 307 " is empty" ); 308 309 JXPathContext context = JXPathContext.newContext( value ); 310 311 if ( value instanceof Document ) { 312 Document doc = (Document )value; 317 318 Node importedNode = 319 doc.importNode( insertDoc.getDocumentElement(), true ); 320 321 context.setLenient( true ); 322 context.setFactory( new DOMFactory() ); 323 context.createPathAndSetValue( this.xPath, importedNode ); 324 } else { 325 context.setValue( this.xPath, insertDoc ); 328 } 329 330 } else { 331 setOutputAttribute( this.attributeType, this.attributeName, insertDoc ); 332 } 333 } 334 335 private class DOMOutputStream extends ByteArrayOutputStream { 336 public void close() throws IOException { 337 SAXParser parser = null; 338 try { 339 parser = (SAXParser)XModuleSource.this.manager.lookup( SAXParser.ROLE ); 340 341 parser.parse( new InputSource ( new ByteArrayInputStream ( super.toByteArray() ) ), 342 XModuleSource.this.getContentHandler()); 343 } catch (Exception e){ 344 throw new IOException ("Exception during processing of " + 345 XModuleSource.super.getURI() + 346 e.getMessage()); 347 } finally { 348 if (parser != null) XModuleSource.this.manager.release( parser ); 349 } 350 super.close(); 351 } 352 } 353 354 355 private Object getInputAttribute( String inputModuleName, String attributeName ) 356 throws SAXException { 357 Object obj; 358 ServiceSelector selector = null; 359 InputModule inputModule = null; 360 try { 361 selector = (ServiceSelector) this.manager.lookup( InputModule.ROLE + "Selector" ); 362 inputModule = (InputModule) selector.select( inputModuleName ); 363 obj = inputModule.getAttribute( attributeName, null, this.objectModel ); 364 365 } catch ( ServiceException e ) { 366 throw new SAXException ( "Could not find an InputModule of the type " + 367 inputModuleName , e ); 368 } catch ( ConfigurationException e ) { 369 throw new SAXException ( "Could not find an attribute: " + attributeName + 370 " from the InputModule " + inputModuleName, e ); 371 } finally { 372 if ( inputModule != null ) selector.release( inputModule ); 373 this.manager.release( selector ); 374 } 375 376 return obj; 377 } 378 379 private void setOutputAttribute( String outputModuleName, 380 String attributeName, Object value ) 381 throws SAXException { 382 ServiceSelector selector = null; 383 OutputModule outputModule = null; 384 try { 385 selector = (ServiceSelector) this.manager.lookup( OutputModule.ROLE + "Selector" ); 386 outputModule = (OutputModule) selector.select( outputModuleName ); 387 outputModule.setAttribute( null, this.objectModel, attributeName, value ); 388 outputModule.commit( null, this.objectModel ); 389 390 } catch ( ServiceException e ) { 391 throw new SAXException ( "Could not find an OutputModule of the type " + 392 outputModuleName , e ); 393 } finally { 394 if ( outputModule != null ) selector.release( outputModule ); 395 this.manager.release( selector ); 396 } 397 } 398 } 399 | Popular Tags |