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;
}
}