cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sylv...@apache.org
Subject cvs commit: cocoon-2.1/src/blocks/batik/java/org/apache/cocoon/serialization SVGSerializer.java
Date Wed, 04 Feb 2004 14:39:28 GMT
sylvain     2004/02/04 06:39:28

  Modified:    src/blocks/batik/java/org/apache/cocoon/serialization
                        SVGSerializer.java
  Added:       src/blocks/batik/java/org/apache/cocoon/components/url
                        SourceProtocolHandler.java
                        StreamJDKRegistryEntry.java
  Log:
  Add support for all cocoon protocols for <svg:image xlink:href="..."/>
  
  Revision  Changes    Path
  1.1                  cocoon-2.1/src/blocks/batik/java/org/apache/cocoon/components/url/SourceProtocolHandler.java
  
  Index: SourceProtocolHandler.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <stefano@apache.org>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.url;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Iterator;
  
  import org.apache.avalon.framework.CascadingRuntimeException;
  import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
  import org.apache.batik.util.AbstractParsedURLProtocolHandler;
  import org.apache.batik.util.ParsedURL;
  import org.apache.batik.util.ParsedURLData;
  import org.apache.batik.util.ParsedURLProtocolHandler;
  import org.apache.cocoon.CascadingIOException;
  import org.apache.excalibur.source.Source;
  import org.apache.excalibur.source.SourceResolver;
  
  /**
   * A Batik protocol handler that handles all Cocoon sources. This allows
   * &lt;svg:image xlink:href="..."/> to use any of the protocols handled by Cocoon.
   * 
   * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
   * @version CVS $Id: SourceProtocolHandler.java,v 1.1 2004/02/04 14:39:28 sylvain Exp $
   */
  public class SourceProtocolHandler extends AbstractParsedURLProtocolHandler {
      
      /** Thread-local source resolver */
      protected static InheritableThreadLocal localResolver = new InheritableThreadLocal();
      
      /** Batik's original default handler */        
      protected static ParsedURLProtocolHandler defaultHandler;
  
      /**
       * Change the default handler used by Batik to resolve URLs to a handler
       * based on <code>SourceResolver</code> and <code>SourceHandler</code>.
       * <p>
       * Note : Batik handlers are defined statically, and are thus shared by
       * all its users. However, this shouldn't be a problem since different
       * web applications live in different classloaders.
       *
       * @param manager the component manager used to get the <code>SourceHandler</code>
       * @param logger the logger for logging.
       */
      static {        
          // Keep the default handler, if any
          SourceProtocolHandler.defaultHandler = ParsedURL.getHandler(null);
          
          // Set the default handler to our handler
          ParsedURL.registerHandler(new SourceProtocolHandler(null));
          
          // Add a new image registry entry to handle image streams
          ImageTagRegistry.getRegistry().register(new StreamJDKRegistryEntry());
          
      }
      
      /**
       * Set the resolver to be used within the current thread.
       */
      public static void setup(SourceResolver resolver) {
          localResolver.set(resolver);
      }
      
      
      /**
       * Get the thread-local resolver.
       */
      public static SourceResolver getSourceResolver()
      {
          SourceResolver resolver = (SourceResolver)localResolver.get();
          return resolver;
      }
  
      //-------------------------------------------------------------------------
      
      public SourceProtocolHandler(String protocol) {
          super(protocol);
      }
      
      public ParsedURLData parseURL(ParsedURL baseURL, String urlStr) {
          SourceResolver resolver = (SourceResolver)localResolver.get();
          if (resolver == null) {
              // Fall back to the previous default handler
              return defaultHandler == null ? null : defaultHandler.parseURL(baseURL, urlStr);
          } else {
              return new SourceParsedURLData(urlStr, resolver);
          }
      }
  
      public ParsedURLData parseURL(String urlStr) {
          SourceResolver resolver = (SourceResolver)localResolver.get();
          if (resolver == null) {
              return defaultHandler == null ? null : defaultHandler.parseURL(urlStr);
          } else {
              return new SourceParsedURLData(urlStr, resolver);
          }
      }
  
      /**
       * Reimplementation of some methods of ParsedURLData since we cannot use <code>java.net.URL</code>.
       */
      static class SourceParsedURLData extends ParsedURLData {
          
          public String url;
          
          private Source source;
          private SourceResolver resolver;
  
          public SourceParsedURLData(String urlStr, SourceResolver resolver) {
              
              this.url = urlStr;
              this.resolver = resolver;
              
              // ParsedURLData has some public members which seems to be required to
              // have a value. This sucks.
              int pidx=0, idx;
      
              idx = urlStr.indexOf(':');
              if (idx != -1) {
                  // May have a protocol spec...
                  this.protocol = urlStr.substring(pidx, idx);
                  if (this.protocol.indexOf('/') == -1)
                      pidx = idx+1;
                  else {
                      // Got a slash in protocol probably means 
                      // no protocol given, (host and port?)
                      this.protocol = null;
                      pidx = 0;
                  }
              }
      
              idx = urlStr.indexOf(',',pidx);
              if (idx != -1) {
                  this.host = urlStr.substring(pidx, idx);
                  pidx = idx+1;
              }
              if (pidx != urlStr.length()) 
                  this.path = urlStr.substring(pidx);
              
              
              // Now do the real job
              
              // Setup source
              try {
                  this.source = resolver.resolveURI(this.url);
              } catch(Exception e) {
                  throw new CascadingRuntimeException("Cannot resolve " + this.url, e);
              }
                  
              // Get Mime-type
              
              // First try the source itself
              this.contentType = this.source.getMimeType();
              
              if (this.contentType == null) {
                  // Guess it from the URL extension
                  if (url.endsWith(".gif")) {
                      this.contentType = "image/gif";
                  } else if (url.endsWith(".jpeg") || url.endsWith(".jpg")) {
                      this.contentType = "image/jpeg";
                  } else if (url.endsWith(".png")) {
                      this.contentType = "image/png";
                  }
              }
          }
          
          public boolean complete() {
              return (this.url != null);
          }
  
          public String getPortStr() {
              String portStr = protocol+":";
              if (host != null) portStr += host;
              portStr += ",";
              return portStr;
          }
                  
          public String toString() {
              return this.url;
          }
  
          /**
           * Open a stream for the data. If the thread-local <code>SourceResolver</code>
exists,
           * then use it, otherwise fall back to <code>SourceHandler</code>.
           */
          protected InputStream openStreamInternal (String userAgent, Iterator mimeTypes,
Iterator encodingTypes)
              throws IOException {
                  
              try {
                  return source.getInputStream();
              } catch(Exception e) {
                  throw new CascadingIOException("Cannot open URL " + this.url, e);
              } finally {
                  this.resolver.release(this.source);
              }
          }
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/batik/java/org/apache/cocoon/components/url/StreamJDKRegistryEntry.java
  
  Index: StreamJDKRegistryEntry.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      apache@apache.org.
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <stefano@apache.org>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.url;
  
  import java.awt.Component;
  import java.awt.Graphics2D;
  import java.awt.Image;
  import java.awt.Label;
  import java.awt.MediaTracker;
  import java.awt.Toolkit;
  import java.awt.image.BufferedImage;
  import java.awt.image.RenderedImage;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Iterator;
  
  import org.apache.batik.ext.awt.image.GraphicsUtil;
  import org.apache.batik.ext.awt.image.renderable.Filter;
  import org.apache.batik.ext.awt.image.renderable.RedRable;
  import org.apache.batik.ext.awt.image.spi.AbstractRegistryEntry;
  import org.apache.batik.ext.awt.image.spi.MagicNumberRegistryEntry;
  import org.apache.batik.ext.awt.image.spi.URLRegistryEntry;
  import org.apache.batik.util.ParsedURL;
  
  
  /**
   * This Image tag registy entry is setup to wrap the core JDK Image stream tools.  
   * 
   * @version CVS $Id: StreamJDKRegistryEntry.java,v 1.1 2004/02/04 14:39:28 sylvain Exp $
   */
  public class StreamJDKRegistryEntry extends AbstractRegistryEntry 
      implements URLRegistryEntry {
  
      /**
       * The priority of this entry.
       * This entry should in most cases be the last entry.
       * but if one wishes one could set a priority higher and be called
       * afterwords
       */
      public final static float PRIORITY = 
          1000*MagicNumberRegistryEntry.PRIORITY;
  
      public StreamJDKRegistryEntry() {
          super ("Stream-JDK", PRIORITY, new String[0], new String [] {"image/gif"});
      }
  
      /**
       * Check if the Stream references an image that can be handled by
       * this format handler.  The input stream passed in should be
       * assumed to support mark and reset.
       *
       * If this method throws a StreamCorruptedException then the
       * InputStream will be closed and a new one opened (if possible).
       *
       * This method should only throw a StreamCorruptedException if it
       * is unable to restore the state of the InputStream
       * (i.e. mark/reset fails basically).  
       */
      public boolean isCompatibleURL(ParsedURL purl) {
          String contentType = purl.getContentType();
          if (contentType == null)
              return false;
  
          Iterator iter = this.getMimeTypes().iterator();
          while (iter.hasNext()) {
              if (contentType.equals(iter.next())) {
                  return true;
              }
          }
          return false;
      }
  
      /**
       * Decode the URL into a RenderableImage
       *
       * @param purl The URLto decode
       * @param needRawData If true the image returned should not have
       *                    any default color correction the file may 
       *                    specify applied.  
       */
      public Filter handleURL(ParsedURL purl, boolean needRawData) {
          
          // Read all bytes from the ParsedURL (too bad, there's no Toolkit.createImage(InputStream))
          InputStream is = null;
          byte[] buffer = new byte[1024];
          int len;
          ByteArrayOutputStream bos = new ByteArrayOutputStream();
          try {
              is = purl.openStream();
              while((len = is.read(buffer)) != -1) {
                  bos.write(buffer, 0, len);
              }
          } catch(IOException ioe) {
              return null;
          } finally {
              try {
                  if (is != null) is.close();
              } catch (Exception e) {}
          }
          
          buffer = bos.toByteArray();
  
          Toolkit tk = Toolkit.getDefaultToolkit();
          final Image img = tk.createImage(buffer);
          if (img == null)
              return null;
  
          RenderedImage ri = loadImage(img);
          if (ri == null)
              return null;
  
          return new RedRable(GraphicsUtil.wrap(ri));
      }
  
      // Stuff for Image Loading.
      static Component mediaComponent = new Label();
      static MediaTracker mediaTracker = new MediaTracker(mediaComponent);
      static int id = 0;
  
      public RenderedImage loadImage(Image img) {
          // In some cases the image will be a
          // BufferedImage (subclass of RenderedImage).
          if (img instanceof RenderedImage)
              return (RenderedImage)img;
  
                      // Setup the mediaTracker.
          int myID;
          synchronized (mediaTracker) {
              myID = id++;
          }
  
          // Add our image to the media tracker and wait....
          mediaTracker.addImage(img, myID);
          while (true) {
              try {
                  mediaTracker.waitForID(myID);
              }
              catch(InterruptedException ie) {
                                  // Something woke us up but the image
                                  // isn't done yet, so try again.
                  continue;
              };
  
              // All done!
              break;
          }
  
          // Clean up our registraction
          mediaTracker.removeImage(img, myID);
  
          if ((img.getWidth(null)  == -1)||
              (img.getHeight(null) == -1))
              return null;
  
                      // Build the image to .
          BufferedImage bi = null;
          bi = new BufferedImage(img.getWidth(null),
                                 img.getHeight(null),
                                 BufferedImage.TYPE_INT_ARGB);
          Graphics2D g2d = bi.createGraphics();
  
          g2d.drawImage(img, 0, 0, null);
          g2d.dispose();
          return bi;
      }
  }
  
  
  
  1.11      +35 -19    cocoon-2.1/src/blocks/batik/java/org/apache/cocoon/serialization/SVGSerializer.java
  
  Index: SVGSerializer.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.1/src/blocks/batik/java/org/apache/cocoon/serialization/SVGSerializer.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- SVGSerializer.java	20 Nov 2003 15:13:36 -0000	1.10
  +++ SVGSerializer.java	4 Feb 2004 14:39:28 -0000	1.11
  @@ -54,26 +54,25 @@
   import java.io.OutputStream;
   
   import org.apache.avalon.excalibur.pool.Poolable;
  +import org.apache.avalon.framework.activity.Disposable;
   import org.apache.avalon.framework.configuration.Configurable;
   import org.apache.avalon.framework.configuration.Configuration;
   import org.apache.avalon.framework.configuration.ConfigurationException;
  -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.service.ServiceException;
  +import org.apache.avalon.framework.service.ServiceManager;
  +import org.apache.avalon.framework.service.Serviceable;
   import org.apache.batik.transcoder.Transcoder;
  +import org.apache.batik.transcoder.TranscoderException;
   import org.apache.batik.transcoder.TranscoderInput;
   import org.apache.batik.transcoder.TranscoderOutput;
   import org.apache.batik.transcoder.TranscodingHints;
  -import org.apache.batik.transcoder.TranscoderException;
  -import org.apache.batik.util.ParsedURL;
  -import org.apache.cocoon.Constants;
   import org.apache.cocoon.caching.CacheableProcessingComponent;
   import org.apache.cocoon.components.transcoder.ExtendableTranscoderFactory;
   import org.apache.cocoon.components.transcoder.TranscoderFactory;
  -import org.apache.cocoon.components.url.ParsedContextURLProtocolHandler;
  -import org.apache.cocoon.components.url.ParsedResourceURLProtocolHandler;
  +import org.apache.cocoon.components.url.SourceProtocolHandler;
   import org.apache.cocoon.util.ClassUtils;
   import org.apache.cocoon.xml.dom.SVGBuilder;
  +import org.apache.excalibur.source.SourceResolver;
   import org.apache.excalibur.source.SourceValidity;
   import org.apache.excalibur.source.impl.validity.NOPValidity;
   import org.w3c.dom.Document;
  @@ -87,17 +86,17 @@
    * @version CVS $Id$
    */
   public class SVGSerializer extends SVGBuilder
  -implements Serializer, Configurable, Poolable, CacheableProcessingComponent, Contextualizable
{
  +implements Serializer, Configurable, Poolable, CacheableProcessingComponent, Serviceable,
Disposable /*, Contextualizable*/ {
   
  -    /**
  -     * Get the context
  -     */
  -    public void contextualize(Context context) throws ContextException {
  -        ParsedContextURLProtocolHandler.setContext(
  -            (org.apache.cocoon.environment.Context)context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT));
  -        ParsedURL.registerHandler(new ParsedContextURLProtocolHandler());
  -        ParsedURL.registerHandler(new ParsedResourceURLProtocolHandler());
  -    }
  +//    /**
  +//     * Get the context
  +//     */
  +//    public void contextualize(Context context) throws ContextException {
  +//        ParsedContextURLProtocolHandler.setContext(
  +//            (org.apache.cocoon.environment.Context)context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT));
  +//        ParsedURL.registerHandler(new ParsedContextURLProtocolHandler());
  +//        ParsedURL.registerHandler(new ParsedResourceURLProtocolHandler());
  +//    }
   
       /** The current <code>OutputStream</code>. */
       private OutputStream output;
  @@ -110,12 +109,28 @@
   
       /** The Transcoder Factory to use */
       TranscoderFactory factory = ExtendableTranscoderFactory.getTranscoderFactoryImplementation();
  +    
  +    private ServiceManager manager;
  +
  +    private SourceResolver resolver;
   
       /**
        * Set the <code>OutputStream</code> where the XML should be serialized.
        */
       public void setOutputStream(OutputStream out) {
           this.output = out;
  +        
  +        // Give the source resolver to Batik
  +        SourceProtocolHandler.setup(this.resolver);
  +    }
  +    
  +    public void service(ServiceManager manager) throws ServiceException {
  +        this.manager = manager;
  +        this.resolver = (SourceResolver)this.manager.lookup(SourceResolver.ROLE);
  +    }
  +    
  +    public void dispose() {
  +        this.manager.release(this.resolver);
       }
   
       /**
  @@ -215,6 +230,7 @@
        * Receive notification of a successfully completed DOM tree generation.
        */
       public void notify(Document doc) throws SAXException {
  +        
           try {
               TranscoderInput transInput = new TranscoderInput(doc);
   
  
  
  

Mime
View raw message