Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/sax/XMLTeePipe.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/sax/XMLTeePipe.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/sax/XMLTeePipe.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/sax/XMLTeePipe.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,155 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.sax; + +import org.apache.cocoon.xml.XMLConsumer; +import org.apache.cocoon.xml.XMLPipe; +import org.apache.cocoon.xml.XMLProducer; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + + +/** + * This is a simple Tee Component. + * The incoming events are forwarded to two other components. + * + * @author Carsten Ziegeler + * @version CVS $Id: XMLTeePipe.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ + +public final class XMLTeePipe +implements XMLPipe { + + /** + * Set the XMLConsumer that will receive XML data. + */ + public void setConsumer(XMLConsumer consumer) { + ((XMLProducer)this.firstConsumer).setConsumer(consumer); + } + + private XMLConsumer firstConsumer; + private XMLConsumer secondConsumer; + + /** + * Create a new XMLTeePipe with two consumers + */ + public XMLTeePipe(XMLConsumer firstPipe, + XMLConsumer secondConsumer) { + this.firstConsumer = firstPipe; + this.secondConsumer = secondConsumer; + } + + public void recycle() { + this.firstConsumer = null; + this.secondConsumer = null; + } + + public void startDocument() throws SAXException { + this.firstConsumer.startDocument(); + this.secondConsumer.startDocument(); + } + + public void endDocument() throws SAXException { + this.firstConsumer.endDocument(); + this.secondConsumer.endDocument(); + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + this.firstConsumer.startPrefixMapping(prefix, uri); + this.secondConsumer.startPrefixMapping(prefix, uri); + } + + public void endPrefixMapping(String prefix) throws SAXException { + this.firstConsumer.endPrefixMapping(prefix); + this.secondConsumer.endPrefixMapping(prefix); + } + + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) + throws SAXException { + this.firstConsumer.startElement(namespaceURI, localName, qName, atts); + this.secondConsumer.startElement(namespaceURI, localName, qName, atts); + } + + public void endElement(String namespaceURI, String localName, String qName) + throws SAXException { + this.firstConsumer.endElement(namespaceURI, localName, qName); + this.secondConsumer.endElement(namespaceURI, localName, qName); + } + + public void characters(char[] ch, int start, int length) throws SAXException { + this.firstConsumer.characters(ch, start, length); + this.secondConsumer.characters(ch, start, length); + } + + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + this.firstConsumer.ignorableWhitespace(ch, start, length); + this.secondConsumer.ignorableWhitespace(ch, start, length); + } + + public void processingInstruction(String target, String data) throws SAXException { + this.firstConsumer.processingInstruction(target, data); + this.secondConsumer.processingInstruction(target, data); + } + + public void setDocumentLocator(Locator locator) { + this.firstConsumer.setDocumentLocator(locator); + this.secondConsumer.setDocumentLocator(locator); + } + + public void skippedEntity(String name) throws SAXException { + this.firstConsumer.skippedEntity(name); + this.secondConsumer.skippedEntity(name); + } + + public void startDTD(String name, String public_id, String system_id) + throws SAXException { + this.firstConsumer.startDTD(name, public_id, system_id); + this.secondConsumer.startDTD(name, public_id, system_id); + } + + public void endDTD() throws SAXException { + this.firstConsumer.endDTD(); + this.secondConsumer.endDTD(); + } + + public void startEntity(String name) throws SAXException { + this.firstConsumer.startEntity(name); + this.secondConsumer.startEntity(name); + } + + public void endEntity(String name) throws SAXException { + this.firstConsumer.endEntity(name); + this.secondConsumer.endEntity(name); + } + + public void startCDATA() throws SAXException { + this.firstConsumer.startCDATA(); + this.secondConsumer.startCDATA(); + } + + public void endCDATA() throws SAXException { + this.firstConsumer.endCDATA(); + this.secondConsumer.endCDATA(); + } + + public void comment(char ary[], int start, int length) + throws SAXException { + this.firstConsumer.comment(ary, start, length); + this.secondConsumer.comment(ary, start, length); + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/sax/XMLTeePipe.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/CocoonSourceResolver.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/CocoonSourceResolver.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/CocoonSourceResolver.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/CocoonSourceResolver.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,285 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source; + + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +import org.apache.avalon.framework.activity.Disposable; +import org.apache.avalon.framework.context.Context; +import org.apache.avalon.framework.context.ContextException; +import org.apache.avalon.framework.context.Contextualizable; +import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.Processor; +import org.apache.cocoon.core.Core; +import org.apache.cocoon.core.container.ComponentLocatorWrapper; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.cocoon.environment.internal.EnvironmentHelper; +import org.apache.cocoon.sitemap.ComponentLocator; +import org.apache.cocoon.sitemap.Sitemap; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceException; +import org.apache.excalibur.source.SourceFactory; +import org.apache.excalibur.source.URIAbsolutizer; + +/** + * This is the default implementation of the {@link SourceResolver} for + * Cocoon. The implementation is based on the original source resolver implementation + * from the Excalibur project. + * @since 2.2 + * + * @author Carsten Ziegeler + * @version CVS $Id: CocoonSourceResolver.java 292497 2005-09-29 18:11:42Z bloritsch $ +*/ +public class CocoonSourceResolver +extends AbstractLogEnabled +implements SourceResolver, Contextualizable, Serviceable, Disposable, ThreadSafe { + + /** A (optional) custom source resolver */ + protected org.apache.excalibur.source.SourceResolver customResolver; + + /** The service manager */ + protected ServiceManager manager; + + /** The base URL */ + protected URL baseURL; + + /** The core */ + protected Core core; + + /** + * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context) + */ + public void contextualize( Context context ) + throws ContextException { + try { + if ( context.get( "context-root" ) instanceof URL ) { + this.baseURL = (URL)context.get( "context-root" ); + } else { + this.baseURL = ( (File)context.get( "context-root" ) ).toURL(); + } + } catch( ContextException ce ) { + // set the base URL to the current directory + try { + this.baseURL = new File( System.getProperty( "user.dir" ) ).toURL(); + if( this.getLogger().isDebugEnabled() ) { + this.getLogger().debug( "SourceResolver: Using base URL: " + this.baseURL ); + } + } catch( MalformedURLException mue ) { + throw new ContextException( "Malformed URL for user.dir, and no container.rootDir exists", mue ); + } + } catch( MalformedURLException mue ) { + throw new ContextException( "Malformed URL for container.rootDir", mue ); + } + } + + /** + * @see org.apache.excalibur.source.SourceResolver#resolveURI(java.lang.String, java.lang.String, java.util.Map) + */ + public Source resolveURI(String location, String baseURI, Map parameters) + throws MalformedURLException, IOException, SourceException { + if ( baseURI == null ) { + final Processor processor = EnvironmentHelper.getCurrentProcessor(); + if ( processor != null ) { + baseURI = processor.getContext(); + } + } + if ( this.customResolver != null ) { + return this.customResolver.resolveURI(location, baseURI, parameters); + } + if( this.getLogger().isDebugEnabled() ) { + this.getLogger().debug( "Resolving '" + location + "' with base '" + baseURI + "' in context '" + this.baseURL + "'" ); + } + if( location == null ) { + throw new MalformedURLException( "Invalid System ID" ); + } + if( null != baseURI && org.apache.excalibur.source.SourceUtil.indexOfSchemeColon(baseURI) == -1 ) { + throw new MalformedURLException( "BaseURI is not valid, it must contain a protocol: " + baseURI ); + } + + if( baseURI == null ) { + baseURI = this.baseURL.toExternalForm(); + } + + String systemID = location; + // special handling for windows file paths + if( location.length() > 1 && location.charAt( 1 ) == ':' ) { + systemID = "file:/" + location; + } else if( location.length() > 2 && location.charAt(0) == '/' && location.charAt(2) == ':' ) { + systemID = "file:" + location; + } + + // determine protocol (scheme): first try to get the one of the systemID, if that fails, take the one of the baseURI + String protocol; + int protocolPos = org.apache.excalibur.source.SourceUtil.indexOfSchemeColon(systemID); + if( protocolPos != -1 ) { + protocol = systemID.substring( 0, protocolPos ); + } else { + protocolPos = org.apache.excalibur.source.SourceUtil.indexOfSchemeColon(baseURI); + if( protocolPos != -1 ) { + protocol = baseURI.substring( 0, protocolPos ); + } else { + protocol = "*"; + } + } + + final ComponentLocator m = this.getComponentLocator(); + + Source source = null; + // search for a SourceFactory implementing the protocol + SourceFactory factory = null; + try { + factory = this.getSourceFactory( m, protocol ); + systemID = this.absolutize( factory, baseURI, systemID ); + if( getLogger().isDebugEnabled() ) { + getLogger().debug( "Resolved to systemID : " + systemID ); + } + source = factory.getSource( systemID, parameters ); + } catch( final ProcessingException ce ) { + // no selector available, use fallback + } finally { + m.release( factory ); + } + + if( null == source ) { + try { + factory = this.getSourceFactory( m, "*"); + systemID = this.absolutize( factory, baseURI, systemID ); + if( getLogger().isDebugEnabled() ) { + getLogger().debug( "Resolved to systemID : " + systemID ); + } + source = factory.getSource( systemID, parameters ); + } catch (ProcessingException se ) { + throw new SourceException( "Unable to select source factory for " + systemID, se ); + } finally { + m.release(factory); + } + } + + return source; + } + + /** + * @see org.apache.excalibur.source.SourceResolver#resolveURI(java.lang.String) + */ + public Source resolveURI(String location) + throws MalformedURLException, IOException, SourceException { + return this.resolveURI(location, null, null); + } + + /** + * Obtain a reference to the SourceResolver with "/Cocoon" hint + * + * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) + */ + public void service(ServiceManager manager) throws ServiceException { + this.manager = manager; + if ( this.manager.hasService(org.apache.excalibur.source.SourceResolver.ROLE+"/Cocoon")) { + this.customResolver = (org.apache.excalibur.source.SourceResolver) + this.manager.lookup(org.apache.excalibur.source.SourceResolver.ROLE+"/Cocoon"); + } + this.core = (Core)this.manager.lookup(Core.ROLE); + } + + /** + * @see org.apache.avalon.framework.activity.Disposable#dispose() + */ + public void dispose() { + if ( this.manager != null ) { + this.manager.release( this.customResolver ); + this.customResolver = null; + this.manager.release(this.core); + this.core = null; + this.manager = null; + } + } + + /** + * Get the component locator. + */ + protected ComponentLocator getComponentLocator() { + ComponentLocator l = null; + final Sitemap sitemap = this.core.getCurrentSitemap(); + if ( sitemap != null ) { + l = sitemap.getComponentLocator(); + } + if ( l == null ) { + l = new ComponentLocatorWrapper(this.manager); + } + return l; + } + + /** + * Get the SourceFactory + */ + protected SourceFactory getSourceFactory(ComponentLocator m, String scheme) + throws ProcessingException { + return (SourceFactory)m.getComponent(SourceFactory.ROLE + '/' + scheme); + } + + /** + * @see org.apache.excalibur.source.SourceResolver#release(org.apache.excalibur.source.Source) + */ + public void release(Source source) { + if( source == null ) return; + + if ( this.customResolver != null ) { + this.customResolver.release( source ); + } else { + final ComponentLocator m = this.getComponentLocator(); + + // search for a SourceFactory implementing the protocol + final String scheme = source.getScheme(); + SourceFactory factory = null; + + try { + factory = this.getSourceFactory(m, scheme); + factory.release(source); + } catch (ProcessingException se ) { + try { + factory = this.getSourceFactory(m, "*"); + factory.release(source); + } catch (ProcessingException sse ) { + throw new SourceFactoryNotFoundException( "Unable to select source factory for " + source.getURI(), se ); + } + } finally { + m.release( factory ); + } + } + } + + /** + * Makes an absolute URI based on a baseURI and a relative URI. + */ + protected String absolutize( SourceFactory factory, String baseURI, String systemID ) { + if( factory instanceof URIAbsolutizer ) { + systemID = ((URIAbsolutizer)factory).absolutize(baseURI, systemID); + } else { + systemID = org.apache.excalibur.source.SourceUtil.absolutize(baseURI, systemID); + } + return systemID; + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/CocoonSourceResolver.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceFactoryNotFoundException.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceFactoryNotFoundException.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceFactoryNotFoundException.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceFactoryNotFoundException.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source; + +import org.apache.avalon.framework.CascadingRuntimeException; + +public final class SourceFactoryNotFoundException extends CascadingRuntimeException +{ + public SourceFactoryNotFoundException(String message) + { + super(message, null); + } + + public SourceFactoryNotFoundException(String message, Throwable cause) + { + super(message, cause); + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceFactoryNotFoundException.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceUtil.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceUtil.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceUtil.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceUtil.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,837 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.ServiceSelector; + +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.ResourceNotFoundException; +import org.apache.cocoon.environment.internal.EnvironmentHelper; +import org.apache.cocoon.serialization.Serializer; +import org.apache.cocoon.util.NetUtils; +import org.apache.cocoon.xml.IncludeXMLConsumer; +import org.apache.cocoon.xml.XMLUtils; +import org.apache.cocoon.xml.dom.DOMBuilder; +import org.apache.cocoon.xml.dom.DOMStreamer; + +import org.apache.excalibur.source.ModifiableSource; +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceException; +import org.apache.excalibur.source.SourceNotFoundException; +import org.apache.excalibur.source.SourceParameters; +import org.apache.excalibur.source.SourceResolver; +import org.apache.excalibur.xml.sax.SAXParser; +import org.apache.excalibur.xml.sax.XMLizable; +import org.apache.excalibur.xmlizer.XMLizer; +import org.apache.regexp.RE; +import org.apache.regexp.RECompiler; +import org.apache.regexp.REProgram; +import org.apache.regexp.RESyntaxException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.transform.OutputKeys; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +/** + * This class contains some utility methods for the source resolving. + * + * @author Carsten Ziegeler + * @author Stephan Michels + * @version $Id: SourceUtil.java 178779 2005-05-27 14:09:30Z vgritsenko $ + */ +public final class SourceUtil { + + private static REProgram uripattern = null; + + static { + try { + uripattern = new RECompiler().compile("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"); + } catch (RESyntaxException e) { + // Should not happen + e.printStackTrace(); + } + } + + /** Avoid instantiation */ + private SourceUtil() { + } + + /** + * Generates SAX events from the XMLizable and handle SAXException. + * + * @param source the data + */ + static public void toSAX(XMLizable source, + ContentHandler handler) + throws SAXException, IOException, ProcessingException { + try { + source.toSAX(handler); + } catch (SAXException e) { + // Unwrap ProcessingException, IOException, and extreme cases of SAXExceptions. + // Handle SourceException. + // See also handleSAXException + final Exception cause = e.getException(); + if (cause != null) { + if (cause instanceof SourceException) { + throw handle((SourceException) cause); + } + if (cause instanceof ProcessingException) { + throw (ProcessingException) cause; + } + if (cause instanceof IOException) { + throw (IOException) cause; + } + if (cause instanceof SAXException) { + throw (SAXException) cause; + } + } + + // Throw original SAX exception + throw e; + } + } + + /** + * Generates SAX events from the given source. + * + *

NOTE: If the implementation can produce lexical events, + * care should be taken that handler can actually + * directly implement the LexicalHandler interface!

+ * + * @param source the data + * @throws ProcessingException if no suitable converter is found + */ + static public void toSAX(Source source, + ContentHandler handler) + throws SAXException, IOException, ProcessingException { + toSAX(EnvironmentHelper.getSitemapServiceManager(), + source, null, handler); + } + + /** + * Generates SAX events from the given source by using XMLizer. + * Current sitemap manager will be used to lookup XMLizer. + * + *

NOTE: If the implementation can produce lexical events, + * care should be taken that handler can actually + * directly implement the LexicalHandler interface!

+ * + * @param source the data + * @throws ProcessingException if no suitable converter is found + */ + static public void toSAX(Source source, + String mimeTypeHint, + ContentHandler handler) + throws SAXException, IOException, ProcessingException { + toSAX(EnvironmentHelper.getSitemapServiceManager(), + source, mimeTypeHint, handler); + } + + /** + * Generates SAX events from the given source by using XMLizer. + * + *

NOTE: If the implementation can produce lexical events, + * care should be taken that handler can actually + * directly implement the LexicalHandler interface!

+ * + * @param source the data + * @throws ProcessingException if no suitable converter is found + */ + static public void toSAX(ServiceManager manager, + Source source, + String mimeTypeHint, + ContentHandler handler) + throws SAXException, IOException, ProcessingException { + if (source instanceof XMLizable) { + toSAX((XMLizable) source, handler); + } else { + String mimeType = source.getMimeType(); + if (null == mimeType) { + mimeType = mimeTypeHint; + } + + XMLizer xmlizer = null; + try { + xmlizer = (XMLizer) manager.lookup(XMLizer.ROLE); + xmlizer.toSAX(source.getInputStream(), + mimeType, + source.getURI(), + handler); + } catch (SourceException e) { + throw SourceUtil.handle(e); + } catch (ServiceException e) { + throw new ProcessingException("Exception during streaming source.", e); + } finally { + manager.release(xmlizer); + } + } + } + + /** + * Generates SAX events from the given source with possible URL rewriting. + * + *

NOTE: If the implementation can produce lexical events, + * care should be taken that handler can actually + * directly implement the LexicalHandler interface!

+ * + * @param source the data + * @throws ProcessingException if no suitable converter is found + */ + static public void toSAX(Source source, + ContentHandler handler, + Parameters typeParameters, + boolean filterDocumentEvent) + throws SAXException, IOException, ProcessingException { + // Test for url rewriting + if (typeParameters != null + && typeParameters.getParameter(URLRewriter.PARAMETER_MODE, null) != null) { + handler = new URLRewriter(typeParameters, handler); + } + + String mimeTypeHint = null; + if (typeParameters != null) { + mimeTypeHint = typeParameters.getParameter("mime-type", mimeTypeHint); + } + if (filterDocumentEvent) { + IncludeXMLConsumer filter = new IncludeXMLConsumer(handler); + toSAX(source, mimeTypeHint, filter); + } else { + toSAX(source, mimeTypeHint, handler); + } + } + + /** + * Generates character SAX events from the given source. + * + * @param source The data + * @param encoding The character encoding of the data + */ + static public void toCharacters(Source source, + String encoding, + ContentHandler handler) + throws SAXException, IOException, ProcessingException { + try { + Reader r = encoding == null? + new InputStreamReader(source.getInputStream()): + new InputStreamReader(source.getInputStream(), encoding); + + int len; + char[] chr = new char[4096]; + try { + while ((len = r.read(chr)) > 0) { + handler.characters(chr, 0, len); + } + } finally { + r.close(); + } + } catch (SAXException e) { + handleSAXException(source.getURI(), e); + } + } + + /** + * Generates SAX events from the given source by parsing it. + * + *

NOTE: If the implementation can produce lexical events, + * care should be taken that handler can actually + * directly implement the LexicalHandler interface!

+ * + * @param source the data + * @throws ProcessingException if no suitable converter is found + */ + static public void parse(ServiceManager manager, + Source source, + ContentHandler handler) + throws SAXException, IOException, ProcessingException { + if (source instanceof XMLizable) { + toSAX((XMLizable) source, handler); + } else { + SAXParser parser = null; + try { + parser = (SAXParser) manager.lookup(SAXParser.ROLE); + parser.parse(getInputSource(source), handler); + } catch (SourceException e) { + throw SourceUtil.handle(e); + } catch (ServiceException e) { + throw new ProcessingException("Exception during parsing source.", e); + } finally { + manager.release(parser); + } + } + } + + /** + * Generates a DOM from the given source + * @param source The data + * + * @return Created DOM document. + * + * @throws IOException If a io exception occurs. + * @throws ProcessingException if no suitable converter is found + * @throws SAXException If a SAX exception occurs. + */ + static public Document toDOM(Source source) + throws SAXException, IOException, ProcessingException { + DOMBuilder builder = new DOMBuilder(); + + toSAX(source, builder); + + Document document = builder.getDocument(); + if (document == null) { + throw new ProcessingException("Could not build DOM for '" + + source.getURI() + "'"); + } + + return document; + } + + /** + * Generates a DOM from the given source + * @param source The data + * + * @return Created DOM document. + * + * @throws IOException If a io exception occurs. + * @throws ProcessingException if no suitable converter is found + * @throws SAXException If a SAX exception occurs. + */ + static public Document toDOM(ServiceManager manager, Source source) + throws SAXException, IOException, ProcessingException { + DOMBuilder builder = new DOMBuilder(); + + toSAX(manager, source, null, builder); + + Document document = builder.getDocument(); + if (document == null) { + throw new ProcessingException("Could not build DOM for '" + + source.getURI() + "'"); + } + + return document; + } + + /** + * Generates a DOM from the given source + * @param source The data + * + * @return Created DOM document. + * + * @throws IOException If a io exception occurs. + * @throws ProcessingException if no suitable converter is found + * @throws SAXException If a SAX exception occurs. + */ + static public Document toDOM(ServiceManager manager, String mimeTypeHint, Source source) + throws SAXException, IOException, ProcessingException { + DOMBuilder builder = new DOMBuilder(); + + toSAX(manager, source, mimeTypeHint, builder); + + Document document = builder.getDocument(); + if (document == null) { + throw new ProcessingException("Could not build DOM for '" + + source.getURI() + "'"); + } + + return document; + } + + /** + * Make a ProcessingException from a SourceException. + * If the exception is a SourceNotFoundException then a + * ResourceNotFoundException is thrown. + * + * @param se Source exception + * @return Created processing exception. + */ + static public ProcessingException handle(SourceException se) { + if (se instanceof SourceNotFoundException) { + return new ResourceNotFoundException("Resource not found.", se); + } + return new ProcessingException("Exception during source resolving.", + se); + } + + /** + * Make a ProcessingException from a SourceException. + * If the exception is a SourceNotFoundException then a + * ResourceNotFoundException is thrown. + * + * @param message Additional exception message. + * @param se Source exception. + * @return Created processing exception. + */ + static public ProcessingException handle(String message, + SourceException se) { + if (se instanceof SourceNotFoundException) { + return new ResourceNotFoundException(message, se); + } + return new ProcessingException(message, se); + } + + /** + * Handle SAXException catched in Generator's generate method. + * + * @param source Generator's source + * @param e SAXException happened in the generator's generate method. + */ + static public void handleSAXException(String source, SAXException e) + throws ProcessingException, IOException, SAXException { + final Exception cause = e.getException(); + if (cause != null) { + // Unwrap ProcessingException, IOException, and extreme cases of SAXExceptions. + // Handle SourceException. + // See also toSax(XMLizable, ContentHandler) + if (cause instanceof SourceException) { + throw handle((SourceException) cause); + } + if (cause instanceof ProcessingException) { + throw (ProcessingException) cause; + } + if (cause instanceof IOException) { + throw (IOException) cause; + } + if (cause instanceof SAXException) { + throw (SAXException) cause; + } + throw new ProcessingException("Could not read resource " + + source, cause); + } + throw e; + } + + /** + * Get an InputSource object + * + * @param source Source. + * + * @return Input stream of the source. + * + * @throws IOException If a io exception occurs. + * @throws ProcessingException If an exception occurs during + * processing. + */ + static public InputSource getInputSource(Source source) + throws IOException, ProcessingException { + try { + final InputSource newObject = new InputSource(source.getInputStream()); + + newObject.setSystemId(source.getURI()); + return newObject; + } catch (SourceException se) { + throw handle(se); + } + } + + /** + * Get a Source object + * + * @param uri URI of the source. + * @param typeParameters Type of Source query. Currently, only + * method parameter (value typically GET or + * POST) is recognized. May be null. + * @param resourceParameters Parameters of the source. May be null + * @param resolver Resolver for the source. + * + * @return The resolved source. + * + * @throws IOException If a io exception occurs. + * @throws SAXException If a SAX exception occurs. + * @throws SourceException If the source an exception throws. + */ + static public Source getSource(String uri, + Parameters typeParameters, + SourceParameters resourceParameters, + SourceResolver resolver) + throws IOException, SAXException, SourceException { + + // first step: encode parameters which are already appended to the url + int queryPos = uri.indexOf('?'); + if (queryPos != -1) { + String queryString = uri.substring(queryPos+1); + SourceParameters queries = new SourceParameters(queryString); + + if (queries.hasParameters()) { + StringBuffer buffer = new StringBuffer(uri.substring(0, queryPos)); + char separator = '?'; + + Iterator i = queries.getParameterNames(); + while (i.hasNext()) { + String current = (String) i.next(); + Iterator values = queries.getParameterValues(current); + while (values.hasNext()) { + buffer.append(separator) + .append(current) + .append('=') + .append(NetUtils.encode((String) values.next(), "utf-8")); + separator = '&'; + } + } + uri = buffer.toString(); + } + } + + String method = ((typeParameters!=null) + ? typeParameters.getParameter("method", "GET") + : "GET"); + if (method.equalsIgnoreCase("POST") && + (resourceParameters == null || + !resourceParameters.hasParameters())) { + method = "GET"; + } + + if (uri.startsWith("cocoon:") && resourceParameters != null && + resourceParameters.hasParameters()) { + int pos = uri.indexOf(";jsessionid="); + + StringBuffer buf; + if (pos == -1) { + buf = new StringBuffer(uri); + } else { + buf = new StringBuffer(uri.substring(0, pos)); + } + buf.append(((uri.indexOf('?') == -1) ? '?' : '&')); + buf.append(resourceParameters.getEncodedQueryString()); + uri = buf.toString(); + } + + Map resolverParameters = new HashMap(); + resolverParameters.put(SourceResolver.METHOD, method); + if (typeParameters != null) { + String encoding = typeParameters.getParameter("encoding", + System.getProperty("file.encoding", "ISO-8859-1")); + if (encoding != null && !"".equals(encoding)) { + resolverParameters.put(SourceResolver.URI_ENCODING, encoding); + } + } + resolverParameters.put(SourceResolver.URI_PARAMETERS, + resourceParameters); + + return resolver.resolveURI(uri, null, resolverParameters); + } + + /** + * Write a DOM Fragment to a source. + * If the source is a ModifiableSource the interface is used. + * If not, the source is invoked with an additional parameter named + * "content" containing the XML. + * The current sitemap service manager is used to lookup the serializer. + * + * @param location URI of the Source + * @param typeParameters Type of Source query. Currently, only + * method parameter (value typically GET or + * POST) is recognized. May be null. + * @param parameters Parameters (e.g. URL params) of the source. + * May be null + * @param frag DOM fragment to serialize to the Source + * @param resolver Resolver for the source. + * @param serializerName The serializer to use + * + * @throws ProcessingException + */ + public static void writeDOM(String location, + Parameters typeParameters, + SourceParameters parameters, + DocumentFragment frag, + SourceResolver resolver, + String serializerName) + throws ProcessingException { + Source source = null; + + try { + source = SourceUtil.getSource(location, typeParameters, + parameters, resolver); + if (source instanceof ModifiableSource) { + ModifiableSource ws = (ModifiableSource) source; + + frag.normalize(); + + if (null != serializerName) { + ServiceManager manager = EnvironmentHelper.getSitemapServiceManager(); + + ServiceSelector selector = null; + Serializer serializer = null; + OutputStream oStream = null; + try { + selector = (ServiceSelector)manager.lookup(Serializer.ROLE + "Selector"); + serializer = (Serializer)selector.select(serializerName); + oStream = ws.getOutputStream(); + serializer.setOutputStream(oStream); + serializer.startDocument(); + DOMStreamer streamer = new DOMStreamer(serializer); + streamer.stream(frag); + serializer.endDocument(); + } catch (ServiceException e) { + throw new ProcessingException("Unable to lookup serializer.", e); + } finally { + if (oStream != null) { + oStream.flush(); + try { + oStream.close(); + } catch (Exception ignore) { + } + } + if (selector != null) { + selector.release(serializer); + manager.release(selector); + } + } + } else { + Properties props = XMLUtils.createPropertiesForXML(false); + props.put(OutputKeys.ENCODING, "ISO-8859-1"); + final String content = XMLUtils.serializeNode(frag, props); + OutputStream oStream = ws.getOutputStream(); + + oStream.write(content.getBytes()); + oStream.flush(); + oStream.close(); + } + } else { + String content; + if (null != serializerName) { + ServiceManager manager = EnvironmentHelper.getSitemapServiceManager(); + + ServiceSelector selector = null; + Serializer serializer = null; + ByteArrayOutputStream oStream = new ByteArrayOutputStream(); + try { + selector = (ServiceSelector)manager.lookup(Serializer.ROLE + "Selector"); + serializer = (Serializer)selector.select(serializerName); + serializer.setOutputStream(oStream); + serializer.startDocument(); + DOMStreamer streamer = new DOMStreamer(serializer); + streamer.stream(frag); + serializer.endDocument(); + } catch (ServiceException e) { + throw new ProcessingException("Unable to lookup serializer.", e); + } finally { + if (oStream != null) { + oStream.flush(); + try { + oStream.close(); + } catch (Exception ignore) { + } + } + if (selector != null) { + selector.release(serializer); + manager.release(selector); + } + } + content = oStream.toString(); + } else { + Properties props = XMLUtils.createPropertiesForXML(false); + props.put(OutputKeys.ENCODING, "ISO-8859-1"); + content = XMLUtils.serializeNode(frag, props); + } + + if (parameters == null) { + parameters = new SourceParameters(); + } else { + parameters = (SourceParameters) parameters.clone(); + } + parameters.setSingleParameterValue("content", content); + + source = SourceUtil.getSource(location, typeParameters, + parameters, resolver); + SourceUtil.toSAX(source, new DefaultHandler()); + } + } catch (SourceException e) { + throw SourceUtil.handle(e); + } catch (IOException e) { + throw new ProcessingException(e); + } catch (SAXException e) { + throw new ProcessingException(e); + } finally { + resolver.release(source); + } + } + + /** + * Read a DOM Fragment from a source + * + * @param location URI of the Source + * @param typeParameters Type of Source query. Currently, only + * method parameter (value typically GET or + * POST) is recognized. May be null. + * @param parameters Parameters (e.g. URL params) of the source. + * May be null + * @param resolver Resolver for the source. + * + * @return DOM DocumentFragment constructed from the specified + * source. + * + * @throws ProcessingException + */ + public static DocumentFragment readDOM(String location, + Parameters typeParameters, + SourceParameters parameters, + SourceResolver resolver) + throws ProcessingException { + + Source source = null; + try { + source = SourceUtil.getSource(location, typeParameters, parameters, resolver); + Document doc = SourceUtil.toDOM(source); + + DocumentFragment fragment = doc.createDocumentFragment(); + fragment.appendChild(doc.getDocumentElement()); + + return fragment; + } catch (SourceException e) { + throw SourceUtil.handle(e); + } catch (IOException e) { + throw new ProcessingException(e); + } catch (SAXException e) { + throw new ProcessingException(e); + } finally { + resolver.release(source); + } + } + + /** + * Return the scheme of a URI. Just as there are many different methods + * of access to resources, there are a variety of schemes for identifying + * such resources. + * (see RFC 2396). + * + * @param uri Uniform resource identifier. + * + * @return Scheme of the URI. + */ + public static String getScheme(String uri) { + RE re = new RE(uripattern); + if (re.match(uri)) { + return re.getParen(2); + } else { + throw new IllegalArgumentException("'" + uri + + "' is not a correct URI"); + } + } + + /** + * Return the authority of a URI. This authority is + * typically defined by an Internet-based server or a scheme-specific + * registry of naming authorities + * (see RFC 2396). + * + * @param uri Uniform resource identifier. + * + * @return Scheme of the URI. + */ + public static String getAuthority(String uri) { + RE re = new RE(uripattern); + if (re.match(uri)) { + return re.getParen(4); + } else { + throw new IllegalArgumentException("'" + uri + + "' is not a correct URI"); + } + } + + /** + * Return the path of a URI. The path contains data, specific to the + * authority (or the scheme if there is no authority component), + * identifying the resource within the scope of that scheme and authority + * (see RFC 2396). + * + * @param uri Uniform resource identifier. + * + * @return Path of the URI. + */ + public static String getPath(String uri) { + RE re = new RE(uripattern); + if (re.match(uri)) { + return re.getParen(5); + } else { + throw new IllegalArgumentException("'" + uri + + "' is not a correct URI"); + } + } + + /** + * Return the path of a URI, if the URI can't contains a authority. + * This implementation differ to the RFC 2396. + * + * @param uri Uniform resource identifier. + * + * @return Path of the URI. + */ + public static String getPathWithoutAuthority(String uri) { + RE re = new RE(uripattern); + if (re.match(uri)) { + return re.getParen(4) + re.getParen(5); + } else { + throw new IllegalArgumentException("'" + uri + + "' is not a correct URI"); + } + } + + /** + * Return the query of a URI. The query is a string of information to + * be interpreted by the resource + * (see RFC 2396). + * + * @param uri Uniform resource identifier. + * + * @return Query of the URI. + */ + public static String getQuery(String uri) { + RE re = new RE(uripattern); + if (re.match(uri)) { + return re.getParen(7); + } else { + throw new IllegalArgumentException("'" + uri + + "' is not a correct URI"); + } + } + + /** + * Return the fragment of a URI. When a URI reference is used to perform + * a retrieval action on the identified resource, the optional fragment + * identifier, consists of additional reference information to be + * interpreted by the user agent after the retrieval action has been + * successfully completed + * (see RFC 2396). + * + * @param uri Uniform resource identifier. + * + * @return Fragment of the URI. + */ + public static String getFragment(String uri) { + RE re = new RE(uripattern); + if (re.match(uri)) { + return re.getParen(9); + } else { + throw new IllegalArgumentException("'" + uri + + "' is not a correct URI"); + } + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/SourceUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/URLRewriter.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/URLRewriter.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/URLRewriter.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/URLRewriter.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,295 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.xml.XMLConsumer; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.AttributesImpl; + +import java.net.MalformedURLException; +import java.net.URL; + +/** + * This is an XMLConsumer which rewrites the stream according + * to the configuration. The configuration can have the following + * parameters: + * + * + * + *

URLRewriter rewrites only href, src, background, and action attributes. + * + * @author Carsten Ziegeler + * @version CVS $Id: URLRewriter.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public final class URLRewriter implements XMLConsumer { + + public static final String PARAMETER_MODE = "rewriteURLMode"; + public static final String MODE_NONE = "none"; + public static final String MODE_COCOON = "cocoon"; + public static final String PARAMETER_PARAMETER_NAME = "urlParameterName"; + public static final String PARAMETER_URL = "baseURL"; + public static final String PARAMETER_COCOON_URL = "cocoonURL"; + + /** The ContentHandler */ + private ContentHandler contentHandler; + /** The LexicalHandler */ + private LexicalHandler lexicalHandler; + + /** + * The mode: + * 0: no rewriting + * 1: cocoon + */ + private int mode; + + /** The base url */ + private String baseUrl; + /** The cocoon url */ + private String cocoonUrl; + + /** + * Create a new rewriter + */ + public URLRewriter(Parameters configuration, + ContentHandler contentHandler, + LexicalHandler lexicalHandler) + throws ProcessingException { + try { + this.contentHandler = contentHandler; + this.lexicalHandler = lexicalHandler; + this.mode = 0; + if (configuration != null && + MODE_COCOON.equalsIgnoreCase(configuration.getParameter(PARAMETER_MODE, null))) { + this.mode = 1; + this.baseUrl = configuration.getParameter(PARAMETER_URL); + this.cocoonUrl = configuration.getParameter(PARAMETER_COCOON_URL) + + '?' + configuration.getParameter(PARAMETER_PARAMETER_NAME) + '='; + } + } catch (org.apache.avalon.framework.parameters.ParameterException local) { + throw new ProcessingException("URLRewriter: configuration exception.", local); + } + } + + /** + * Create a new rewriter + */ + public URLRewriter(Parameters configuration, + ContentHandler contentHandler) + throws ProcessingException { + this(configuration, contentHandler, + (contentHandler instanceof LexicalHandler ? (LexicalHandler)contentHandler : null)); + } + + /** + * SAX Event Handling + */ + public void setDocumentLocator(Locator locator) { + contentHandler.setDocumentLocator(locator); + } + + /** + * SAX Event Handling + */ + public void startDocument() + throws SAXException { + contentHandler.startDocument(); + } + + /** + * SAX Event Handling + */ + public void endDocument() + throws SAXException { + contentHandler.endDocument(); + } + + /** + * SAX Event Handling + */ + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + contentHandler.startPrefixMapping(prefix,uri); + } + + /** + * SAX Event Handling + */ + public void endPrefixMapping(String prefix) + throws SAXException { + contentHandler.endPrefixMapping(prefix); + } + + /** + * SAX Event Handling + */ + public void startElement(String namespace, String name, String raw, + Attributes attr) + throws SAXException { + if (this.mode == 1) { + String attrname; + AttributesImpl newattr = null; + String value; + + for(int i = 0; i < attr.getLength(); i++) { + attrname = attr.getLocalName(i); + if (attrname.equals("href") == true || + attrname.equals("action") == true) { + if (newattr == null) { + newattr = new AttributesImpl(attr); + } + value = attr.getValue(i); + if (value.indexOf(':') == -1) { + try { + URL baseURL = new URL(new URL(this.baseUrl), value); + value = baseURL.toExternalForm(); + } catch (MalformedURLException local) { + value = attr.getValue(i); + } + } + newattr.setValue(i, this.cocoonUrl + value); + } else if (attrname.equals("src") == true || + attrname.equals("background") == true) { + if (newattr == null) { + newattr = new AttributesImpl(attr); + } + value = attr.getValue(i); + if (value.indexOf(':') == -1) { + try { + URL baseURL = new URL(new URL(this.baseUrl), value); + value = baseURL.toExternalForm(); + } catch (MalformedURLException local) { + value = attr.getValue(i); + } + } + newattr.setValue(i, value); + } + } + if (newattr != null) { + contentHandler.startElement(namespace, name, raw, newattr); + return; + } + } + contentHandler.startElement(namespace, name, raw, attr); + } + + /** + * SAX Event Handling + */ + public void endElement(String namespace, String name, String raw) + throws SAXException { + contentHandler.endElement(namespace, name, raw); + } + + /** + * SAX Event Handling + */ + public void characters(char ary[], int start, int length) + throws SAXException { + contentHandler.characters(ary, start, length); + } + + /** + * SAX Event Handling + */ + public void ignorableWhitespace(char ary[], int start, int length) + throws SAXException { + contentHandler.ignorableWhitespace(ary, start, length); + } + + /** + * SAX Event Handling + */ + public void processingInstruction(String target, String data) + throws SAXException { + contentHandler.processingInstruction(target, data); + } + + /** + * SAX Event Handling + */ + public void skippedEntity(String name) + throws SAXException { + contentHandler.skippedEntity(name); + } + + /** + * SAX Event Handling + */ + public void startDTD(String name, String public_id, String system_id) + throws SAXException { + if (lexicalHandler != null) lexicalHandler.startDTD(name, public_id, system_id); + } + + /** + * SAX Event Handling + */ + public void endDTD() throws SAXException { + if (lexicalHandler != null) lexicalHandler.endDTD(); + } + + /** + * SAX Event Handling + */ + public void startEntity(String name) throws SAXException { + if (lexicalHandler != null) lexicalHandler.startEntity(name); + } + + /** + * SAX Event Handling + */ + public void endEntity(String name) throws SAXException { + if (lexicalHandler != null) lexicalHandler.endEntity(name); + } + + /** + * SAX Event Handling + */ + public void startCDATA() throws SAXException { + if (lexicalHandler != null) lexicalHandler.startCDATA(); + } + + /** + * SAX Event Handling + */ + public void endCDATA() throws SAXException { + if (lexicalHandler != null) lexicalHandler.endCDATA(); + } + + + /** + * SAX Event Handling + */ + public void comment(char ary[], int start, int length) + throws SAXException { + if (this.lexicalHandler != null) { + lexicalHandler.comment(ary, start, length); + } + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/URLRewriter.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/SourceCredential.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/SourceCredential.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/SourceCredential.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/SourceCredential.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,85 @@ +/* + * Copyright 2001,2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cocoon.components.source.helpers; + +/** + * This class represents a credential for a given user + * + * @author Stephan Michels + * @version CVS $Id: SourceCredential.java 30941 2004-07-29 19:56:58Z vgritsenko $ + */ +public class SourceCredential { + + private String principal = "guest"; + private String password = "guest"; + + /** + * Create a new credential + * + * @param principal The user name + */ + public SourceCredential(String principal) { + this.principal = principal; + } + + /** + * Create a new credential + * + * @param principal The user name + * @param password Password + */ + public SourceCredential(String principal, String password) { + this.principal = principal; + this.password = password; + } + + /** + * Sets the principal + * + * @param principal The user name + */ + public void setPrincipal(String principal) { + this.principal = principal; + } + + /** + * Returns the principal + * + * @return Principal + */ + public String getPrincipal() { + return this.principal; + } + + /** + * Sets the password + * + * @param password Password + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Returns the password + * + * @return Password + */ + public String getPassword() { + return this.password; + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/SourceCredential.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSource.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSource.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSource.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSource.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,180 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; + +import org.apache.avalon.framework.logger.Logger; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.components.blocks.Block; +import org.apache.cocoon.environment.Environment; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.internal.BlockEnvironmentHelper; +import org.apache.cocoon.environment.internal.EnvironmentHelper; +import org.apache.cocoon.environment.wrapper.EnvironmentWrapper; +import org.apache.excalibur.source.SourceException; +import org.apache.excalibur.source.impl.AbstractSource; + +/** + * Implementation of a {@link Source} that gets its content by + * invoking the Block. + * + * @version $Id: BlockSource.java 292282 2005-09-28 19:54:16Z vgritsenko $ */ +public final class BlockSource + extends AbstractSource { + + /** The current ServiceManager */ + private final ServiceManager manager; + + /** The environment */ + private final EnvironmentWrapper environment; + + /** The name of the called block */ + private String blockName; + + /** The current block */ + private final Block block; + + /** + * Construct a new object + */ + public BlockSource(ServiceManager manager, + String uri, + Map parameters, + Logger logger) + throws MalformedURLException { + + Environment env = EnvironmentHelper.getCurrentEnvironment(); + if ( env == null ) { + throw new MalformedURLException("The block protocol can not be used outside an environment."); + } + this.manager = manager; + + this.block = BlockEnvironmentHelper.getCurrentBlock(); + if (this.block == null) + throw new MalformedURLException("Must be used in a block context " + this.getURI()); + + SitemapSourceInfo info = null; + try { + info = parseBlockURI(env, uri); + } catch (URISyntaxException e) { + throw new MalformedURLException("Malformed URI in block source " + + e.getMessage()); + } + setScheme(info.protocol); + setSystemId(info.systemId); + + // create environment... + this.environment = new EnvironmentWrapper(env, info, logger); + + // ...and put information passed from the parent request to the internal request + if ( null != parameters ) { + this.environment.getObjectModel().put(ObjectModelHelper.PARENT_CONTEXT, parameters); + } else { + this.environment.getObjectModel().remove(ObjectModelHelper.PARENT_CONTEXT); + } + + this.environment.setURI(info.prefix, info.uri); + this.environment.setAttribute(Block.NAME, this.blockName); + } + + /** + * Return an InputStream object to read from the source. + */ + public InputStream getInputStream() + throws IOException, SourceException { + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + this.environment.setOutputStream(os); + + try { + this.block.process(this.environment); + + return new ByteArrayInputStream(os.toByteArray()); + + } catch (Exception e) { + throw new SourceException("Exception during processing of " + this.getURI(), e); + } finally { + // Unhide wrapped environment output stream + this.environment.setOutputStream(null); + } + } + + /** + * Returns true always. + * @see org.apache.excalibur.source.Source#exists() + */ + public boolean exists() { + return true; + } + + /** + * Recyclable + */ + public void recycle() { + } + + // Parse the block protocol. + private SitemapSourceInfo parseBlockURI(Environment env, String blockURI) + throws URISyntaxException { + + SitemapSourceInfo info = new SitemapSourceInfo(); + // Maybe rawMode should be available for the block protocol. + info.rawMode = false; + + URI uri = new URI(blockURI); + + // Can't happen + if (!uri.isAbsolute()) { + throw new URISyntaxException(blockURI, + "Only absolute URIs are allowed for the block protocol."); + } + info.protocol = uri.getScheme(); + + String baseURI = env.getURIPrefix(); + if (baseURI.length() == 0 || !baseURI.startsWith("/")) + baseURI = "/" + baseURI; + + uri = this.block.resolveURI(new URI(uri.getSchemeSpecificPart()), + new URI(null, null, baseURI, null)); + + this.blockName = uri.getScheme(); + info.uri = uri.getPath(); + // Sub sitemap URI parsing doesn't like URIs starting with "/" + if (info.uri.length() != 0 && info.uri.startsWith("/")) + info.uri = info.uri.substring(1); + // All URIs, also relative are resolved and processed from the block manager + info.processFromRoot = true; + info.prefix = ""; + info.requestURI = info.uri; + info.queryString = uri.getQuery(); + info.view = SitemapSourceInfo.getView(info.queryString, env); + + // FIXME: This will not be a system global id, as the blockName is block local. + String ssp = (new URI(this.blockName, null, uri.getPath(), info.queryString, null)).toString(); + info.systemId = (new URI(info.protocol, ssp, null)).toString(); + + return info; + } +} + Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSource.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSourceFactory.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSourceFactory.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSourceFactory.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSourceFactory.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,87 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source.impl; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Map; + +import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.avalon.framework.thread.ThreadSafe; + +import org.apache.excalibur.source.Source; +import org.apache.excalibur.source.SourceFactory; +import org.apache.excalibur.source.URIAbsolutizer; +import org.apache.excalibur.source.SourceUtil; + +/** + * This class implements the block: protocol. + * + * + * @version $Id: BlockSourceFactory.java 292282 2005-09-28 19:54:16Z vgritsenko $ */ +public final class BlockSourceFactory + extends AbstractLogEnabled + implements SourceFactory, ThreadSafe, Serviceable, URIAbsolutizer +{ + + /** The ServiceManager */ + private ServiceManager manager; + + /* (non-Javadoc) + * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) + */ + public void service(ServiceManager manager) throws ServiceException { + this.manager = manager; + } + + /* (non-Javadoc) + * @see org.apache.excalibur.source.SourceFactory#getSource(java.lang.String, java.util.Map) + */ + public Source getSource( String location, Map parameters ) + throws MalformedURLException, IOException { + if( getLogger().isDebugEnabled() ) { + getLogger().debug( "Creating source object for " + location ); + } + + return new BlockSource( this.manager, + location, + parameters, + getLogger()); + } + + /* (non-Javadoc) + * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source) + */ + public void release( Source source ) { + if ( null != source ) { + if ( this.getLogger().isDebugEnabled() ) { + this.getLogger().debug("Releasing source " + source.getURI()); + } + ((BlockSource)source).recycle(); + } + } + + /* (non-Javadoc) + * @see org.apache.excalibur.source.URIAbsolutizer#absolutize(java.lang.String, java.lang.String) + */ + public String absolutize(String baseURI, String location) { + return SourceUtil.absolutize(baseURI, location, true); + } + +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlockSourceFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlocksSource.java URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlocksSource.java?rev=330548&view=auto ============================================================================== --- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlocksSource.java (added) +++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlocksSource.java Thu Nov 3 05:41:06 2005 @@ -0,0 +1,163 @@ +/* + * Copyright 1999-2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.cocoon.components.source.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; + +import org.apache.avalon.framework.logger.Logger; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.ResourceNotFoundException; +import org.apache.cocoon.components.blocks.BlocksManager; +import org.apache.cocoon.environment.Environment; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.internal.EnvironmentHelper; +import org.apache.cocoon.environment.wrapper.EnvironmentWrapper; +import org.apache.excalibur.source.SourceException; +import org.apache.excalibur.source.SourceNotFoundException; +import org.apache.excalibur.source.impl.AbstractSource; + +/** + * Implementation of a {@link Source} that gets its content by + * invoking the BlocksManager. + * + * WARNING: It is created for being able to use the blocks + * functionality without needing to change the Cocoon object and other + * fundamental classes. This class will probably be removed later. + * + * @version $Id: BlocksSource.java 292282 2005-09-28 19:54:16Z vgritsenko $ */ +public final class BlocksSource + extends AbstractSource { + + /** The current ServiceManager */ + private final ServiceManager manager; + + /** The environment */ + private final EnvironmentWrapper environment; + + /** + * Construct a new object + */ + public BlocksSource(ServiceManager manager, + String uri, + Map parameters, + Logger logger) + throws MalformedURLException { + + Environment env = EnvironmentHelper.getCurrentEnvironment(); + if ( env == null ) { + throw new MalformedURLException("The blocks protocol can not be used outside an environment."); + } + this.manager = manager; + + SitemapSourceInfo info = null; + try { + info = parseBlocksURI(env, uri); + } catch (URISyntaxException e) { + throw new MalformedURLException("Malformed URI in blocks source " + + e.getMessage()); + } + setScheme(info.protocol); + setSystemId(info.systemId); + + // create environment... + this.environment = new EnvironmentWrapper(env, info, logger); + + // ...and put information passed from the parent request to the internal request + if ( null != parameters ) { + this.environment.getObjectModel().put(ObjectModelHelper.PARENT_CONTEXT, parameters); + } else { + this.environment.getObjectModel().remove(ObjectModelHelper.PARENT_CONTEXT); + } + + this.environment.setURI(info.prefix, info.uri); + } + + /** + * Return an InputStream object to read from the source. + */ + public InputStream getInputStream() + throws IOException, SourceException { + + BlocksManager blocks = null; + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + this.environment.setOutputStream(os); + + blocks = (BlocksManager)this.manager.lookup(BlocksManager.ROLE); + blocks.process(this.environment); + + return new ByteArrayInputStream(os.toByteArray()); + + } catch (ResourceNotFoundException e) { + throw new SourceNotFoundException("Exception during processing of " + this.getURI(), e); + } catch (Exception e) { + throw new SourceException("Exception during processing of " + this.getURI(), e); + } finally { + this.manager.release(blocks); + // Unhide wrapped environment output stream + this.environment.setOutputStream(null); + } + } + + /** + * Returns true always. + * @see org.apache.excalibur.source.Source#exists() + */ + public boolean exists() { + return true; + } + + /** + * Recyclable + */ + public void recycle() { + } + + // Parse the blocks protocol. + private static SitemapSourceInfo parseBlocksURI(Environment env, String sitemapURI) + throws URISyntaxException { + URI uri = new URI(sitemapURI); + + if (!uri.isAbsolute() && uri.isOpaque() && uri.getAuthority() == null) { + throw new URISyntaxException(sitemapURI, + "The blocks protocol must be an absolute, hierachial URI whithout authority part"); + } + + SitemapSourceInfo info = new SitemapSourceInfo(); + // the blocks protocol is for redirecting the call to a + // mounted block, so using the request parameters from the + // original request is reasonable. + info.rawMode = false; + info.protocol = uri.getScheme(); + // The blocks protocol is always from the root context + info.prefix = ""; + info.uri = uri.getPath(); + info.requestURI = info.prefix + info.uri; + info.processFromRoot = true; + info.queryString = uri.getQuery(); + info.view = SitemapSourceInfo.getView(info.queryString, env); + info.systemId = uri.toString(); + + return info; + } +} Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/BlocksSource.java ------------------------------------------------------------------------------ svn:eol-style = native