Author: cziegeler
Date: Mon May  2 06:32:24 2005
New Revision: 165628

URL: http://svn.apache.org/viewcvs?rev=165628&view=rev
Log:
Protocols can be defined on a per sitemap configuration

Modified:
    
cocoon/trunk/src/java/org/apache/cocoon/components/source/CocoonSourceResolver.java

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/source/CocoonSourceResolver.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/source/CocoonSourceResolver.java?rev=165628&r1=165627&r2=165628&view=diff
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/source/CocoonSourceResolver.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/source/CocoonSourceResolver.java
 Mon May  2 06:32:24 2005
@@ -16,35 +16,82 @@
 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.CascadingRuntimeException;
+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.cocoon.Processor;
 import org.apache.cocoon.environment.SourceResolver;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceException;
-import org.apache.excalibur.source.impl.SourceResolverImpl;
+import org.apache.excalibur.source.SourceFactory;
+import org.apache.excalibur.source.URIAbsolutizer;
 
 /**
  * This is the default implementation of the [EMAIL PROTECTED] SourceResolver} 
for
- * Cocoon.
+ * Cocoon. The implementation is based on the original source resolver 
implementation
+ * from the Excalibur project.
  * @since 2.2
  * 
  * @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
- * @version CVS $Id: CocoonSourceResolver.java,v 1.1 2004/05/25 07:28:26 
cziegeler Exp $
+ * @version CVS $Id$
 */
 public class CocoonSourceResolver 
-extends SourceResolverImpl
-implements SourceResolver {
+extends AbstractLogEnabled
+implements SourceResolver, Contextualizable, Serviceable, Disposable {
 
     /** A (optional) custom source resolver */
     protected org.apache.excalibur.source.SourceResolver customResolver;
-    
-    /* (non-Javadoc)
+
+    /** The service manager */
+    protected ServiceManager manager;
+
+    /** The base URL */
+    protected URL baseURL;
+
+    /** The component context */
+    protected Context context;
+
+    /**
+     * @see 
org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+     */
+    public void contextualize( Context context )
+    throws ContextException {
+        this.context = context;
+        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)
@@ -58,11 +105,80 @@
         if ( this.customResolver != null ) {
             return this.customResolver.resolveURI(location, baseURI, 
parameters);
         } else {
-            return super.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 ServiceManager m = this.getServiceManager();
+
+            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 ServiceException 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 (ServiceException se ) {
+                    throw new SourceException( "Unable to select source 
factory for " + systemID, se );
+                } finally {
+                    m.release(factory);
+                }
+            }
+
+            return source;
         }
     }
 
-    /* (non-Javadoc)
+    /**
      * @see 
org.apache.excalibur.source.SourceResolver#resolveURI(java.lang.String)
      */
     public Source resolveURI(String location)
@@ -76,33 +192,84 @@
      * @see 
org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
      */
     public void service(ServiceManager manager) throws ServiceException {
-        super.service(manager);
-        if ( 
manager.hasService(org.apache.excalibur.source.SourceResolver.ROLE+"/Cocoon")) {
+        this.manager = manager;
+        if ( 
this.manager.hasService(org.apache.excalibur.source.SourceResolver.ROLE+"/Cocoon"))
 {
             this.customResolver = (org.apache.excalibur.source.SourceResolver)
-               
manager.lookup(org.apache.excalibur.source.SourceResolver.ROLE+"/Cocoon");
+                     
this.manager.lookup(org.apache.excalibur.source.SourceResolver.ROLE+"/Cocoon");
         }
     }
 
-    /* (non-Javadoc)
+    /**
      * @see org.apache.avalon.framework.activity.Disposable#dispose()
      */
     public void dispose() {
-        if ( this.m_manager != null ) {
-            this.m_manager.release( this.customResolver );
+        if ( this.manager != null ) {
+            this.manager.release( this.customResolver );
             this.customResolver = null;
+            this.manager = null;
         }
-        super.dispose();
     }
 
-    /* (non-Javadoc)
+    /**
+     * Get the service manager.
+     */
+    protected ServiceManager getServiceManager() {
+        ServiceManager m = EnvironmentHelper.getSitemapServiceManager();
+        if ( m == null ) {
+            m = this.manager;
+        }
+        return m;
+    }
+
+    /**
+     * Get the SourceFactory
+     */
+    protected SourceFactory getSourceFactory(ServiceManager m, String scheme) 
+    throws ServiceException {
+        return (SourceFactory)m.lookup(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 {
-            super.release(source);
+            final ServiceManager m = this.getServiceManager();
+            
+            // 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 (ServiceException se ) {
+                try {
+                    factory = this.getSourceFactory(m, "*");
+                    factory.release(source);
+                } catch (ServiceException sse ) {
+                    throw new CascadingRuntimeException( "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;
     }
 
 }


Reply via email to