You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by sy...@apache.org on 2002/03/15 19:49:32 UTC

cvs commit: xml-cocoon2/src/scratchpad/src/org/apache/cocoon/components/source BlobSource.java BlobSourceFactory.java blob.xconf

sylvain     02/03/15 10:49:32

  Added:       src/scratchpad/src/org/apache/cocoon/components/source
                        BlobSource.java BlobSourceFactory.java blob.xconf
  Log:
  New Blob source
  
  Revision  Changes    Path
  1.1                  xml-cocoon2/src/scratchpad/src/org/apache/cocoon/components/source/BlobSource.java
  
  Index: BlobSource.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 (INCLUDING, 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.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.cocoon.components.source;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.log.Logger;
  
  import org.apache.avalon.excalibur.datasource.DataSourceComponent;
  import org.apache.avalon.framework.component.ComponentSelector;
  
  import org.apache.cocoon.ProcessingException;
  
  import java.io.InputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.ByteArrayInputStream;
  import java.io.FilterInputStream;
  import java.net.MalformedURLException;
  
  import java.sql.*;
  
  /**
   * A <code>Source</code> that takes its content in a single JDBC column. Any
   * kind of column can be used (clob, blob, varchar, etc), but "Blob" means
   * that the whole content is contained in a single column.
   * <p>The URL syntax is "blob:/datasource/table/column[cond]", where :
   * <ul>
   * <li>"datasource" is the jdbc datasource to use (defined in cocoon.xonf)
   * <li>"table" is the database table,
   * <li>"column" is (you can guess, now :) the column in "table",
   * <li>"cond" is the boolean condition used to select a particular record in
   * the table.
   * </ul>
   * <p>For example, "<code>blob:/personel/people/photo[userid='foo']</code>"
   * will fetch the first column returned by the statement "<code>SELECT photo
   * from people where userid='foo'</code>" in the datasource "<code>personel</code>"
   * 
   * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
   * @version $Id: BlobSource.java,v 1.1 2002/03/15 18:49:32 sylvain Exp $
   */
  
  public class BlobSource extends AbstractStreamSource {
      
      /**
       * The system ID for this source
       */
      private String systemId;
      
      private String datasourceName;
      
      private String tableName;
      
      private String columnName;
      
      private String condition;
      
      private final static String URL_PREFIX = "blob:/";
      private final static int URL_PREFIX_LEN = URL_PREFIX.length();
      
      /**
       * Create a file source from a 'blob:' url and a component manager.
       * <p>The url is of the form "blob:/datasource/table/column[condition]
       */
      public BlobSource(String url, ComponentManager manager) throws MalformedURLException {
          
          super(manager);
          
          if (!url.startsWith("blob:/")) {
              throw new MalformedURLException("Malformed url for a blob source : " + url);
          }
          
          this.systemId = url;
          
          // Parse the url
          int start = URL_PREFIX_LEN;
          int end;
          
          // Datasource
          end = url.indexOf('/', start);
          if (end == -1) {
              throw new MalformedURLException("Malformed blob source (cannot find datasource) : " + url);
          }
          
          this.datasourceName = url.substring(start, end);
          
          // Table
          start = end + 1;
          end = url.indexOf('/', start);
          if (end == -1) {
              throw new MalformedURLException("Malformed blob source (cannot find table name) : " + url);
          }
          
          this.tableName = url.substring(start, end);
          
          // Column
          start = end + 1;
          end = url.indexOf('[', start);
          if (end == -1) {
              this.columnName = url.substring(start);
          } else {
              this.columnName = url.substring(start, end);
              
              // Condition
              start = end + 1;
              end = url.length() - 1;
              if (url.charAt(end) != ']') {
                  throw new MalformedURLException("Malformed url for a blob source (cannot find condition) : " + url);
              } else {
                  this.condition = url.substring(start, end);
              }
          }
      }
  
      /**
       * Return the unique identifer for this source
       */
      public String getSystemId() {
          return this.systemId;
      }
  
      /**
       * Get the input stream for this source.
       */
      public InputStream getInputStream() throws IOException, ProcessingException {
          if (getLogger().isDebugEnabled()) {
              getLogger().debug("Opening stream for datasource " + this.datasourceName +
                  ", table " + this.tableName + ", column " + this.columnName +
                  (this.condition == null ? ", no condition" : ", condition " + this.condition)
              );
          }
  
          Connection cnx = null;
          Statement stmt = null;
          
          try {
              cnx = getConnection();
              stmt = cnx.createStatement();
          
              StringBuffer selectBuf = new StringBuffer("SELECT ").append(this.columnName).
                  append(" FROM ").append(this.tableName);
              
              if (this.condition != null) {
                  selectBuf.append(" WHERE ").append(this.condition);
              }
              
              String select = selectBuf.toString();
              if (getLogger().isDebugEnabled()) {
                  getLogger().debug("Executing statement " + select);
              }
              
              ResultSet rs = stmt.executeQuery(select);
              rs.next();
              
              int colType = rs.getMetaData().getColumnType(1);
              
              switch(colType) {
                  case Types.BLOB :
                      Blob blob = rs.getBlob(1);
                      return new JDBCInputStream(blob.getBinaryStream(), cnx);
                  //break;
                  
                  case Types.CLOB :
                      Clob clob = rs.getClob(1);
                      return new JDBCInputStream(clob.getAsciiStream(), cnx);
                  //break;
                  
                  default :
                      String value = rs.getString(1);
                      stmt.close();
                      rs.close();
                      cnx.close();
                      return new ByteArrayInputStream(value.getBytes());
              }
          } catch(SQLException sqle) {
              String msg = "Cannot retrieve content from " + this.systemId;
              getLogger().error(msg, sqle);
              
              try {
                  if (cnx != null) {
                      cnx.close();
                  }
              } catch(SQLException sqle2) {
                  // PITA
                  throw new ProcessingException("Cannot close connection", sqle2);
              }
  
              // IOException would be more adequate, but ProcessingException is cascaded...
              throw new ProcessingException(msg, sqle);
          }
      }
      
      private Connection getConnection() throws ProcessingException {
  
          ComponentSelector selector = null;
          DataSourceComponent datasource = null;
  
          try {
              try {
                  selector = (ComponentSelector)this.manager.lookup(DataSourceComponent.ROLE + "Selector");
                      
                  datasource = (DataSourceComponent)selector.select(this.datasourceName);
      
              } catch(Exception e) {
                  String msg = "Cannot get datasource '" + this.datasourceName + "'";
                  getLogger().error(msg);
                  throw new ProcessingException(msg, e);
              }
              
              try {
                  return datasource.getConnection();
              } catch(Exception e) {
                  String msg = "Cannot get connection for datasource '" + this .datasourceName + "'";
                  getLogger().error(msg);
                  throw new ProcessingException(msg, e);
              }
  
          } finally {
              if (datasource != null) {
                  selector.release(datasource);
              }
          }
      }
          
      /**
       * An OutputStream that will close the connection that created it on
       * close.
       */
      private class JDBCInputStream extends FilterInputStream {
          
          Connection cnx;
          
          public JDBCInputStream(InputStream stream, Connection cnx) {
              super(stream);
              this.cnx = cnx;
          }
          
          public void close() throws IOException {
              super.close();
              if (this.cnx != null) {
                  try {
                      cnx.close();
                      cnx = null;
                  } catch(Exception e) {
                      String msg = "Error closing the connection for " + BlobSource.this.systemId;
                      BlobSource.this.getLogger().error(msg, e);
                      throw new IOException(msg + " : " + e.getMessage());
                  }
              }
          }
      }
  }
      
  
  
  
  1.1                  xml-cocoon2/src/scratchpad/src/org/apache/cocoon/components/source/BlobSourceFactory.java
  
  Index: BlobSourceFactory.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, 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 (INCLUDING, 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.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.cocoon.components.source;
  
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.logger.AbstractLoggable;
  import org.apache.avalon.framework.thread.ThreadSafe;
  
  import org.apache.cocoon.components.source.SourceFactory;
  import org.apache.cocoon.environment.Environment;
  import org.apache.cocoon.environment.Source;
  import org.apache.cocoon.ProcessingException;
  
  import java.io.IOException;
  import java.net.MalformedURLException;
  import java.net.URL;
  
  /**
   * A factory for 'blob:' sources.
   *
   * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
   * @version $Id: BlobSourceFactory.java,v 1.1 2002/03/15 18:49:32 sylvain Exp $
   */
  
  public class BlobSourceFactory extends AbstractLoggable
    implements SourceFactory, Composable, ThreadSafe {
      
      private ComponentManager manager;
  
      public void compose(ComponentManager manager) throws ComponentException {
          this.manager = manager;
      }
      
      public Source getSource(Environment environment, String location)
        throws ProcessingException, MalformedURLException, IOException {
          Source result = new BlobSource(location, this.manager);
          setupLogger(result);
          return result;
      }
  
      public Source getSource(Environment environment, URL base, String location)
        throws ProcessingException, MalformedURLException, IOException {
          return getSource(environment, new URL(base, location).toExternalForm());
      }
  }
      
  
  
  1.1                  xml-cocoon2/src/scratchpad/src/org/apache/cocoon/components/source/blob.xconf
  
  Index: blob.xconf
  ===================================================================
  <?xml version="1.0"?>
  
  <xconf xpath="/cocoon/source-handler" unless="protocol[@name='blob']">
  
      <!-- blob pseudo protocol -->
      <protocol name="blob" class="org.apache.cocoon.components.source.BlobSource"/>
  
  </xconf>
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     webmaster@xml.apache.org
To unsubscribe, e-mail:          cocoon-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-cvs-help@xml.apache.org