Starting to update the code according to the new repository API

git-svn-id: https://svn.apache.org/repos/asf/lenya/sandbox/repository@366518 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/java/org/apache/lenya/cms/ac/DocumentPolicyManagerWrapper.java b/src/java/org/apache/lenya/cms/ac/DocumentPolicyManagerWrapper.java
index 92c2894..bde6df5 100644
--- a/src/java/org/apache/lenya/cms/ac/DocumentPolicyManagerWrapper.java
+++ b/src/java/org/apache/lenya/cms/ac/DocumentPolicyManagerWrapper.java
@@ -19,8 +19,6 @@
 
 package org.apache.lenya.cms.ac;
 
-import java.util.Map;
-
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
@@ -31,9 +29,6 @@
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.avalon.framework.service.Serviceable;
-import org.apache.cocoon.components.CocoonComponentManager;
-import org.apache.cocoon.environment.ObjectModelHelper;
-import org.apache.cocoon.environment.Request;
 import org.apache.lenya.ac.AccessControlException;
 import org.apache.lenya.ac.Accreditable;
 import org.apache.lenya.ac.AccreditableManager;
@@ -43,12 +38,14 @@
 import org.apache.lenya.ac.impl.DefaultPolicy;
 import org.apache.lenya.ac.impl.InheritingPolicyManager;
 import org.apache.lenya.cms.cocoon.components.context.ContextUtility;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.cms.publication.URLUtil;
+import org.apache.lenya.cms.repo.Area;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.SiteNode;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 
 /**
  * A PolicyManager which is capable of mapping all URLs of a document to the appropriate canonical
@@ -78,27 +75,36 @@
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("Resolving policy for webapp URL [" + webappUrl + "]");
         }
-        
-        
-        Publication publication = getPublication(webappUrl);
+
         String url = null;
         ContextUtility contextUtility = null;
         try {
-            contextUtility = (ContextUtility)serviceManager.lookup(ContextUtility.ROLE);
-            Session session = RepositoryUtil.getSession(contextUtility.getRequest(), getLogger());
-            DocumentIdentityMap map = new DocumentIdentityMap(session,
-                    getServiceManager(),
+            contextUtility = (ContextUtility) serviceManager.lookup(ContextUtility.ROLE);
+            Session session = RepositoryUtil.getSession(serviceManager,
+                    contextUtility.getRequest(),
                     getLogger());
-            if (map.isDocument(webappUrl)) {
-                Document document = map.getFromURL(webappUrl);
-                if (document.existsInAnyLanguage()) {
-                    url = "/" + document.getArea() + document.getId();
-                    if (getLogger().isDebugEnabled()) {
-                        getLogger().debug("    Document exists");
-                        getLogger().debug("    Document ID: [" + document.getId() + "]");
-                    }
+            
+            String pubId = new URLInformation(webappUrl).getPublicationId();
+            Publication pub = session.getPublication(pubId);
+            
+            if (URLUtil.existsDocument(session, webappUrl)) {
+                Document document = URLUtil.getDocument(session, webappUrl);
+                Area area = document.getContentNode().getContent().getArea();
+                SiteNode siteNode = area.getSite().getFirstReference(document);
+                url = "/" + area + siteNode.getPath();
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("    Document exists");
+                    getLogger().debug("    URL: [" + url + "]");
                 }
             }
+
+            if (url == null) {
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("    Document does not exist.");
+                }
+                url = webappUrl.substring(("/" + pub.getPublicationId()).length());
+            }
+
         } catch (ServiceException e) {
             throw new AccessControlException("Error looking up ContextUtility component", e);
         } catch (Exception e) {
@@ -109,35 +115,12 @@
             }
         }
 
-        if (url == null) {
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("    Document does not exist.");
-            }
-            url = webappUrl.substring(("/" + publication.getId()).length());
-        }
-
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("    Using URL: [" + url + "]");
         }
         return url;
     }
 
-    /**
-     * Returns the publication for a certain URL.
-     * @param url The webapp url.
-     * @return A publication.
-     * @throws AccessControlException when the publication could not be created.
-     */
-    protected Publication getPublication(String url) throws AccessControlException {
-        getLogger().debug("Building publication");
-
-        try {
-            return PublicationUtil.getPublicationFromUrl(this.serviceManager, url);
-        } catch (Exception e) {
-            throw new AccessControlException(e);
-        }
-    }
-
     private ServiceManager serviceManager;
 
     /**
diff --git a/src/java/org/apache/lenya/cms/ac/PublicationAccessControllerResolver.java b/src/java/org/apache/lenya/cms/ac/PublicationAccessControllerResolver.java
index 2a80900..8c38687 100644
--- a/src/java/org/apache/lenya/cms/ac/PublicationAccessControllerResolver.java
+++ b/src/java/org/apache/lenya/cms/ac/PublicationAccessControllerResolver.java
@@ -25,15 +25,19 @@
 import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.avalon.framework.service.ServiceException;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.excalibur.source.SourceUtil;
 import org.apache.lenya.ac.AccessControlException;
 import org.apache.lenya.ac.AccessController;
 import org.apache.lenya.ac.impl.AbstractAccessControllerResolver;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
+import org.apache.lenya.cms.cocoon.components.context.ContextUtility;
 import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 
 /**
  * Resolves the access controller according to the <code>ac.xconf</code> file of a publication.
@@ -41,8 +45,7 @@
 public class PublicationAccessControllerResolver extends AbstractAccessControllerResolver implements
         Initializable {
 
-    protected static final String CONFIGURATION_FILE = "config/ac/ac.xconf".replace('/',
-            File.separatorChar);
+    protected static final String CONFIGURATION_FILE = "/config/ac/ac.xconf";
     protected static final String TYPE_ATTRIBUTE = "type";
 
     /**
@@ -76,8 +79,12 @@
         Publication publication = getPublication(webappUrl);
 
         if (publication != null) {
-            String publicationUrl = webappUrl.substring(("/" + publication.getId()).length());
-            controller = resolveAccessController(publication, publicationUrl);
+            try {
+                String publicationUrl = webappUrl.substring(("/" + publication.getPublicationId()).length());
+                controller = resolveAccessController(publication, publicationUrl);
+            } catch (RepositoryException e) {
+                throw new AccessControlException(e);
+            }
         }
         return controller;
     }
@@ -90,30 +97,32 @@
      * @throws AccessControlException when something went wrong.
      */
     protected Publication getPublication(String webappUrl) throws AccessControlException {
-        Publication publication = null;
 
-        assert webappUrl.startsWith("/");
-        // remove leading slash
-        String url = webappUrl.substring(1);
-
-        if (url.length() > 0) {
-
-            URLInformation info = new URLInformation(webappUrl);
-            String publicationId = info.getPublicationId();
-
-            try {
-                publication = PublicationUtil.getPublicationFromUrl(this.manager, webappUrl);
-            } catch (Exception e) {
-                throw new AccessControlException(e);
-            }
-            if (publication.exists()) {
-                getLogger().debug("Publication [" + publicationId + "] exists.");
+        ContextUtility contextUtility = null;
+        try {
+            contextUtility = (ContextUtility) this.manager.lookup(ContextUtility.ROLE);
+            Session session = RepositoryUtil.getSession(this.manager,
+                    contextUtility.getRequest(),
+                    getLogger());
+            String pubId = new URLInformation(webappUrl).getPublicationId();
+            if (session.existsPublication(pubId)) {
+                getLogger().debug("Publication [" + pubId + "] exists.");
+                return session.getPublication(pubId);
             } else {
-                getLogger().debug("Publication [" + publicationId + "] does not exist.");
-                publication = null;
+                getLogger().debug("Publication [" + pubId + "] does not exist.");
+                return null;
+            }
+
+        } catch (ServiceException e) {
+            throw new AccessControlException("Error looking up ContextUtility component", e);
+        } catch (Exception e) {
+            throw new AccessControlException(e);
+        } finally {
+            if (contextUtility != null) {
+                this.manager.release(contextUtility);
             }
         }
-        return publication;
+
     }
 
     /**
@@ -139,23 +148,21 @@
         assert publication != null;
 
         AccessController accessController = null;
-        File configurationFile = new File(publication.getDirectory(), CONFIGURATION_FILE);
+        try {
+            String configUrl = "context://lenya/pubs/" + publication.getPublicationId()
+                    + CONFIGURATION_FILE;
+            Configuration configuration = new DefaultConfigurationBuilder().build(configUrl);
+            String type = configuration.getAttribute(TYPE_ATTRIBUTE);
 
-        if (configurationFile.isFile()) {
-            try {
-                Configuration configuration = new DefaultConfigurationBuilder().buildFromFile(configurationFile);
-                String type = configuration.getAttribute(TYPE_ATTRIBUTE);
+            accessController = (AccessController) getManager().lookup(AccessController.ROLE + "/"
+                    + type);
 
-                accessController = (AccessController) getManager().lookup(AccessController.ROLE
-                        + "/" + type);
-
-                if (accessController instanceof Configurable) {
-                    ((Configurable) accessController).configure(configuration);
-                }
-
-            } catch (Exception e) {
-                throw new AccessControlException(e);
+            if (accessController instanceof Configurable) {
+                ((Configurable) accessController).configure(configuration);
             }
+
+        } catch (Exception e) {
+            throw new AccessControlException(e);
         }
 
         return accessController;
diff --git a/src/java/org/apache/lenya/cms/ac/usecase/UsecaseAuthorizer.java b/src/java/org/apache/lenya/cms/ac/usecase/UsecaseAuthorizer.java
index dda8941..2bdeff7 100644
--- a/src/java/org/apache/lenya/cms/ac/usecase/UsecaseAuthorizer.java
+++ b/src/java/org/apache/lenya/cms/ac/usecase/UsecaseAuthorizer.java
@@ -36,9 +36,12 @@
 import org.apache.lenya.ac.cache.CachingException;
 import org.apache.lenya.ac.cache.SourceCache;
 import org.apache.lenya.ac.impl.PolicyAuthorizer;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationException;
-import org.apache.lenya.cms.publication.PublicationUtil;
+import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.util.ServletHelper;
 
 /**
  * Authorizer for usecases.
@@ -68,8 +71,11 @@
      * @return A string representing a URI.
      */
     protected String getConfigurationURI(Publication publication) {
-        return "context:///" + Publication.PUBLICATION_PREFIX_URI + "/" + publication.getId()
-                + CONFIGURATION_FILE;
+        try {
+            return "context://lenya/pubs/" + publication.getPublicationId() + CONFIGURATION_FILE;
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     /**
@@ -90,7 +96,10 @@
                 if (getConfigurationURI() != null) {
                     _configurationUri = getConfigurationURI();
                 } else {
-                    Publication publication = PublicationUtil.getPublication(this.manager, request);
+                    Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+                    String url = ServletHelper.getWebappURI(request);
+                    String pubId = new URLInformation(url).getPublicationId();
+                    Publication publication = session.getPublication(pubId);
                     _configurationUri = getConfigurationURI(publication);
                 }
 
@@ -101,9 +110,7 @@
             }
         } catch (final ServiceException e) {
             throw new AccessControlException(e);
-        } catch (final PublicationException e) {
-            throw new AccessControlException(e);
-        } catch (final AccessControlException e) {
+        } catch (final Exception e) {
             throw new AccessControlException(e);
         } finally {
             if (resolver != null) {
diff --git a/src/java/org/apache/lenya/cms/ac/usecases/AccessControl.java b/src/java/org/apache/lenya/cms/ac/usecases/AccessControl.java
index f32f902..83bba55 100644
--- a/src/java/org/apache/lenya/cms/ac/usecases/AccessControl.java
+++ b/src/java/org/apache/lenya/cms/ac/usecases/AccessControl.java
@@ -22,10 +22,9 @@
 import java.util.List;
 
 import org.apache.cocoon.ProcessingException;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 import org.apache.lenya.cms.usecase.UsecaseException;
 
 import org.apache.lenya.ac.AccessControlException;
@@ -89,9 +88,8 @@
         try {
             URLInformation info = new URLInformation(getSourceURL());
             setParameter(COMPLETE_AREA, info.getCompleteArea());
-
-            DocumentIdentityMap map = getDocumentIdentityMap();
-            Document sourceDocument = map.getFromURL(getSourceURL());
+            
+            Document sourceDocument = RepositoryUtil.getDocument(getSession(), getSourceURL());
             setParameter(DOCUMENT, sourceDocument);
 
             setParameter(SSL, Boolean.toString(isSSLProtected()));
@@ -151,7 +149,7 @@
         super.doCheckPreconditions();
         URLInformation info = new URLInformation(getSourceURL());
         String acArea = getParameterAsString(AC_AREA);
-        if (!acArea.equals(Publication.LIVE_AREA) && !info.getArea().equals(acArea)) {
+        if (!acArea.equals("live") && !info.getArea().equals(acArea)) {
             addErrorMessage("This usecase can only be invoked in the configured area.");
         }
     }
diff --git a/src/java/org/apache/lenya/cms/ac/usecases/Login.java b/src/java/org/apache/lenya/cms/ac/usecases/Login.java
index d79d308..08eecf1 100644
--- a/src/java/org/apache/lenya/cms/ac/usecases/Login.java
+++ b/src/java/org/apache/lenya/cms/ac/usecases/Login.java
@@ -21,8 +21,7 @@
 import org.apache.cocoon.components.ContextHelper;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
+import org.apache.lenya.cms.publication.URLInformation;
 import org.apache.lenya.cms.usecase.UsecaseException;
 
 /**
@@ -40,13 +39,10 @@
      */
     protected void initParameters() {
         super.initParameters();
-
-        Publication publication;
-
         try {
-            publication = PublicationUtil.getPublicationFromUrl(this.manager, getSourceURL());
-            if (publication.exists()) {
-                setParameter(PUBLICATION_ID, publication.getId());
+            String pubId = new URLInformation(getSourceURL()).getPublicationId();
+            if (getSession().existsPublication(pubId)) {
+                setParameter(PUBLICATION_ID, pubId);
             }
         } catch (Exception e) {
             throw new RuntimeException(e);
diff --git a/src/java/org/apache/lenya/cms/ac/workflow/WorkflowAuthorizer.java b/src/java/org/apache/lenya/cms/ac/workflow/WorkflowAuthorizer.java
index ee0ca0d..84bab96 100644
--- a/src/java/org/apache/lenya/cms/ac/workflow/WorkflowAuthorizer.java
+++ b/src/java/org/apache/lenya/cms/ac/workflow/WorkflowAuthorizer.java
@@ -27,10 +27,9 @@
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.lenya.ac.AccessControlException;
 import org.apache.lenya.ac.Authorizer;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 import org.apache.lenya.cms.workflow.WorkflowUtil;
 import org.apache.lenya.util.ServletHelper;
 
@@ -79,12 +78,10 @@
 
             try {
                 resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-                Session session = RepositoryUtil.getSession(request, getLogger());
-                DocumentIdentityMap map = new DocumentIdentityMap(session,
-                        this.manager,
-                        getLogger());
-                if (map.isDocument(webappUrl)) {
-                    Document document = map.getFromURL(webappUrl);
+                Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+                
+                Document document = RepositoryUtil.getDocument(session, webappUrl);
+                if (document != null) {
                     authorized = WorkflowUtil.canInvoke(this.manager,
                             session,
                             getLogger(),
diff --git a/src/java/org/apache/lenya/cms/authoring/DefaultCreator.java b/src/java/org/apache/lenya/cms/authoring/DefaultCreator.java
index 40531ae..7058974 100644
--- a/src/java/org/apache/lenya/cms/authoring/DefaultCreator.java
+++ b/src/java/org/apache/lenya/cms/authoring/DefaultCreator.java
@@ -25,7 +25,6 @@
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.lenya.cms.cocoon.source.SourceUtil;
-import org.apache.lenya.cms.publication.DocumentBuildException;
 import org.apache.lenya.cms.publication.DocumentException;
 import org.w3c.dom.Document;
 
@@ -64,8 +63,7 @@
     /**
      * @see NodeCreatorInterface#create(String, org.apache.lenya.cms.publication.Document, Map)
      */
-    public void create(String initialContentsURI,
-            org.apache.lenya.cms.publication.Document document,
+    public void create(String initialContentsURI, org.apache.lenya.cms.repo.Document document,
             Map parameters) throws Exception {
 
         if (getLogger().isDebugEnabled())
@@ -93,12 +91,7 @@
         transformXML(xmlDoc, document, parameters);
 
         // write the document
-        try {
-            SourceUtil.writeDOM(xmlDoc, document.getSourceURI(), manager);
-        } catch (Exception e) {
-            throw new DocumentBuildException("could not write document [" + document
-                    + "], exception " + e.toString(), e);
-        }
+        SourceUtil.writeDOM(xmlDoc, document.getOutputStream(), manager);
     }
 
     /**
@@ -117,8 +110,7 @@
      * @param parameters additional parameters that can be used in the transformation
      * @throws Exception if the transformation fails
      */
-    protected void transformXML(Document doc,
-            org.apache.lenya.cms.publication.Document document,
+    protected void transformXML(Document doc, org.apache.lenya.cms.repo.Document document,
             Map parameters) throws Exception {
     }
 
diff --git a/src/java/org/apache/lenya/cms/authoring/NodeCreatorInterface.java b/src/java/org/apache/lenya/cms/authoring/NodeCreatorInterface.java
index 341c380..eaa937a 100644
--- a/src/java/org/apache/lenya/cms/authoring/NodeCreatorInterface.java
+++ b/src/java/org/apache/lenya/cms/authoring/NodeCreatorInterface.java
@@ -26,7 +26,8 @@
 /**
  * Interface for creation of nodes in the document hierarchy
  * @version $Id$
- * @deprecated This interface and it's implementations will be removed during the 1.4 development cycle
+ * @deprecated This interface and it's implementations will be removed during the 1.4 development
+ *             cycle
  */
 public interface NodeCreatorInterface {
 
@@ -57,8 +58,7 @@
      * 
      * @exception Exception if an error occurs
      */
-    void create(String initialContentsURI,
-            org.apache.lenya.cms.publication.Document document,
+    void create(String initialContentsURI, org.apache.lenya.cms.repo.Document document,
             Map parameters) throws Exception;
 
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/acting/LanguageExistsAction.java b/src/java/org/apache/lenya/cms/cocoon/acting/LanguageExistsAction.java
index 82df6c6..89290de 100644
--- a/src/java/org/apache/lenya/cms/cocoon/acting/LanguageExistsAction.java
+++ b/src/java/org/apache/lenya/cms/cocoon/acting/LanguageExistsAction.java
@@ -19,9 +19,6 @@
 
 package org.apache.lenya.cms.cocoon.acting;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.avalon.framework.parameters.Parameters;
@@ -30,11 +27,10 @@
 import org.apache.cocoon.environment.Redirector;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.SourceResolver;
-import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.DocumentDoesNotExistException;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 import org.apache.lenya.util.ServletHelper;
 
 /**
@@ -67,22 +63,15 @@
             Parameters parameters) throws Exception {
 
         Request request = ObjectModelHelper.getRequest(objectModel);
-        Session session = RepositoryUtil.getSession(request, getLogger());
-        DocumentIdentityMap map = new DocumentIdentityMap(session, this.manager, getLogger());
+        Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
 
         String url = ServletHelper.getWebappURI(request);
-        Document doc = map.getFromURL(url);
-        String language = doc.getLanguage();
+        Document doc = RepositoryUtil.getDocument(session, url);
 
-        if (!doc.existsInAnyLanguage()) {
-            throw new DocumentDoesNotExistException("Document " + doc.getId()
+        if (doc == null) {
+            throw new DocumentDoesNotExistException("Document for URL " + url
                     + " does not exist. Check sitetree, it might need to be reloaded.");
         }
-        List availableLanguages = Arrays.asList(doc.getLanguages());
-
-        if (availableLanguages.contains(language)) {
-            return Collections.unmodifiableMap(Collections.EMPTY_MAP);
-        }
         return null;
     }
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/acting/RevisionControllerAction.java b/src/java/org/apache/lenya/cms/cocoon/acting/RevisionControllerAction.java
index e4fdfbc..5121970 100644
--- a/src/java/org/apache/lenya/cms/cocoon/acting/RevisionControllerAction.java
+++ b/src/java/org/apache/lenya/cms/cocoon/acting/RevisionControllerAction.java
@@ -27,18 +27,16 @@
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.Session;
 import org.apache.cocoon.environment.SourceResolver;
-import org.apache.lenya.ac.AccessControlException;
 import org.apache.lenya.ac.Identity;
 import org.apache.lenya.ac.User;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.PageEnvelope;
-import org.apache.lenya.cms.publication.PageEnvelopeFactory;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
+import org.apache.lenya.cms.cocoon.source.SourceUtil;
+import org.apache.lenya.cms.publication.URLInformation;
 import org.apache.lenya.cms.rc.RCEnvironment;
 import org.apache.lenya.cms.rc.RevisionController;
-import org.apache.lenya.cms.repository.RepositoryUtil;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.util.ServletHelper;
 
 /**
  * Revision controller action.
@@ -51,7 +49,6 @@
     private String backupDirectory = null;
     private RevisionController rc = null;
     private String username = null;
-    private String filename = null;
 
     /**
      * @see org.apache.cocoon.acting.Action#act(org.apache.cocoon.environment.Redirector,
@@ -69,39 +66,27 @@
             return null;
         }
 
-        PageEnvelope envelope = null;
         Publication publication;
-
-        try {
-            publication = PublicationUtil.getPublication(this.manager, request);
-        } catch (Exception e) {
-            throw new AccessControlException(e);
-        }
-        org.apache.lenya.cms.repository.Session repoSession = RepositoryUtil.getSession(request,
+        org.apache.lenya.cms.repo.Session repoSession = RepositoryUtil.getSession(this.manager,
+                request,
                 getLogger());
-        DocumentIdentityMap map = new DocumentIdentityMap(repoSession, this.manager, getLogger());
-        Document document = null;
 
-        try {
-            publication = PublicationUtil.getPublication(this.manager, objectModel);
-            envelope = PageEnvelopeFactory.getInstance().getPageEnvelope(map, objectModel, publication);
-            document = envelope.getDocument();
-        } catch (Exception e) {
-            getLogger().error("Resolving page envelope failed: ", e);
-            throw e;
-        }
+        String url = ServletHelper.getWebappURI(request);
+        String pubId = new URLInformation(url).getPublicationId();
+        publication = repoSession.getPublication(pubId);
+        Document document = RepositoryUtil.getDocument(repoSession, url);
 
         // get Parameters for RC
-        String publicationPath = publication.getDirectory().getCanonicalPath();
-        RCEnvironment rcEnvironment = RCEnvironment.getInstance(publication.getServletContext()
-                .getCanonicalPath());
+        String contextPath = SourceUtil.getRealPath(this.manager, "");
+        String pubPath = SourceUtil.getRealPath(this.manager, "lenya/pubs/" + pubId);
+        RCEnvironment rcEnvironment = RCEnvironment.getInstance(contextPath);
         this.rcmlDirectory = rcEnvironment.getRCMLDirectory();
-        this.rcmlDirectory = publicationPath + File.separator + this.rcmlDirectory;
+        this.rcmlDirectory = pubPath + File.separator + this.rcmlDirectory;
         this.backupDirectory = rcEnvironment.getBackupDirectory();
-        this.backupDirectory = publicationPath + File.separator + this.backupDirectory;
+        this.backupDirectory = pubPath + File.separator + this.backupDirectory;
 
         // Initialize Revision Controller
-        this.rc = new RevisionController(this.rcmlDirectory, this.backupDirectory, publicationPath);
+        this.rc = new RevisionController(this.rcmlDirectory, this.backupDirectory, pubPath);
         getLogger().debug("revision controller" + this.rc);
 
         // /Initialize Revision Controller
@@ -121,36 +106,35 @@
         // cannot be get from
         // the page-envelope
 
-        String documentid = document.getId();
-        int bx = documentid.lastIndexOf("-bxe");
+        int bx = url.lastIndexOf("-bxe");
 
         if (bx > 0) {
             String language = document.getLanguage();
 
-            int l = documentid.length();
+            int l = url.length();
             int bxLength = "-bxe".length();
-            int lang = documentid.lastIndexOf("_", bx);
+            int lang = url.lastIndexOf("_", bx);
             int langLength = bx - lang;
 
             if (bx > 0 && bx + bxLength <= l) {
-                documentid = documentid.substring(0, bx) + documentid.substring(bx + bxLength, l);
+                url = url.substring(0, bx) + url.substring(bx + bxLength, l);
 
                 if (lang > 0 && langLength + lang < l) {
-                    language = documentid.substring(lang + 1, lang + langLength);
-                    documentid = documentid.substring(0, lang)
-                            + documentid.substring(lang + langLength, l - bxLength);
+                    language = url.substring(lang + 1, lang + langLength);
+                    url = url.substring(0, lang)
+                            + url.substring(lang + langLength, l - bxLength);
                 }
             }
 
-            Document srcDoc = map.get(publication, document.getArea(), documentid, language);
-            File newFile = srcDoc.getFile();
-            this.filename = newFile.getCanonicalPath();
+            Document srcDoc = document.getContentNode().getDocument(language);
+            // TODO File newFile = srcDoc.getFile();
+            // TODO this.filename = newFile.getCanonicalPath();
 
         } else {
-            this.filename = document.getFile().getCanonicalPath();
+            // TODO this.filename = document.getFile().getCanonicalPath();
         }
 
-        this.filename = this.filename.substring(publicationPath.length());
+        this.filename = this.filename.substring(pubPath.length());
 
         this.username = null;
 
@@ -167,6 +151,8 @@
 
         return null;
     }
+    
+    private String filename;
 
     /**
      * Get the filename.
diff --git a/src/java/org/apache/lenya/cms/cocoon/acting/WorkflowInvokerAction.java b/src/java/org/apache/lenya/cms/cocoon/acting/WorkflowInvokerAction.java
index a7260ea..bd65e0e 100644
--- a/src/java/org/apache/lenya/cms/cocoon/acting/WorkflowInvokerAction.java
+++ b/src/java/org/apache/lenya/cms/cocoon/acting/WorkflowInvokerAction.java
@@ -28,13 +28,10 @@
 import org.apache.cocoon.environment.Redirector;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.SourceResolver;
-import org.apache.lenya.ac.AccessControlException;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 import org.apache.lenya.cms.workflow.WorkflowUtil;
 
 /**
@@ -86,17 +83,12 @@
             getLogger().debug("    Event:       [" + eventName + "]");
         }
 
-        Publication pub;
         Request request = ObjectModelHelper.getRequest(objectModel);
 
-        try {
-            pub = PublicationUtil.getPublication(this.manager, request);
-        } catch (Exception e) {
-            throw new AccessControlException(e);
-        }
-        Session session = RepositoryUtil.getSession(request, getLogger());
-        DocumentIdentityMap map = new DocumentIdentityMap(session, this.manager, getLogger());
-        Document document = map.get(pub, area, documentId, language);
+        Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+        
+        Publication pub = RepositoryUtil.getPublication(this.manager, request, getLogger());
+        Document document = pub.getArea(area).getContent().getNode(documentId).getDocument(language);
 
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("    Invoking workflow event");
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AbstractPageEnvelopeModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AbstractPageEnvelopeModule.java
deleted file mode 100644
index 67147f3..0000000
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AbstractPageEnvelopeModule.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.cocoon.components.modules.input;
-
-import java.io.File;
-import java.util.Map;
-
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.cocoon.environment.Context;
-import org.apache.cocoon.environment.ObjectModelHelper;
-import org.apache.cocoon.environment.Request;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.PageEnvelope;
-import org.apache.lenya.cms.publication.PageEnvelopeFactory;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
-import org.apache.lenya.util.ServletHelper;
-
-/**
- * Abstract superclass for classes which need access to the page envelope.
- * 
- * The web application URL can be provided in the attribute name, separated by a colon (":").
- */
-public abstract class AbstractPageEnvelopeModule extends OperationModule {
-
-    /**
-     * Get the the page envelope for the given objectModel.
-     * @param objectModel the objectModel for which the page enevelope is requested.
-     * @param name The attribute name.
-     * @return a <code>PageEnvelope</code>
-     * @throws ConfigurationException if the page envelope could not be instantiated.
-     */
-    protected PageEnvelope getEnvelope(Map objectModel, String name) throws ConfigurationException {
-
-        String webappUrl = null;
-        Request request = ObjectModelHelper.getRequest(objectModel);
-
-        PageEnvelope envelope = (PageEnvelope) request.getAttribute(PageEnvelope.class.getName());
-        if (envelope == null) {
-
-            String[] snippets = name.split(":");
-            if (snippets.length > 1) {
-                webappUrl = snippets[1];
-            } else {
-                webappUrl = ServletHelper.getWebappURI(request);
-            }
-
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("Resolving page envelope for URL [" + webappUrl + "]");
-            }
-
-            String contextPath = request.getContextPath();
-            Context context = ObjectModelHelper.getContext(objectModel);
-            String servletContextPath = context.getRealPath("");
-
-            try {
-                DocumentIdentityMap map = getDocumentIdentityMap();
-                Publication pub = PublicationUtil.getPublicationFromUrl(this.manager, webappUrl);
-                envelope = PageEnvelopeFactory.getInstance().getPageEnvelope(map,
-                        contextPath,
-                        webappUrl,
-                        new File(servletContextPath),
-                        pub);
-            } catch (Exception e) {
-                throw new ConfigurationException("Resolving page envelope failed: ", e);
-            }
-            request.setAttribute(PageEnvelope.class.getName(), envelope);
-        }
-        return envelope;
-    }
-
-    /**
-     * @param name The original attribute name.
-     * @return The attribute name without URL attachment.
-     */
-    protected String getAttributeName(String name) {
-        final String[] snippets = name.split(":");
-        return snippets[0];
-    }
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AbstractServiceableInputModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AbstractServiceableInputModule.java
new file mode 100644
index 0000000..3bc22f6
--- /dev/null
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AbstractServiceableInputModule.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ */
+
+/* $Id: AccessControlModule.java 152682 2005-02-08 18:13:39Z gregor $  */
+
+package org.apache.lenya.cms.cocoon.components.modules.input;
+
+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.components.modules.input.AbstractInputModule;
+
+/**
+ * Input module for access control attributes.
+ */
+public abstract class AbstractServiceableInputModule extends AbstractInputModule implements Serviceable {
+
+    protected ServiceManager manager;
+
+    /**
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
+    public void service(ServiceManager _manager) throws ServiceException {
+        this.manager = _manager;
+    }
+
+}
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AccessControlModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AccessControlModule.java
index c0be5a7..f0b3083 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AccessControlModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/AccessControlModule.java
@@ -25,11 +25,7 @@
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.ServiceSelector;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.cocoon.components.modules.input.AbstractInputModule;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.Session;
@@ -48,7 +44,7 @@
 /**
  * Input module for access control attributes.
  */
-public class AccessControlModule extends AbstractInputModule implements Serviceable {
+public class AccessControlModule extends AbstractServiceableInputModule {
 
     /**
      * <code>USER_ID</code> The user id
@@ -247,13 +243,4 @@
         return itemManager;
     }
 
-    private ServiceManager manager;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager _manager) throws ServiceException {
-        this.manager = _manager;
-    }
-
 }
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/CustomMetaDataModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/CustomMetaDataModule.java
index 57c7102..0742ca6 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/CustomMetaDataModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/CustomMetaDataModule.java
@@ -22,16 +22,24 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Map;
+
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.lenya.cms.metadata.MetaData;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentException;
+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.components.modules.input.AbstractInputModule;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.cms.repo.metadata.MetaData;
 
 /**
  * Input module to access custom meta data values.
  */
-public class CustomMetaDataModule extends AbstractPageEnvelopeModule {
+public class CustomMetaDataModule extends AbstractInputModule implements Serviceable {
 
     final static String NS_PREFIX = "lenya:";
 
@@ -43,15 +51,13 @@
             throws ConfigurationException {
         Object value;
 
-        MetaData metaData = getCustomMetaData(objectModel);
-
-        if (!metaData.isValidAttribute(NS_PREFIX + name)) {
-            throw new ConfigurationException("The attribute [" + name + "] is not supported!");
-        }
-
         try {
-            value = metaData.getFirstValue(NS_PREFIX + name);
-        } catch (DocumentException e) {
+            MetaData metaData = getCustomMetaData(objectModel);
+            if (!metaData.getElementSet().contains(NS_PREFIX + name)) {
+                throw new ConfigurationException("The attribute [" + name + "] is not supported!");
+            }
+            value = metaData.getValue(NS_PREFIX + name);
+        } catch (RepositoryException e) {
             throw new ConfigurationException("Obtaining custom meta data value for [" + name
                     + "] failed: ", e);
         }
@@ -77,15 +83,15 @@
     public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)
             throws ConfigurationException {
         Object[] values;
-        MetaData metaData = getCustomMetaData(objectModel);
-
-        if (!metaData.isValidAttribute(NS_PREFIX + name)) {
-            throw new ConfigurationException("The attribute [" + name + "] is not supported!");
-        }
 
         try {
+            MetaData metaData = getCustomMetaData(objectModel);
+            if (!metaData.getElementSet().contains(NS_PREFIX + name)) {
+                throw new ConfigurationException("The attribute [" + name + "] is not supported!");
+            }
+
             values = metaData.getValues(NS_PREFIX + name);
-        } catch (DocumentException e) {
+        } catch (RepositoryException e) {
             throw new ConfigurationException("Obtaining custom meta data value for [" + name
                     + "] failed: ", e);
         }
@@ -95,17 +101,24 @@
 
     protected MetaData getCustomMetaData(Map objectModel) throws ConfigurationException {
         // FIXME: There seems to be no reason to pass the attribute name to get the page envelope.
-        Document document = getEnvelope(objectModel, "").getDocument();
-        if (document == null) {
-            throw new ConfigurationException("There is no document for this page envelope!");
-        }
         MetaData metaData = null;
         try {
-            metaData = document.getMetaDataManager().getCustomMetaData();
-        } catch (DocumentException e) {
-            throw new ConfigurationException("Obtaining custom meta data value for ["
-                    + document.getSourceURI() + "] failed: ", e);
+            Request request = ObjectModelHelper.getRequest(objectModel);
+            Document document = RepositoryUtil.getDocument(this.manager, request, getLogger());
+            if (document == null) {
+                throw new ConfigurationException("There is no document for this page envelope!");
+            }
+            metaData = document.getMetaData("custom");
+        } catch (RepositoryException e) {
+            throw new ConfigurationException("Obtaining custom meta data value failed: ", e);
         }
         return metaData;
     }
+
+    protected ServiceManager manager;
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+
+    }
 }
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentModule.java
new file mode 100644
index 0000000..5285319
--- /dev/null
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentModule.java
@@ -0,0 +1,78 @@
+/*
+ * 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.lenya.cms.cocoon.components.modules.input;
+
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+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.components.modules.input.AbstractInputModule;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.publication.URLUtil;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.util.ServletHelper;
+
+/**
+ * Document module.
+ */
+public class DocumentModule extends AbstractInputModule implements Serviceable {
+
+    protected static final String NODE_ID = "nodeId";
+    protected static final String AREA = "area";
+    protected static final String LANGUAGE = "language";
+    protected static final String LABEL = "label";
+    private ServiceManager manager;
+
+    public Object getAttribute(String name, Configuration modeConf, Map objectModel)
+            throws ConfigurationException {
+        Object value;
+
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String webappUrl = ServletHelper.getWebappURI(request);
+        Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+        Document document;
+        try {
+            document = URLUtil.getDocument(session, webappUrl);
+
+            if (name.equals(NODE_ID)) {
+                value = document.getContentNode().getNodeId();
+            } else if (name.equals(AREA)) {
+                value = document.getContentNode().getContent().getArea().getAreaID();
+            } else if (name.equals(LANGUAGE)) {
+                value = document.getLanguage();
+            } else if (name.equals(LABEL)) {
+                value = document.getLabel();
+            } else {
+                throw new ConfigurationException("The attribute [" + name + "] is not supported.");
+            }
+        } catch (RepositoryException e) {
+            throw new ConfigurationException("Error for attribute [" + name + "]:", e);
+        }
+        return value;
+    }
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+}
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentURLModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentURLModule.java
index d99689d..7d2a9e1 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentURLModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DocumentURLModule.java
@@ -36,7 +36,7 @@
  * </p>
  * @version $Id$
  */
-public class DocumentURLModule extends AbstractPageEnvelopeModule {
+public class DocumentURLModule extends AbstractServiceableInputModule {
 
     /**
      * @see org.apache.cocoon.components.modules.input.InputModule#getAttribute(java.lang.String,
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DublinCoreModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DublinCoreModule.java
index 4efb6d5..e3be0b5 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DublinCoreModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/DublinCoreModule.java
@@ -19,42 +19,50 @@
 
 package org.apache.lenya.cms.cocoon.components.modules.input;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.lenya.cms.metadata.MetaData;
-import org.apache.lenya.cms.metadata.dublincore.DublinCoreImpl;
-import org.apache.lenya.cms.publication.Document;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.cms.repo.metadata.Element;
+import org.apache.lenya.cms.repo.metadata.ElementSet;
+import org.apache.lenya.cms.repo.metadata.MetaData;
+import org.apache.lenya.cms.repo.metadata.impl.DublinCoreElements;
 
 /**
  * Input module to access the dublin core values.
  */
-public class DublinCoreModule extends AbstractPageEnvelopeModule {
+public class DublinCoreModule extends AbstractServiceableInputModule {
 
     /**
      * @see org.apache.cocoon.components.modules.input.InputModule#getAttribute(java.lang.String,
-     *      org.apache.avalon.framework.configuration.Configuration,
-     *      java.util.Map)
+     *      org.apache.avalon.framework.configuration.Configuration, java.util.Map)
      */
     public Object getAttribute(String name, Configuration modeConf, Map objectModel)
             throws ConfigurationException {
 
         Object value;
         try {
-            Document document = getEnvelope(objectModel, name).getDocument();
+            Request request = ObjectModelHelper.getRequest(objectModel);
+            Document document = RepositoryUtil.getDocument(this.manager, request, getLogger());
             if (document == null) {
                 throw new ConfigurationException("There is no document for this page envelope!");
             }
-            MetaData dc = document.getMetaDataManager().getDublinCoreMetaData();
+            MetaData dc = document.getMetaData(DublinCoreElements.NAME);
 
-            if (! dc.isValidAttribute(name)) {
+            if (!dc.getElementSet().contains(name)) {
                 throw new ConfigurationException("The attribute [" + name + "] is not supported!");
             }
 
-            value = dc.getFirstValue(name);
+            value = dc.getValue(name);
         } catch (Exception e) {
             throw new ConfigurationException("Obtaining dublin core value for [" + name
                     + "] failed: ", e);
@@ -73,15 +81,30 @@
         // calling static method on DublinCoreImpl is a work-around
         // because we do not have access to an instance here, because
         // the page envelope cannot be read here.
-        List names = DublinCoreImpl.getAttributeNames();
+
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+        ElementSet dcElements;
+        try {
+            dcElements = session.getRepository()
+                    .getMetaDataRegistry()
+                    .getElementSet(DublinCoreElements.NAME);
+        } catch (RepositoryException e) {
+            throw new ConfigurationException("Obtaining attribute names failed: ", e);
+        }
+
+        Element[] elements = dcElements.getElements();
+        List names = new ArrayList();
+        for (int i = 0; i < elements.length; i++) {
+            names.add(elements[i].getName());
+        }
 
         return names.iterator();
     }
 
     /**
      * @see org.apache.cocoon.components.modules.input.InputModule#getAttributeValues(java.lang.String,
-     *      org.apache.avalon.framework.configuration.Configuration,
-     *      java.util.Map)
+     *      org.apache.avalon.framework.configuration.Configuration, java.util.Map)
      */
     public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)
             throws ConfigurationException {
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/FallbackModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/FallbackModule.java
index d775c7f..e51e75c 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/FallbackModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/FallbackModule.java
@@ -42,7 +42,7 @@
  * 
  * @version $Id$
  */
-public class FallbackModule extends AbstractPageEnvelopeModule {
+public class FallbackModule extends AbstractServiceableInputModule {
 
     private String[] baseUris;
 
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java
deleted file mode 100644
index a79fb35..0000000
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/OperationModule.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.lenya.cms.cocoon.components.modules.input;
-
-import org.apache.avalon.framework.activity.Initializable;
-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.cocoon.components.ContextHelper;
-import org.apache.cocoon.components.modules.input.AbstractInputModule;
-import org.apache.cocoon.environment.Request;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
-import org.apache.lenya.transaction.Operation;
-import org.apache.lenya.transaction.UnitOfWork;
-import org.apache.lenya.transaction.UnitOfWorkImpl;
-
-/**
- * Super class for operation-based input modules.
- * 
- * @version $Id$
- */
-public class OperationModule extends AbstractInputModule implements Operation, Serviceable,
-        Initializable, Contextualizable {
-
-    /**
-     * Ctor.
-     */
-    public OperationModule() {
-        super();
-    }
-
-    private UnitOfWork unitOfWork;
-
-    private DocumentIdentityMap documentIdentityMap;
-
-    private Request request;
-
-    protected DocumentIdentityMap getDocumentIdentityMap() {
-        if (this.documentIdentityMap == null) {
-            Session session = RepositoryUtil.getSession(this.request, getLogger());
-            this.documentIdentityMap = new DocumentIdentityMap(session, this.manager, getLogger());
-        }
-        return this.documentIdentityMap;
-    }
-
-    /**
-     * Retrieves a unit-of-work, which gives the operation access to business objects affected by
-     * the operation.
-     * 
-     * @return a UnitOfWork, the interface to access the objects
-     * @throws ServiceException if the unit-of-work component can not be initialized by the
-     *             component framework
-     * 
-     * @see org.apache.lenya.transaction.Operation#getUnitOfWork()
-     */
-    public UnitOfWork getUnitOfWork() throws ServiceException {
-        if (this.unitOfWork == null) {
-            if (getLogger().isDebugEnabled())
-                getLogger().debug("OperationModule.getUnitOfWork() does not yet have instance.");
-
-            this.unitOfWork = new UnitOfWorkImpl(getDocumentIdentityMap().getIdentityMap(),
-                    getLogger());
-        }
-
-        return this.unitOfWork;
-    }
-
-    protected ServiceManager manager;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager _manager) throws ServiceException {
-        this.manager = _manager;
-    }
-
-    /**
-     * @see org.apache.avalon.framework.activity.Initializable#initialize()
-     */
-    public void initialize() throws Exception {
-        // do nothing
-    }
-
-    /**
-     * @see org.apache.avalon.framework.activity.Disposable#dispose()
-     */
-    public void dispose() {
-        if (this.manager != null) {
-            if (this.unitOfWork != null) {
-                this.manager.release(this.unitOfWork);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Operation#setUnitOfWork(org.apache.lenya.transaction.UnitOfWork)
-     */
-    public void setUnitOfWork(UnitOfWork unit) {
-        this.unitOfWork = unit;
-    }
-
-    public void contextualize(Context context) throws ContextException {
-        this.request = ContextHelper.getRequest(context);
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PageEnvelopeModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PageEnvelopeModule.java
deleted file mode 100644
index a3c75cf..0000000
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PageEnvelopeModule.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.cocoon.components.modules.input;
-
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.commons.lang.StringUtils;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentException;
-import org.apache.lenya.cms.publication.PageEnvelope;
-import org.apache.lenya.cms.publication.ResourceType;
-
-/**
- * Input module wrapping the page envelope. This module provides publication
- * related information such as document-id, area, publication-id.
- * 
- * @see org.apache.lenya.cms.publication.PageEnvelope
- */
-public class PageEnvelopeModule extends AbstractPageEnvelopeModule {
-
-    protected static final String URI_PARAMETER_DOCTYPE = "doctype";
-
-    /**
-     * @see org.apache.cocoon.components.modules.input.InputModule#getAttribute(java.lang.String,
-     *      org.apache.avalon.framework.configuration.Configuration,
-     *      java.util.Map)
-     */
-    public Object getAttribute(final String attributeName, Configuration modeConf, Map objectModel)
-            throws ConfigurationException {
-        
-        final String name = getAttributeName(attributeName);
-
-        if (!Arrays.asList(PageEnvelope.PARAMETER_NAMES).contains(name)) {
-            throw new ConfigurationException("The attribute [" + name + "] is not supported!");
-        }
-
-        PageEnvelope envelope = getEnvelope(objectModel, attributeName);
-        Object value = null;
-
-        try {
-            if (name.equals(PageEnvelope.AREA)) {
-                value = envelope.getArea();
-            } else if (name.equals(PageEnvelope.CONTEXT)) {
-                value = envelope.getContext();
-            } else if (name.equals(PageEnvelope.PUBLICATION_ID)) {
-                value = envelope.getPublication().getId();
-            } else if (name.equals(PageEnvelope.PUBLICATION)) {
-                value = envelope.getPublication();
-            } else if (name.equals(PageEnvelope.PUBLICATION_LANGUAGES_CSV)) {
-                value = StringUtils.join(envelope.getPublication().getLanguages(), ',');
-            } else if (name.equals(PageEnvelope.DEFAULT_LANGUAGE)) {
-                value = envelope.getPublication().getDefaultLanguage();
-            } else if (name.equals(PageEnvelope.BREADCRUMB_PREFIX)) {
-                value = envelope.getPublication().getBreadcrumbPrefix();
-            }
-
-            Document document = envelope.getDocument();
-            if (document != null) {
-                if (name.equals(PageEnvelope.DOCUMENT)) {
-                    value = document;
-                } else if (name.equals(PageEnvelope.DOCUMENT_ID)) {
-                    value = document.getId();
-                } else if (name.equals(PageEnvelope.DOCUMENT_NAME)) {
-                    value = document.getName();
-                } else if (name.equals(PageEnvelope.DOCUMENT_LABEL)) {
-                    value = document.getLabel();
-                } else if (name.equals(PageEnvelope.DOCUMENT_URL)) {
-                    value = document.getCanonicalDocumentURL();
-                } else if (name.equals(PageEnvelope.DOCUMENT_URL_WITHOUT_LANGUAGE)) {
-                    value = document.getCanonicalWebappURL();
-                } else if (name.equals(PageEnvelope.DOCUMENT_PATH)) {
-                    value = envelope.getDocumentPath();
-                } else if (name.equals(PageEnvelope.DOCUMENT_FILE)) {
-                    value = document.getFile();
-                } else if (name.equals(PageEnvelope.DOCUMENT_EXTENSION)) {
-                    value = document.getExtension();
-                } else if (name.equals(PageEnvelope.DOCUMENT_LANGUAGE)) {
-                    value = document.getLanguage();
-                } else if (name.equals(PageEnvelope.DOCUMENT_LANGUAGES)) {
-                    value = document.getLanguages();
-                } else if (name.equals(PageEnvelope.DOCUMENT_LANGUAGES_CSV)) {
-                    value = StringUtils.join(document.getLanguages(), ',');
-                } else if (name.equals(PageEnvelope.DOCUMENT_LASTMODIFIED)) {
-                    Date date = document.getLastModified();
-                    value = new SimpleDateFormat(DATE_FORMAT).format(date);
-                } else if (name.equals(PageEnvelope.DOCUMENT_TYPE)) {
-                    ResourceType resourceType = document.getResourceType();
-                    if (resourceType == null) {
-                        value = null;
-                    }
-                    else {
-                        value = resourceType.getName();
-                    }
-                }
-            }
-        } catch (final DocumentException e) {
-            throw new ConfigurationException("Getting attribute for name [" + name + "] failed: ",
-                    e);
-        }
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Returning [" + name + "] = [" + value + "]");
-        }
-
-        return value;
-    }
-
-    /**
-     * <code>DATE_FORMAT</code> The date format
-     */
-    public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
-
-    /**
-     * @see org.apache.cocoon.components.modules.input.InputModule#getAttributeNames(org.apache.avalon.framework.configuration.Configuration,
-     *      java.util.Map)
-     */
-    public Iterator getAttributeNames(Configuration modeConf, Map objectModel)
-            throws ConfigurationException {
-        return Arrays.asList(PageEnvelope.PARAMETER_NAMES).iterator();
-    }
-
-    /**
-     * @see org.apache.cocoon.components.modules.input.InputModule#getAttributeValues(java.lang.String,
-     *      org.apache.avalon.framework.configuration.Configuration,
-     *      java.util.Map)
-     */
-    public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)
-            throws ConfigurationException {
-        Object[] objects = { getAttribute(name, modeConf, objectModel) };
-
-        return objects;
-    }
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ProxyUrlModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ProxyUrlModule.java
index 143f3d2..6ce84d5 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ProxyUrlModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ProxyUrlModule.java
@@ -22,11 +22,7 @@
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.ServiceSelector;
-import org.apache.cocoon.components.modules.input.AbstractInputModule;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
 import org.apache.lenya.ac.AccessController;
@@ -37,13 +33,11 @@
 import org.apache.lenya.ac.PolicyManager;
 import org.apache.lenya.ac.impl.DefaultAccessController;
 import org.apache.lenya.ac.impl.PolicyAuthorizer;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.Proxy;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.proxy.Proxy;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.util.ServletHelper;
 
 /**
  * Input module for getting the proxied URL of a document.
@@ -59,9 +53,7 @@
  * 
  * @version $Id:$
  */
-public class ProxyUrlModule extends AbstractInputModule implements Serviceable {
-
-    private ServiceManager manager;
+public class ProxyUrlModule extends AbstractServiceableInputModule {
 
     /**
      * @see org.apache.cocoon.components.modules.input.InputModule#getAttribute(java.lang.String,
@@ -90,19 +82,21 @@
         String value = null;
         try {
             Request request = ObjectModelHelper.getRequest(objectModel);
-            Session session = RepositoryUtil.getSession(request, getLogger());
-            DocumentIdentityMap map = new DocumentIdentityMap(session, this.manager, getLogger());
-            Publication publication = PublicationUtil.getPublication(this.manager, request);
+            Publication publication = RepositoryUtil.getPublication(this.manager,
+                    request,
+                    getLogger());
 
-            Document doc = map.get(publication, area, documentId, language);
+            Document doc = publication.getArea(area)
+                    .getContent()
+                    .getNode(documentId)
+                    .getDocument(language);
 
             // Get proxy for document
             serviceSelector = (ServiceSelector) this.manager.lookup(AccessControllerResolver.ROLE
                     + "Selector");
-            acResolver = (AccessControllerResolver) serviceSelector
-                    .select(AccessControllerResolver.DEFAULT_RESOLVER);
+            acResolver = (AccessControllerResolver) serviceSelector.select(AccessControllerResolver.DEFAULT_RESOLVER);
 
-            String url = doc.getCanonicalWebappURL();
+            String url = ServletHelper.getWebappURI(request);
             AccessController accessController = acResolver.resolveAccessController(url);
             if (accessController instanceof DefaultAccessController) {
                 DefaultAccessController defaultAccessController = (DefaultAccessController) accessController;
@@ -118,14 +112,14 @@
 
             Policy policy = policyManager.getPolicy(accreditableManager, url);
 
-            Proxy proxy = doc.getPublication().getProxy(doc, policy.isSSLProtected());
+            Proxy proxy = publication.getProxy(doc, policy.isSSLProtected());
 
             if (proxy != null) {
                 value = proxy.getURL(doc);
             } else {
                 // Take server name and port from request.
                 value = "http://" + request.getServerName() + ":" + request.getServerPort()
-                        + request.getContextPath() + doc.getCanonicalWebappURL();
+                        + request.getContextPath() + url;
             }
 
         } catch (Exception e) {
@@ -153,10 +147,4 @@
         return objects;
     }
 
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-    }
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationFallbackModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationFallbackModule.java
index 15c90da..09f9fdf 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationFallbackModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationFallbackModule.java
@@ -20,8 +20,10 @@
 import java.util.Map;
 
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.lenya.cms.publication.PageEnvelope;
-import org.apache.lenya.cms.publication.Publication;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.util.ServletHelper;
 
 /**
  * Publication Fallback Module
@@ -43,11 +45,11 @@
         String[] superUris = super.getBaseURIs(objectModel, name);
         String[] uris = new String[superUris.length + 1];
 
-        PageEnvelope envelope = getEnvelope(objectModel, name);
-        String publicationId = envelope.getPublication().getId();
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String url = ServletHelper.getWebappURI(request);
+        String publicationId = new URLInformation(url).getPublicationId();
 
-        String publicationUri = "context://" + Publication.PUBLICATION_PREFIX_URI + "/"
-                + publicationId + "/lenya";
+        String publicationUri = "context://lenya/pubs/" + publicationId + "/lenya";
         uris[0] = publicationUri;
 
         for (int i = 0; i < superUris.length; i++) {
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationModule.java
new file mode 100644
index 0000000..98c700d
--- /dev/null
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationModule.java
@@ -0,0 +1,81 @@
+/*
+ * 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.lenya.cms.cocoon.components.modules.input;
+
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+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.components.modules.input.AbstractInputModule;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.commons.lang.StringUtils;
+import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
+import org.apache.lenya.util.ServletHelper;
+
+/**
+ * Publication module.
+ */
+public class PublicationModule extends AbstractInputModule implements Serviceable {
+
+    protected static final String ID = "id";
+    protected static final String DEFAULT_LANGUAGE = "defaultLanguage";
+    protected static final String LANGUAGES_CSV = "languagesCsv";
+
+    public Object getAttribute(String name, Configuration modeConf, Map objectModel)
+            throws ConfigurationException {
+        Object value;
+
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String webappUrl = ServletHelper.getWebappURI(request);
+        Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+
+        String pubId = new URLInformation(webappUrl).getPublicationId();
+        try {
+            Publication pub = session.getPublication(pubId);
+
+            if (name.equals(ID)) {
+                value = pub.getPublicationId();
+            } else if (name.equals(DEFAULT_LANGUAGE)) {
+                return pub.getDefaultLanguage();
+            } else if (name.equals(LANGUAGES_CSV)) {
+                value = StringUtils.join(pub.getLanguages(), ',');
+            } else {
+                throw new ConfigurationException("The attribute [" + name + "] is not supported.");
+            }
+
+        } catch (RepositoryException e) {
+            throw new ConfigurationException("Error for attribute [" + name + "]: ", e);
+        }
+
+        return value;
+    }
+
+    protected ServiceManager manager;
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+}
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationTemplateFallbackModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationTemplateFallbackModule.java
index 9c43936..7a3c73e 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationTemplateFallbackModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/PublicationTemplateFallbackModule.java
@@ -20,10 +20,14 @@
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
 import org.apache.lenya.cms.publication.templating.ExistingSourceResolver;
 import org.apache.lenya.cms.publication.templating.PublicationTemplateManager;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 
 /**
  * This module uses publication templating to resolve the real path for a resource. The current
@@ -33,7 +37,7 @@
  * 
  * @version $Id$
  */
-public class PublicationTemplateFallbackModule extends AbstractPageEnvelopeModule {
+public class PublicationTemplateFallbackModule extends AbstractServiceableInputModule {
 
     /**
      * Ctor.
@@ -57,8 +61,11 @@
         PublicationTemplateManager templateManager = null;
 
         try {
+
+            Request request = ObjectModelHelper.getRequest(objectModel);
+
             templateManager = (PublicationTemplateManager) this.manager.lookup(PublicationTemplateManager.ROLE);
-            Publication publication;
+            Publication publication = null;
             String targetUri = null;
 
             // check if publication ID is provided in attribute name
@@ -75,22 +82,25 @@
                             + "]");
                 }
 
-                publication = PublicationUtil.getPublication(this.manager, publicationId);
+                Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
+                if (session.existsPublication(publicationId)) {
+                    publication = session.getPublication(publicationId);
+                }
             } else {
-                publication = PublicationUtil.getPublication(this.manager, objectModel);
+                publication = RepositoryUtil.getPublication(this.manager, request, getLogger());
                 targetUri = name;
                 if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("Publication resolved from request: [" + publication.getId()
-                            + "]");
+                    getLogger().debug("Publication resolved from request: ["
+                            + publication.getPublicationId() + "]");
                 }
             }
-            if (publication.exists()) {
+            if (publication != null) {
                 ExistingSourceResolver resolver = new ExistingSourceResolver();
                 templateManager.visit(publication, targetUri, resolver);
                 resolvedUri = resolver.getURI();
             } else {
-                //outside of a publication
-            	resolvedUri = "context://" + targetUri;
+                // outside of a publication
+                resolvedUri = "context://" + targetUri;
             }
         } catch (final Exception e) {
             String message = "Resolving path [" + name + "] failed: ";
@@ -110,9 +120,11 @@
      * @return A string.
      */
     public static String getBaseURI(Publication publication) {
-        String publicationUri = "context://" + Publication.PUBLICATION_PREFIX_URI + "/"
-                + publication.getId();
-        return publicationUri;
+        try {
+            return "context://lenya/pubs/" + publication.getPublicationId();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     /**
@@ -121,9 +133,7 @@
      * @return A string.
      */
     protected String getLenyaBaseURI(Publication publication) {
-        String publicationUri = "context://" + Publication.PUBLICATION_PREFIX_URI + "/"
-                + publication.getId() + "/lenya";
-        return publicationUri;
+        return getBaseURI(publication) + "/lenya";
     }
 
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ResourceTypeModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ResourceTypeModule.java
index 0b474ba..e0d695a 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ResourceTypeModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/ResourceTypeModule.java
@@ -20,23 +20,16 @@
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-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.components.modules.input.AbstractInputModule;
 import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Request;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.ResourceType;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
-import org.apache.lenya.util.ServletHelper;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.DocumentType;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 
 /**
  * Resource type module.
  */
-public class ResourceTypeModule extends AbstractInputModule implements Serviceable {
+public class ResourceTypeModule extends AbstractServiceableInputModule {
 
     public Object getAttribute(String name, Configuration modeConf, Map objectModel)
             throws ConfigurationException {
@@ -44,18 +37,13 @@
 
         try {
             Request request = ObjectModelHelper.getRequest(objectModel);
-            Session session = RepositoryUtil.getSession(request, getLogger());
-            DocumentIdentityMap docFactory = new DocumentIdentityMap(session,
-                    this.manager,
-                    getLogger());
-            String webappUrl = ServletHelper.getWebappURI(request);
-            Document document = docFactory.getFromURL(webappUrl);
-            ResourceType resourceType = document.getResourceType();
+            Document document = RepositoryUtil.getDocument(this.manager, request, getLogger());
+            DocumentType docType = document.getContentNode().getDocumentType();
 
             if (name.startsWith("format-")) {
                 String[] steps = name.split("-");
                 String format = steps[1];
-                value = resourceType.getFormatURI(format);
+                value = docType.getFormatURI(format);
             }
             else {
                 throw new ConfigurationException("Attribute [" + name + "] not supported!");
@@ -69,10 +57,4 @@
         return value;
     }
 
-    protected ServiceManager manager;
-
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-    }
-
 }
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/UsecaseFallbackModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/UsecaseFallbackModule.java
index e0d2b76..d28a8ee 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/UsecaseFallbackModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/UsecaseFallbackModule.java
@@ -23,19 +23,18 @@
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.lenya.cms.publication.PageEnvelope;
-import org.apache.lenya.cms.publication.Publication;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
 import org.apache.lenya.cms.publication.templating.ExistingUsecaseResolver;
 import org.apache.lenya.cms.publication.templating.PublicationTemplateManager;
 import org.apache.lenya.cms.publication.templating.PublicationTemplateManagerImpl;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 
 /**
  * Input module to resolve fallback usecases
  */
-public class UsecaseFallbackModule extends AbstractPageEnvelopeModule implements Serviceable {
+public class UsecaseFallbackModule extends AbstractServiceableInputModule {
 
     /**
      * Ctor.
@@ -56,12 +55,14 @@
         String resolvedSitemapUri = null;
 
         try {
-            PublicationTemplateManager templateManager = (PublicationTemplateManager) this._manager
+            PublicationTemplateManager templateManager = (PublicationTemplateManager) this.manager
                     .lookup(PublicationTemplateManager.ROLE);
-            PageEnvelope envelope = getEnvelope(objectModel, name);
-
+            
+            Request request = ObjectModelHelper.getRequest(objectModel);
+            Publication pub = RepositoryUtil.getPublication(this.manager, request, getLogger());
+            
             ExistingUsecaseResolver resolver = new ExistingUsecaseResolver(name);
-            templateManager.visit(envelope.getPublication(), resolver);
+            templateManager.visit(pub, resolver);
 
             Publication publication = resolver.getPublication();
             if (publication != null) {
@@ -77,13 +78,4 @@
         return resolvedSitemapUri;
     }
  
-    private ServiceManager _manager;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager mymanager) throws ServiceException {
-        this._manager = mymanager;
-    }
-
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/WorkflowModule.java b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/WorkflowModule.java
index 4adcac9..3bdcee2 100644
--- a/src/java/org/apache/lenya/cms/cocoon/components/modules/input/WorkflowModule.java
+++ b/src/java/org/apache/lenya/cms/cocoon/components/modules/input/WorkflowModule.java
@@ -25,10 +25,10 @@
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.cocoon.environment.ObjectModelHelper;
-import org.apache.lenya.cms.publication.Document;
-import org.apache.lenya.cms.publication.PageEnvelope;
-import org.apache.lenya.cms.repository.RepositoryUtil;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.RepositoryUtil;
 import org.apache.lenya.cms.workflow.DocumentWorkflowable;
 import org.apache.lenya.workflow.Version;
 import org.apache.lenya.workflow.Workflow;
@@ -39,7 +39,7 @@
  * 
  * @version $Id$
  */
-public class WorkflowModule extends AbstractPageEnvelopeModule {
+public class WorkflowModule extends AbstractServiceableInputModule {
 
     /**
      * <code>STATE</code> The state
@@ -68,12 +68,11 @@
         WorkflowManager wfManager = null;
 
         try {
-            PageEnvelope envelope = getEnvelope(objectModel, name);
-            Document document = envelope.getDocument();
-            if (document != null && document.exists()) {
+            Request request = ObjectModelHelper.getRequest(objectModel);
+            Document document = RepositoryUtil.getDocument(this.manager, request, getLogger());
+            if (document != null) {
                 wfManager = (WorkflowManager) this.manager.lookup(WorkflowManager.ROLE);
-                Session session = RepositoryUtil.getSession(ObjectModelHelper.getRequest(objectModel),
-                        getLogger());
+                Session session = RepositoryUtil.getSession(this.manager, request, getLogger());
                 DocumentWorkflowable workflowable = new DocumentWorkflowable(this.manager,
                         session,
                         document,
diff --git a/src/java/org/apache/lenya/cms/cocoon/source/SourceUtil.java b/src/java/org/apache/lenya/cms/cocoon/source/SourceUtil.java
index 0917f75..8fa8b03 100644
--- a/src/java/org/apache/lenya/cms/cocoon/source/SourceUtil.java
+++ b/src/java/org/apache/lenya/cms/cocoon/source/SourceUtil.java
@@ -17,6 +17,7 @@
 
 package org.apache.lenya.cms.cocoon.source;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -37,7 +38,6 @@
 import org.apache.excalibur.source.SourceException;
 import org.apache.excalibur.source.SourceNotFoundException;
 import org.apache.excalibur.source.SourceResolver;
-import org.apache.lenya.cms.repository.RepositoryException;
 import org.apache.lenya.xml.DocumentHelper;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
@@ -214,6 +214,32 @@
     }
 
     /**
+     * Writes a DOM to an output stream.
+     * @param document The document.
+     * @param oStream The output stream.
+     * @param manager The service manager.
+     * @throws TransformerConfigurationException if an error occurs.
+     * @throws TransformerException if an error occurs.
+     * @throws ServiceException if the source resolver could not be obtained.
+     * @throws MalformedURLException if the source URI is not valid.
+     * @throws IOException if an error occurs.
+     */
+    public static void writeDOM(Document document, OutputStream oStream, ServiceManager manager)
+            throws TransformerConfigurationException, TransformerException, ServiceException,
+            MalformedURLException, IOException {
+        Writer writer = new OutputStreamWriter(oStream);
+        DocumentHelper.writeDocument(document, writer);
+        if (oStream != null) {
+            oStream.flush();
+            try {
+                oStream.close();
+            } catch (Throwable t) {
+                throw new RuntimeException("Could not write document: ", t);
+            }
+        }
+    }
+
+    /**
      * Deletes a source if it exists.
      * @param sourceUri The source URI.
      * @param manager The service manager.
@@ -272,25 +298,23 @@
     }
 
     /**
-     * Checks out a repository source.
-     * @param sourceUri The source URI.
      * @param manager The service manager.
-     * @throws RepositoryException If an error occurs.
-     * @throws ServiceException If an error occurs.
-     * @throws MalformedURLException If an error occurs.
-     * @throws IOException If an error occurs.
+     * @param contextPath The relative path inside the context.
+     * @return The file system path.
+     * @throws IOException if an error occurs.
+     * @throws MalformedURLException if an error occurs. 
+     * @throws ServiceException  if an error occurs.
      */
-    public static void checkout(String sourceUri, ServiceManager manager)
-            throws RepositoryException, ServiceException, MalformedURLException, IOException {
+    public static String getRealPath(ServiceManager manager, String contextPath)
+            throws MalformedURLException, IOException, ServiceException {
         SourceResolver resolver = null;
-        RepositorySource source = null;
+        Source source = null;
         try {
-
             resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-            source = (RepositorySource) resolver.resolveURI(sourceUri);
-
-            source.getNode().checkout();
-
+            source = resolver.resolveURI("context://");
+            File contextFile = org.apache.excalibur.source.SourceUtil.getFile(source);
+            File file = new File(contextFile, contextPath.replace('/', File.separatorChar));
+            return file.getAbsolutePath();
         } finally {
             if (resolver != null) {
                 if (source != null) {
@@ -299,121 +323,6 @@
                 manager.release(resolver);
             }
         }
-    }
 
-    /**
-     * Checks in a transactionable source.
-     * @param sourceUri The source URI.
-     * @param manager The service manager.
-     * @throws RepositoryException If an error occurs.
-     * @throws ServiceException If an error occurs.
-     * @throws MalformedURLException If an error occurs.
-     * @throws IOException If an error occurs.
-     */
-    public static void checkin(String sourceUri, ServiceManager manager)
-            throws RepositoryException, ServiceException, MalformedURLException, IOException {
-        SourceResolver resolver = null;
-        RepositorySource source = null;
-        try {
-
-            resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-            source = (RepositorySource) resolver.resolveURI(sourceUri);
-
-            source.getNode().checkin();
-
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * Locks a transactionable source.
-     * @param sourceUri The source URI.
-     * @param manager The service manager.
-     * @throws RepositoryException If an error occurs.
-     */
-    public static void lock(String sourceUri, ServiceManager manager) throws RepositoryException {
-        SourceResolver resolver = null;
-        RepositorySource source = null;
-        try {
-
-            resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-            source = (RepositorySource) resolver.resolveURI(sourceUri);
-
-            source.getNode().lock();
-
-        } catch (RepositoryException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * Unlocks a transactionable source.
-     * @param sourceUri The source URI.
-     * @param manager The service manager.
-     * @throws RepositoryException If an error occurs.
-     */
-    public static void unlock(String sourceUri, ServiceManager manager) throws RepositoryException {
-        SourceResolver resolver = null;
-        RepositorySource source = null;
-        try {
-
-            resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-            source = (RepositorySource) resolver.resolveURI(sourceUri);
-
-            source.getNode().unlock();
-
-        } catch (RepositoryException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * Registers a source as dirty.
-     * @param sourceUri The source URI.
-     * @param manager The service manager.
-     */
-    public static void registerDirty(String sourceUri, ServiceManager manager) {
-        SourceResolver resolver = null;
-        RepositorySource source = null;
-        try {
-
-            resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-            source = (RepositorySource) resolver.resolveURI(sourceUri);
-            source.getNode().registerDirty();
-            
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                manager.release(resolver);
-            }
-        }
     }
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java b/src/java/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java
index 9547b50..7898114 100644
--- a/src/java/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java
+++ b/src/java/org/apache/lenya/cms/cocoon/transformation/LinkRewritingTransformer.java
@@ -37,11 +37,11 @@
 import org.apache.lenya.ac.PolicyManager;
 import org.apache.lenya.ac.impl.DefaultAccessController;
 import org.apache.lenya.ac.impl.PolicyAuthorizer;
+import org.apache.lenya.cms.proxy.Proxy;
 import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.DocumentBuildException;
 import org.apache.lenya.cms.publication.DocumentException;
 import org.apache.lenya.cms.publication.DocumentIdentityMap;
-import org.apache.lenya.cms.publication.Proxy;
 import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.cms.repository.RepositoryUtil;
 import org.apache.lenya.cms.repository.Session;
diff --git a/src/java/org/apache/lenya/cms/proxy/Proxy.java b/src/java/org/apache/lenya/cms/proxy/Proxy.java
new file mode 100644
index 0000000..306dd60
--- /dev/null
+++ b/src/java/org/apache/lenya/cms/proxy/Proxy.java
@@ -0,0 +1,82 @@
+/*
+ * 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.lenya.cms.proxy;
+
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Site;
+import org.apache.lenya.cms.repo.SiteNode;
+
+/**
+ * <p>
+ * An object of this class represents a proxy configuration.
+ * </p>
+ * <p>
+ * Configuration example:
+ * </p>
+ * 
+ * <pre>
+ *  &lt;proxy area=&quot;live&quot; ssl=&quot;true&quot; url=&quot;https://www.host.com/ssl/default&quot;/&gt;
+ *  &lt;proxy area=&quot;live&quot; ssl=&quot;false&quot; url=&quot;http://www.host.com/default&quot;/&gt;
+ *  &lt;proxy area=&quot;authoring&quot; ssl=&quot;true&quot; url=&quot;https://www.host.com/lenya/default/authoring&quot;/&gt;
+ *  &lt;proxy area=&quot;authoring&quot; ssl=&quot;false&quot; url=&quot;http://www.host.com/lenya/default/authoring&quot;/&gt;
+ * </pre>
+ * 
+ * @version $Id$
+ */
+public class Proxy {
+
+    private String url;
+
+    /**
+     * Returns the absolute URL of a particular document.
+     * @param document The document.
+     * @return A string.
+     */
+    public String getURL(Document document) {
+        try {
+            Site site = document.getContentNode().getContent().getArea().getSite();
+            SiteNode siteNode = site.getFirstReference(document);
+            return getUrl() + siteNode.getPath();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Returns the proxy URL.
+     * @return A string.
+     */
+    public String getUrl() {
+        return this.url;
+    }
+
+    /**
+     * Sets the proxy URL.
+     * @param _url The url to set.
+     */
+    public void setUrl(String _url) {
+        this.url = _url;
+    }
+
+    /**
+     * @see java.lang.Object#toString()
+     */
+    public String toString() {
+        return "Proxy URL=[" + getUrl() + "]";
+    }
+}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/DefaultDocument.java b/src/java/org/apache/lenya/cms/publication/DefaultDocument.java
deleted file mode 100644
index 7974fe4..0000000
--- a/src/java/org/apache/lenya/cms/publication/DefaultDocument.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.ServiceSelector;
-import org.apache.excalibur.source.SourceResolver;
-import org.apache.lenya.cms.cocoon.source.RepositorySource;
-import org.apache.lenya.cms.cocoon.source.SourceUtil;
-import org.apache.lenya.cms.metadata.LenyaMetaData;
-import org.apache.lenya.cms.metadata.MetaDataManager;
-import org.apache.lenya.cms.publication.util.DocumentVisitor;
-import org.apache.lenya.cms.repository.Node;
-import org.apache.lenya.cms.site.SiteManager;
-
-/**
- * A typical CMS document.
- * @version $Id$
- */
-public class DefaultDocument extends AbstractLogEnabled implements Document {
-
-    private DocumentIdentifier identifier;
-    private String sourceURI;
-    private DocumentIdentityMap identityMap;
-    protected ServiceManager manager;
-    private MetaDataManager metaDataManager;
-
-    /**
-     * Creates a new instance of DefaultDocument.
-     * @param manager The service manager.
-     * @param map The identity map the document belongs to.
-     * @param identifier The identifier.
-     * @param _logger a logger
-     */
-    protected DefaultDocument(ServiceManager manager, DocumentIdentityMap map,
-            DocumentIdentifier identifier, Logger _logger) {
-
-        ContainerUtil.enableLogging(this, _logger);
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DefaultDocument() creating new instance with id ["
-                    + identifier.getId() + "], language [" + identifier.getLanguage() + "]");
-
-        this.manager = manager;
-        this.identifier = identifier;
-        if (identifier.getId() == null) {
-            throw new IllegalArgumentException("The document ID must not be null!");
-        }
-        if (!identifier.getId().startsWith("/")) {
-            throw new IllegalArgumentException("The document ID must start with a slash!");
-        }
-
-        this.identityMap = map;
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DefaultDocument() done building instance with _id ["
-                    + identifier.getId() + "], _language [" + identifier.getLanguage() + "]");
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getId()
-     */
-    public String getId() {
-        return this.identifier.getId();
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getName()
-     */
-    public String getName() {
-        String[] ids = getId().split("/");
-        String nodeId = ids[ids.length - 1];
-
-        return nodeId;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getPublication()
-     */
-    public Publication getPublication() {
-        return this.identifier.getPublication();
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getLastModified()
-     */
-    public Date getLastModified() {
-        return new Date(getFile().lastModified());
-    }
-
-    /**
-     * Returns the file for this document.
-     * @return A file object.
-     */
-    public File getFile() {
-        return getPublication().getPathMapper().getFile(getPublication(),
-                getArea(),
-                getId(),
-                getLanguage());
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getLanguage()
-     */
-    public String getLanguage() {
-        return this.identifier.getLanguage();
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getLanguages()
-     */
-    public String[] getLanguages() throws DocumentException {
-
-        List documentLanguages = new ArrayList();
-        String[] allLanguages = getPublication().getLanguages();
-
-        for (int i = 0; i < allLanguages.length; i++) {
-            Document version;
-            try {
-                version = getIdentityMap().getLanguageVersion(this, allLanguages[i]);
-            } catch (DocumentBuildException e) {
-                throw new DocumentException(e);
-            }
-            if (version.exists()) {
-                documentLanguages.add(allLanguages[i]);
-            }
-        }
-
-        return (String[]) documentLanguages.toArray(new String[documentLanguages.size()]);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getLabel()
-     */
-    public String getLabel() throws DocumentException {
-        String labelString = "";
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        try {
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            siteManager = (SiteManager) selector.select(getPublication().getSiteManagerHint());
-            if (siteManager != null) {
-                labelString = siteManager.getLabel(this);
-            }
-        } catch (Exception e) {
-            throw new DocumentException(e);
-        } finally {
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-        return labelString;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getArea()
-     */
-    public String getArea() {
-        return this.identifier.getArea();
-    }
-
-    private String extension = "html";
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getExtension()
-     */
-    public String getExtension() {
-        return this.extension;
-    }
-
-    /**
-     * Sets the extension of the file in the URL.
-     * @param _extension A string.
-     */
-    protected void setExtension(String _extension) {
-        assert _extension != null;
-        this.extension = _extension;
-    }
-
-    private String documentURL;
-
-    /**
-     * Sets the document URL.
-     * @param url The document URL (without publication ID and area).
-     */
-    public void setDocumentURL(String url) {
-        assert url != null;
-        this.documentURL = url;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#exists()
-     */
-    public boolean exists() throws DocumentException {
-        boolean exists;
-        String hint = getPublication().getSiteManagerHint();
-        if (hint == null) {
-            try {
-                exists = SourceUtil.exists(getSourceURI(), this.manager);
-            } catch (Exception e) {
-                throw new DocumentException(e);
-            }
-        } else {
-            SiteManager siteManager = null;
-            ServiceSelector selector = null;
-            try {
-                selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-                siteManager = (SiteManager) selector.select(hint);
-                exists = siteManager.contains(this);
-            } catch (Exception e) {
-                throw new DocumentException(e);
-            } finally {
-                if (selector != null) {
-                    if (siteManager != null) {
-                        selector.release(siteManager);
-                    }
-                    this.manager.release(selector);
-                }
-            }
-        }
-        return exists;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#existsInAnyLanguage()
-     */
-    public boolean existsInAnyLanguage() throws DocumentException {
-        boolean exists = false;
-
-        try {
-            String[] languages = getLanguages();
-            for (int i = 0; i < languages.length; i++) {
-                Document languageVersion = getIdentityMap().getLanguageVersion(this, languages[i]);
-                exists = exists || languageVersion.exists();
-            }
-        } catch (DocumentBuildException e) {
-            throw new DocumentException(e);
-        }
-        return exists;
-    }
-
-    /**
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    public boolean equals(Object object) {
-        boolean equals = false;
-        if (getClass().isInstance(object)) {
-            Document document = (Document) object;
-            equals = getPublication().equals(document.getPublication())
-                    && getId().equals(document.getId()) && getArea().equals(document.getArea())
-                    && getLanguage().equals(document.getLanguage());
-        }
-        return equals;
-
-    }
-
-    /**
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-
-        String key = getPublication().getId() + ":" + getPublication().getServletContext() + ":"
-                + getArea() + ":" + getId() + ":" + getLanguage();
-
-        return key.hashCode();
-    }
-
-    /**
-     * @see java.lang.Object#toString()
-     */
-    public String toString() {
-        return getPublication().getId() + ":" + getArea() + ":" + getId() + ":" + getLanguage();
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getIdentityMap()
-     */
-    public DocumentIdentityMap getIdentityMap() {
-        return this.identityMap;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getCanonicalWebappURL()
-     */
-    public String getCanonicalWebappURL() {
-        return "/" + getPublication().getId() + "/" + getArea() + getCanonicalDocumentURL();
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getCanonicalDocumentURL()
-     */
-    public String getCanonicalDocumentURL() {
-        return this.documentURL;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#accept(org.apache.lenya.cms.publication.util.DocumentVisitor)
-     */
-    public void accept(DocumentVisitor visitor) throws PublicationException {
-        visitor.visitDocument(this);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.metadata.MetaDataOwner#getMetaDataManager()
-     */
-    public MetaDataManager getMetaDataManager() {
-        if (this.metaDataManager == null) {
-            SourceResolver resolver = null;
-            RepositorySource source = null;
-            try {
-                resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-                source = (RepositorySource) resolver.resolveURI(getSourceURI());
-                this.metaDataManager = source.getNode().getMetaDataManager();
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            } finally {
-                if (resolver != null) {
-                    if (source != null) {
-                        resolver.release(source);
-                    }
-                    this.manager.release(resolver);
-                }
-            }
-        }
-        return metaDataManager;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#delete()
-     */
-    public void delete() throws DocumentException {
-        try {
-            SourceUtil.delete(getSourceURI(), this.manager);
-        } catch (Exception e) {
-            throw new DocumentException(e);
-        }
-    }
-
-    protected static final String IDENTIFIABLE_TYPE = "document";
-
-    /**
-     * @see org.apache.lenya.transaction.Identifiable#getIdentifiableType()
-     */
-    public String getIdentifiableType() {
-        return IDENTIFIABLE_TYPE;
-    }
-
-    /**
-     * When source URI has not been set by whoever created the document, provides a default
-     * mechanism for constructing the document's URI.
-     * @return A URI.
-     */
-    private String getDefaultSourceURI() {
-        String path = getPublication().getPathMapper().getPath(getId(), getLanguage());
-        return getPublication().getSourceURI() + "/content/" + getArea() + "/" + path;
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getSourceURI()
-     */
-    public String getSourceURI() {
-        if (sourceURI == null)
-            sourceURI = getDefaultSourceURI();
-        return sourceURI;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#setSourceURI(String)
-     */
-    public void setSourceURI(String _uri) {
-        sourceURI = _uri;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Document#getRepositoryNode()
-     */
-    public Node getRepositoryNode() {
-        Node node = null;
-        SourceResolver resolver = null;
-        RepositorySource documentSource = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            documentSource = (RepositorySource) resolver.resolveURI(getSourceURI());
-            node = documentSource.getNode();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (resolver != null) {
-                if (documentSource != null) {
-                    resolver.release(documentSource);
-                }
-                this.manager.release(resolver);
-            }
-        }
-        return node;
-    }
-
-    private ResourceType resourceType;
-
-    /**
-     * Convenience method to read the document's resource type from the meta-data.
-     * @see Document#getResourceType()
-     */
-    public ResourceType getResourceType() throws DocumentException {
-        if (this.resourceType == null) {
-            String name = getMetaDataManager().getLenyaMetaData()
-                    .getFirstValue(LenyaMetaData.ELEMENT_RESOURCE_TYPE);
-            if (name == null) {
-                throw new DocumentException("No resource type defined for document [" + this + "]!");
-            }
-            ServiceSelector selector = null;
-            try {
-                selector = (ServiceSelector) this.manager.lookup(ResourceType.ROLE + "Selector");
-                this.resourceType = (ResourceType) selector.select(name);
-            } catch (Exception e) {
-                throw new DocumentException(e);
-            }
-        }
-        return this.resourceType;
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DefaultDocumentBuilder.java b/src/java/org/apache/lenya/cms/publication/DefaultDocumentBuilder.java
deleted file mode 100644
index 8d98b81..0000000
--- a/src/java/org/apache/lenya/cms/publication/DefaultDocumentBuilder.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.thread.ThreadSafe;
-
-/**
- * Default document builder implementation.
- * 
- * @version $Id$
- */
-public class DefaultDocumentBuilder extends AbstractLogEnabled implements DocumentBuilder,
-        Serviceable, ThreadSafe {
-
-    /**
-     * Ctor.
-     */
-    public DefaultDocumentBuilder() {
-    }
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager manager) {
-        this.manager = manager;
-    }
-
-    protected ServiceManager manager;
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentBuilder#buildDocument(org.apache.lenya.cms.publication.DocumentIdentityMap,
-     *      org.apache.lenya.cms.publication.DocumentIdentifier)
-     */
-    public Document buildDocument(DocumentIdentityMap map, DocumentIdentifier identifier)
-            throws DocumentBuildException {
-
-        DefaultDocument document = createDocument(map, identifier);
-        ContainerUtil.enableLogging(document, getLogger());
-        /*
-         * document.setExtension(extension); document.setDocumentURL(originalURL);
-         */
-        return document;
-    }
-
-    /**
-     * Creates a new document object. Override this method to create specific document objects,
-     * e.g., for different document IDs.
-     * @param map The identity map.
-     * @param identifier The identifier.
-     * @return A document.
-     * @throws DocumentBuildException when something went wrong.
-     */
-    protected DefaultDocument createDocument(DocumentIdentityMap map, DocumentIdentifier identifier)
-            throws DocumentBuildException {
-        DefaultDocument document = new DefaultDocument(this.manager, map, identifier, getLogger());
-        document.setDocumentURL(buildCanonicalDocumentUrl(identifier));
-        return document;
-    }
-
-    /**
-     * Removes all "."-separated extensions from a URL (e.g., <code>/foo.print.html</code> is
-     * transformed to <code>/foo</code>).
-     * @param url The URL to trim.
-     * @return A URL string.
-     */
-    protected String removeExtensions(String url) {
-        int dotIndex = url.indexOf(".");
-        if (dotIndex > -1) {
-            url = url.substring(0, dotIndex);
-        }
-        return url;
-    }
-
-    /**
-     * Returns the language of a URL.
-     * @param urlWithoutSuffix The URL without the suffix.
-     * @return A string.
-     */
-    protected String getLanguage(String urlWithoutSuffix) {
-
-        String language = "";
-        String url = urlWithoutSuffix;
-
-        int languageSeparatorIndex = url.lastIndexOf("_");
-        if (languageSeparatorIndex > -1) {
-            String suffix = url.substring(languageSeparatorIndex + 1);
-            if (suffix.length() <= 5) {
-                language = suffix;
-            }
-        }
-        return language;
-    }
-
-    /**
-     * Returns the extension of a URL.
-     * @param url The URL.
-     * @return The extension.
-     */
-    protected String getExtension(String url) {
-        int startOfSuffix = url.lastIndexOf('.');
-        String suffix = "";
-
-        if ((startOfSuffix > -1) && !url.endsWith(".")) {
-            suffix = url.substring(startOfSuffix + 1);
-        }
-
-        return suffix;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentBuilder#isDocument(java.lang.String)
-     */
-    public boolean isDocument(String url) throws DocumentBuildException {
-        boolean isDocument = false;
-
-        URLInformation info = new URLInformation(url);
-        String area = info.getArea();
-        if (area != null && PublicationImpl.isValidArea(area)
-                && !area.equals(Publication.ADMIN_AREA)) {
-            String documentUrl = info.getDocumentUrl();
-            if (documentUrl != null && documentUrl.startsWith("/") && documentUrl.length() > 1) {
-                isDocument = true;
-            }
-        }
-
-        return isDocument;
-    }
-
-    /**
-     * Builds the canonical document URL.
-     * @param identifier The identifier.
-     * @return A string.
-     */
-    protected String buildCanonicalDocumentUrl(DocumentIdentifier identifier) {
-
-        String languageSuffix = "";
-        String language = identifier.getLanguage();
-        if (!language.equals(identifier.getPublication().getDefaultLanguage())) {
-            languageSuffix = "_" + language;
-        }
-
-        String url = identifier.getId() + languageSuffix + ".html";
-        return url;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentBuilder#buildCanonicalUrl(org.apache.lenya.cms.publication.DocumentIdentifier)
-     */
-    public String buildCanonicalUrl(DocumentIdentifier identifier) {
-
-        String documentUrl = buildCanonicalDocumentUrl(identifier);
-        String url = "/" + identifier.getPublication().getId() + "/" + identifier.getArea()
-                + documentUrl;
-
-        return url;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentBuilder#getIdentitfier(java.lang.String)
-     */
-    public DocumentIdentifier getIdentitfier(String webappUrl) throws DocumentBuildException {
-
-        if (!isDocument(webappUrl)) {
-            throw new DocumentBuildException("The webapp URL [" + webappUrl
-                    + "] does not refer to a document!");
-        }
-
-        URLInformation info = new URLInformation(webappUrl);
-
-        Publication publication;
-        try {
-            publication = PublicationUtil.getPublicationFromUrl(this.manager, webappUrl);
-        } catch (PublicationException e) {
-            throw new DocumentBuildException(e);
-        }
-
-        String documentURL = info.getDocumentUrl();
-        String originalURL = documentURL;
-
-        String extension = getExtension(documentURL);
-        documentURL = removeExtensions(documentURL);
-
-        String language = getLanguage(documentURL);
-        String fullLanguage = "".equals(language) ? "" : ("_" + language);
-        documentURL = documentURL.substring(0, documentURL.length() - fullLanguage.length());
-
-        if ("".equals(language)) {
-            language = publication.getDefaultLanguage();
-        }
-
-        String documentId = documentURL;
-
-        if (!documentId.startsWith("/")) {
-            throw new DocumentBuildException("Document ID [" + documentId
-                    + "] does not start with '/'!");
-        }
-
-        DocumentIdentifier identifier = new DocumentIdentifier(publication,
-                info.getArea(),
-                documentId,
-                language);
-        return identifier;
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DefaultDocumentIdToPathMapper.java b/src/java/org/apache/lenya/cms/publication/DefaultDocumentIdToPathMapper.java
deleted file mode 100644
index c405118..0000000
--- a/src/java/org/apache/lenya/cms/publication/DefaultDocumentIdToPathMapper.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.io.File;
-
-/**
- * Default DocumentIdToPathMapper implementation.
- * 
- * @version $Id$
- */
-public class DefaultDocumentIdToPathMapper
-    implements DocumentIdToPathMapper, PathToDocumentIdMapper {
-    	
-    /**
-     * The file name.
-     */
-    public static final String BASE_FILENAME_PREFIX = "index";
-    
-    /**
-     * The file extension.
-     */
-    public static final String BASE_FILENAME_SUFFIX = ".xml";
-
-    /**
-	 * @see org.apache.lenya.cms.publication.DocumentIdToPathMapper#getFile(org.apache.lenya.cms.publication.Publication,
-	 *      java.lang.String, java.lang.String, java.lang.String)
-	 */
-    public File getFile(Publication publication, String area, String documentId, String language) {
-        File file = new File(getDirectory(publication, area, documentId), getFilename(language));
-        return file;
-    }
-
-    /**
-	 * (non-Javadoc)
-	 * 
-	 * @see org.apache.lenya.cms.publication.DocumentIdToPathMapper#getDirectory(org.apache.lenya.cms.publication.Publication,
-	 *      java.lang.String, java.lang.String)
-	 */
-    public File getDirectory(Publication publication, String area, String documentId) {
-        assert documentId.startsWith("/");
-        // remove leading slash
-        documentId = documentId.substring(1);
-        documentId = documentId.replace('/', File.separatorChar);
-
-        File file =
-            new File(
-                publication.getDirectory(),
-                Publication.CONTENT_PATH + File.separator + area + File.separator + documentId);
-
-        return file;
-    }
-
-    /**
-	 * @see org.apache.lenya.cms.publication.DocumentIdToPathMapper#getPath(java.lang.String,
-	 *      java.lang.String)
-	 */
-    public String getPath(String documentId, String language) {
-        assert documentId.startsWith("/");
-        // remove leading slash
-        documentId = documentId.substring(1);
-        return documentId + "/" + getFilename(language);
-    }
-
-    /**
-	 * Constructs the filename for a given language.
-	 * 
-	 * @param language The language.
-	 * @return A string value.
-	 */
-    protected String getFilename(String language) {
-        String languageSuffix = "";
-        if (language != null && !"".equals(language)) {
-            languageSuffix = "_" + language;
-        }
-        return BASE_FILENAME_PREFIX + languageSuffix + BASE_FILENAME_SUFFIX;
-    }
-
-    /**
-     * Returns the document ID for a certain file.
-     * @param publication The publication.
-     * @param area The area.
-     * @param file The file representing the document.
-     * @return A string.
-     * @throws DocumentDoesNotExistException when the document
-     * referenced by the file does not exist.
-     */
-    public String getDocumentId(
-        Publication publication,
-        String area,
-        File file)
-        throws DocumentDoesNotExistException {
-
-        String fileName = file.getAbsolutePath();
-        String contentDirName =
-            publication.getContentDirectory(area).getAbsolutePath();
-        if (fileName.startsWith(contentDirName)) {
-            // trim everything up to the documentId
-            String relativeFileName =
-                fileName.substring(contentDirName.length());
-            // trim everything after the documentId
-            relativeFileName =
-                relativeFileName.substring(
-                    0,
-                    relativeFileName.lastIndexOf(File.separator));
-            // and replace the os specific separator by '/'
-            return relativeFileName.replace(File.separatorChar, '/');
-        }
-        // Document does not seem to exist
-        throw new DocumentDoesNotExistException(
-            "No document associated with file" + fileName);
-    }
-    
-    /**
-     * Returns the language for a certain file
-     * 
-     * @param file the document file
-     * 
-     * @return the language for the given document file or null if
-     * the file has no language.
-     */
-    public String getLanguage(File file) {
-        String fileName = file.getName();
-        String language = null;
-
-        // check if the file is of the form index.html or index_en.html
-
-        if (fileName.startsWith(BASE_FILENAME_PREFIX)
-            && fileName.endsWith(BASE_FILENAME_SUFFIX)) {
-            String languageSuffix =
-                fileName.substring(
-                    BASE_FILENAME_PREFIX.length(),
-                    fileName.indexOf(BASE_FILENAME_SUFFIX));
-            if (languageSuffix.length() > 0) {
-                // trim the leading '_'
-                language = languageSuffix.substring(1);
-            }
-        }
-        return language;
-    }
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java b/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java
deleted file mode 100644
index e6713ed..0000000
--- a/src/java/org/apache/lenya/cms/publication/DefaultResourcesManager.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Locale;
-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.cocoon.servlet.multipart.Part;
-import org.apache.excalibur.source.ModifiableSource;
-import org.apache.excalibur.source.Source;
-import org.apache.excalibur.source.SourceResolver;
-import org.apache.lenya.cms.cocoon.source.SourceUtil;
-import org.apache.lenya.cms.metadata.LenyaMetaData;
-import org.apache.lenya.cms.repository.Node;
-
-/**
- * Manager for resources of a CMS document.
- * @version $Id$
- */
-public class DefaultResourcesManager extends AbstractLogEnabled implements ResourcesManager,
-        Serviceable {
-
-    private static final class MetaSuffixFileFilter implements FileFilter {
-        /**
-         * @see java.io.FileFilter#accept(java.io.File)
-         */
-        public boolean accept(File file) {
-            return file.isFile() && file.getName().endsWith(RESOURCES_META_SUFFIX);
-        }
-    }
-
-    private static final class NotMetaSuffixFileFilter implements FileFilter {
-        /**
-         * @see java.io.FileFilter#accept(java.io.File)
-         */
-        public boolean accept(File file) {
-            return file.isFile() && !file.getName().endsWith(RESOURCES_META_SUFFIX);
-        }
-    }
-
-    private static final class ImageExtensionsFileFilter implements FileFilter {
-        /**
-         * @see java.io.FileFilter#accept(java.io.File)
-         */
-        public boolean accept(File file) {
-            for (int i = 0; i < IMAGE_FILE_EXTENSIONS.length; i++)
-                if (file.getName().toLowerCase(Locale.ENGLISH).endsWith(IMAGE_FILE_EXTENSIONS[i]))
-                    return true;
-            return false;
-        }
-    }
-
-    private static final class ResourceMetaFileFilter implements FileFilter {
-        private final File resource;
-
-        private ResourceMetaFileFilter(File _resource) {
-            super();
-            this.resource = _resource;
-        }
-
-        /**
-         * @see java.io.FileFilter#accept(java.io.File)
-         */
-        public boolean accept(File file) {
-            return file.isFile()
-                    && file.getName().equals(this.resource.getName().concat(RESOURCES_META_SUFFIX));
-        }
-    }
-
-    /**
-     * Constructor
-     */
-    public DefaultResourcesManager() {
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#addResource(org.apache.lenya.cms.publication.Document,
-     *      org.apache.cocoon.servlet.multipart.Part, java.util.Map)
-     */
-    public void addResource(Document document, Part part, Map metadata) throws Exception {
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DefaultResourcesManager::addResource() called");
-
-        try {
-            String fileName = part.getFileName();
-            if (!fileName.matches(FILE_NAME_REGEXP)) {
-                // the file name contains characters which mean trouble
-                // and are therefore not allowed.
-                getLogger().warn("The filename [" + fileName + "]� is not valid for an asset.");
-            }
-            // convert spaces in the file name to underscores
-            fileName = fileName.replace(' ', '_');
-
-            Resource resource = new Resource(document, fileName, this.manager, getLogger());
-            Node[] nodes = resource.getRepositoryNodes();
-            for (int i = 0; i < nodes.length; i++) {
-                nodes[i].lock();
-            }
-
-            String mimeType = part.getMimeType();
-            int fileSize = part.getSize();
-
-            /*
-             * complement and create the meta description for the resource.
-             */
-            metadata.put("format", mimeType);
-            metadata.put("extent", Integer.toString(fileSize));
-            Map lenyaMetaData = new HashMap(1);
-            lenyaMetaData.put(LenyaMetaData.ELEMENT_CONTENT_TYPE, "asset");
-            resource.getMetaDataManager().setMetaData(metadata, lenyaMetaData, null);
-
-            saveResource(resource, part);
-        } catch (final DocumentException e) {
-            getLogger().error("Document exception " + e.toString());
-            throw new RuntimeException(e);
-        } catch (final IOException e) {
-            getLogger().error("IO Error " + e.toString());
-            throw e;
-        }
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DefaultResourcesManager::addResource() done.");
-    }
-
-    /**
-     * Saves the resource to a file.
-     * @param resource The resource.
-     * @param part The part of the multipart request.
-     * @throws IOException if an error occurs.
-     */
-    protected void saveResource(Resource resource, Part part) throws IOException {
-        OutputStream out = null;
-        InputStream in = null;
-
-        SourceResolver resolver = null;
-        ModifiableSource source = null;
-
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = (ModifiableSource) resolver.resolveURI(resource.getSourceURI());
-
-            byte[] buf = new byte[4096];
-            out = source.getOutputStream();
-            in = part.getInputStream();
-            int read = in.read(buf);
-
-            while (read > 0) {
-                out.write(buf, 0, read);
-                read = in.read(buf);
-            }
-        } catch (final FileNotFoundException e) {
-            getLogger().error("file not found" + e.toString());
-            throw new IOException(e.toString());
-        } catch (IOException e) {
-            getLogger().error("IO error " + e.toString());
-            throw new IOException(e.toString());
-        } catch (Exception e) {
-            getLogger().error("Exception" + e.toString());
-            throw new IOException(e.toString());
-        } finally {
-            if (in != null) {
-                in.close();
-            }
-            if (out != null) {
-                out.flush();
-                out.close();
-            }
-
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#getResources(org.apache.lenya.cms.publication.Document)
-     */
-    public Resource[] getResources(Document document) {
-
-        // filter the meta files out. We only want to see the "real" resources.
-        FileFilter filter = new NotMetaSuffixFileFilter();
-
-        return getResources(document, filter);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#getImageResources(org.apache.lenya.cms.publication.Document)
-     */
-    public Resource[] getImageResources(Document document) {
-        return getResources(document, new ImageExtensionsFileFilter());
-    }
-
-    /**
-     * Returns the resources that are matched by a certain file filter.
-     * @param document The document.
-     * @param filter A file filter.
-     * @return A resource array.
-     */
-    protected Resource[] getResources(Document document, FileFilter filter) {
-        File[] files = new File[0];
-        Resource tempResource = new Resource(document, "temp", this.manager, getLogger());
-
-        SourceResolver resolver = null;
-        Source source = null;
-        try {
-            Resource[] resources;
-
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = resolver.resolveURI(tempResource.getBaseURI());
-            if (source.exists()) {
-                File directory = org.apache.excalibur.source.SourceUtil.getFile(source);
-                if (directory.isDirectory()) {
-                    files = directory.listFiles(filter);
-                }
-                resources = new Resource[files.length];
-                for (int i = 0; i < files.length; i++) {
-                    resources[i] = new Resource(document, files[i].getName(), this.manager,
-                            getLogger());
-                }
-            } else {
-                resources = new Resource[0];
-            }
-            return resources;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#deleteResources(org.apache.lenya.cms.publication.Document)
-     */
-    public void deleteResources(Document document) {
-
-        try {
-            Resource[] resources = getResources(document);
-            for (int i = 0; i < resources.length; i++) {
-                SourceUtil.delete(resources[i].getSourceURI(), this.manager);
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#copyResources(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void copyResources(Document sourceDocument, Document destinationDocument)
-            throws Exception {
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug(
-                    "Copying resources from [" + sourceDocument + "] to [" + destinationDocument
-                            + "]");
-        }
-
-        SourceResolver resolver = null;
-        try {
-            Resource[] resources = getResources(sourceDocument);
-            for (int i = 0; i < resources.length; i++) {
-                Resource sourceResource = resources[i];
-                Resource destinationResource = new Resource(destinationDocument, sourceResource
-                        .getName(), this.manager, getLogger());
-
-                Source sourceSource = null;
-                ModifiableSource destSource = null;
-                ModifiableSource destMetaSource = null;
-
-                try {
-                    resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-                    sourceSource = resolver.resolveURI(sourceResource.getSourceURI());
-                    destSource = (ModifiableSource) resolver.resolveURI(destinationResource
-                            .getSourceURI());
-
-                    SourceUtil.copy(sourceSource, destSource, true);
-                } finally {
-                    if (sourceSource != null) {
-                        resolver.release(sourceSource);
-                    }
-                    if (destSource != null) {
-                        resolver.release(destSource);
-                    }
-                    if (destMetaSource != null) {
-                        resolver.release(destMetaSource);
-                    }
-                }
-            }
-        } finally {
-            if (resolver != null) {
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    protected ServiceManager manager;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#getResource(org.apache.lenya.cms.publication.Document,
-     *      java.lang.String)
-     */
-    public Resource getResource(Document document, String resourceName) {
-        Resource theResource = null;
-        Resource[] resources = getResources(document);
-        for (int i = 0; i < resources.length; i++) {
-            if (resources[i].getName().equals(resourceName)) {
-                theResource = resources[i];
-                break;
-            }
-        }
-        return theResource;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#deleteResource(org.apache.lenya.cms.publication.Resource)
-     */
-    public void deleteResource(Resource theResource) throws Exception {
-
-        SourceUtil.delete(theResource.getSourceURI(), this.manager);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.ResourcesManager#deleteResource(org.apache.lenya.cms.publication.Document,
-     *      java.lang.String)
-     */
-    public void deleteResource(Document document, String name) throws Exception {
-        Resource theResource = getResource(document, name);
-        if (theResource == null)
-            throw new Exception("no such resource [" + name + "] exists for document [ "
-                    + document.getId() + "]");
-
-        deleteResource(theResource);
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/Document.java b/src/java/org/apache/lenya/cms/publication/Document.java
deleted file mode 100644
index c5ec581..0000000
--- a/src/java/org/apache/lenya/cms/publication/Document.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.io.File;
-import java.util.Date;
-
-import org.apache.lenya.cms.metadata.MetaDataOwner;
-import org.apache.lenya.cms.publication.util.DocumentVisitor;
-import org.apache.lenya.cms.repository.Node;
-import org.apache.lenya.transaction.Identifiable;
-
-/**
- * A CMS document.
- * @version $Id$
- */
-public interface Document extends MetaDataOwner, Identifiable {
-    
-    /**
-     * The document namespace URI.
-     */
-    String NAMESPACE = "http://apache.org/cocoon/lenya/document/1.0";
-    
-    /**
-     * The default namespace prefix.
-     */
-    String DEFAULT_PREFIX = "lenya";
-    
-    /**
-     * The transactionable type for document objects.
-     */
-    String TRANSACTIONABLE_TYPE = "document";
-    
-    /**
-     * <code>DOCUMENT_META_SUFFIX</code> The suffix for document meta Uris
-     */
-    final String DOCUMENT_META_SUFFIX = ".meta";
-
-    /**
-     * Returns the document ID of this document.
-     * @return the document-id of this document.
-     */
-    String getId();
-    
-    /**
-     * Returns the document name of this document.
-     * @return the document-name of this document.
-     */
-    String getName();
-    
-    /**
-     * Returns the publication this document belongs to.
-     * @return A publication object.
-     */
-    Publication getPublication();
-    
-    /**
-     * Returns the canonical web application URL.
-     * @return A string.
-     */
-    String getCanonicalWebappURL();
-
-    /**
-     * Returns the canonical document URL.
-     * @return A string.
-     */
-    String getCanonicalDocumentURL();
-
-    /**
-     * Returns the language of this document.
-     * Each document has one language associated to it. 
-     * @return A string denoting the language.
-     */
-    String getLanguage();
-
-    /**
-     * Returns all the languages this document is available in.
-     * A document has one associated language (@see Document#getLanguage)
-     * but there are possibly a number of other languages for which a 
-     * document with the same document-id is also available in. 
-     * 
-     * @return An array of strings denoting the languages.
-     * 
-     * @throws DocumentException if an error occurs
-     */
-    String[] getLanguages() throws DocumentException;
-
-    /**
-     * Get the navigation label associated with this document 
-     * for the language.
-     * 
-     * @return the label String
-     * 
-     * @throws DocumentException if an error occurs
-     */
-    String getLabel() throws DocumentException;
-
-    /**
-     * Returns the date of the last modification of this document.
-     * @return A date denoting the date of the last modification.
-     */
-    Date getLastModified();
-
-    /**
-     * Returns the area this document belongs to.
-     * @return The area.
-     */
-    String getArea();
-
-    /**
-     * Returns the file for this document.
-     * @return A file object.
-     */
-    File getFile();
-
-    /**
-     * Returns the extension in the URL.
-     * @return A string.
-     */
-    String getExtension();
-    
-    /**
-     * Check if a document with the given document-id, language and in the given
-     * area actually exists.
-     * 
-     * @return true if the document exists, false otherwise
-     * 
-     * @throws DocumentException if an error occurs
-     */
-    boolean exists() throws DocumentException;
-    
-    /**
-     * Check if a document exists with the given document-id and the given area
-     * independently of the given language.
-     * 
-     * @return true if a document with the given document-id and area exists,
-     * null otherwise
-     * 
-     * @throws DocumentException if an error occurs
-     */
-    boolean existsInAnyLanguage() throws DocumentException;
-    
-    /**
-     * Returns the identity map this document belongs to.
-     * @return A document identity map.
-     */
-    DocumentIdentityMap getIdentityMap();
-    
-    /**
-     * Returns the URI to resolve the document's source.
-     * @return A string.
-     */
-    String getSourceURI();
-    
-    /**
-     * Setter for the URI to resolve the document's source.
-     * @param uri URI
-     */
-    void setSourceURI(String uri);
-    
-    /**
-     * Accepts a document visitor.
-     * @param visitor The visitor.
-     * @throws PublicationException if an error occurs.
-     */
-    void accept(DocumentVisitor visitor) throws PublicationException;
-
-    /**
-     * Deletes the document.
-     * @throws DocumentException if an error occurs.
-     */
-    void delete() throws DocumentException;
-    
-    /**
-     * @return The repository node that represents this document.
-     */
-    Node getRepositoryNode();
-
-    /**
-     * @return The resource type of this document (formerly known as doctype)
-     * @throws DocumentException if an error occurs.
-     */
-    ResourceType getResourceType() throws DocumentException;
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentBuildException.java b/src/java/org/apache/lenya/cms/publication/DocumentBuildException.java
deleted file mode 100644
index 79dadc7..0000000
--- a/src/java/org/apache/lenya/cms/publication/DocumentBuildException.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-/**
- * Document build exception.
- *
- * @version $Id$
- */
-public class DocumentBuildException extends PublicationException {
-    /**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/**
-     * Constructor.
-     */
-    public DocumentBuildException() {
-        super();
-    }
-
-    /**
-     * Constructor.
-     * @param message A message.
-     */
-    public DocumentBuildException(String message) {
-        super(message);
-    }
-
-    /**
-     * Constructor.
-     * @param cause The cause of the exception.
-     */
-    public DocumentBuildException(Throwable cause) {
-        super(cause);
-    }
-
-    /**
-     * Constructor.
-     * @param message A message.
-     * @param cause The cause of the exception.
-     */
-    public DocumentBuildException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentBuilder.java b/src/java/org/apache/lenya/cms/publication/DocumentBuilder.java
deleted file mode 100644
index 392260e..0000000
--- a/src/java/org/apache/lenya/cms/publication/DocumentBuilder.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-/**
- * A document builder builds a document from a URL.
- */
-public interface DocumentBuilder {
-
-    /**
-     * The Avalon role.
-     */
-    String ROLE = DocumentBuilder.class.getName();
-    
-    DocumentIdentifier getIdentitfier(String webappUrl) throws DocumentBuildException;
-
-    /**
-     * Builds a document.
-     * @param map The identity map the document belongs to.
-     * @param publication The publication.
-     * @param url The URL of the form
-     *            /{publication-id}/{area}/{document-id}{language-suffix}.{extension}.
-     * @return A document.
-     * @throws DocumentBuildException when something went wrong.
-     */
-    Document buildDocument(DocumentIdentityMap map, DocumentIdentifier identifier)
-            throws DocumentBuildException;
-
-    /**
-     * Checks if an URL corresponds to a CMS document.
-     * @param publication The publication the document belongs to.
-     * @param url The URL of the form /{publication-id}/...
-     * @return A boolean value.
-     * @throws DocumentBuildException when something went wrong.
-     */
-    boolean isDocument(String url) throws DocumentBuildException;
-
-    /**
-     * Builds an URL corresponding to a cms document from the publication, the area, the document id
-     * and the language
-     * @param publication The publication the document belongs to.
-     * @param area The area the document belongs to.
-     * @param documentid The document id of the document.
-     * @param language The language of the document.
-     * @return a String The builded url
-     */
-    String buildCanonicalUrl(DocumentIdentifier identifier);
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentIdToPathMapper.java b/src/java/org/apache/lenya/cms/publication/DocumentIdToPathMapper.java
deleted file mode 100644
index 33ab906..0000000
--- a/src/java/org/apache/lenya/cms/publication/DocumentIdToPathMapper.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-
-/**
- * Document Id to Path mapper interface
- */
-public interface DocumentIdToPathMapper {
-    
-    /**
-     * Compute the document-path for a given publication, area
-     * and document-id. The file separator is the slash (/).
-     *
-     * @param documentId the document-id of the document
-     * @param language the language of the document
-     * 
-     * @return the path to the document, without publication ID and area
-     */
-    String getPath(String documentId, String language);
-
-    /**
-     * Compute the document-path for a given publication, area, 
-     * document-id and language
-     *
-     * @param publication the publication of the document
-     * @param area the area of the document
-     * @param documentId the document-id of the document
-     * @param language the language of the document
-     * 
-     * @return the path to the document
-     */
-    File getFile(Publication publication, String area, String documentId,
-        String language);
-
-    /**
-     * Compute the document-path for a given publication, area and 
-     * document-id. As there are possibly multiple files for the same 
-     * document-id (for different languages) the return value is a directory.
-     *  
-     * @param publication The publication.
-     * @param area The area.
-     * @param documentId The document id.
-     * 
-     * @return The directory where all the files with the same 
-     * document-id are located
-     */
-    File getDirectory(Publication publication, String area, String documentId);
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentIdentifier.java b/src/java/org/apache/lenya/cms/publication/DocumentIdentifier.java
index 209332a..96b2adb 100644
--- a/src/java/org/apache/lenya/cms/publication/DocumentIdentifier.java
+++ b/src/java/org/apache/lenya/cms/publication/DocumentIdentifier.java
@@ -21,20 +21,20 @@
  */
 public class DocumentIdentifier {
 
-    private Publication publication;
+    private String publicationId;
     private String area;
     private String id;
     private String language;
     
     /**
      * Ctor.
-     * @param publication The publication.
+     * @param publicationId The publication ID.
      * @param area The area.
-     * @param id The document ID.
+     * @param id The node ID.
      * @param language The language.
      */
-    public DocumentIdentifier(Publication publication, String area, String id, String language) {
-        this.publication = publication;
+    public DocumentIdentifier(String publicationId, String area, String id, String language) {
+        this.publicationId = publicationId;
         this.area = area;
         this.id = id;
         this.language = language;
@@ -48,9 +48,9 @@
     }
 
     /**
-     * @return The document ID.
+     * @return The node ID.
      */
-    public String getId() {
+    public String getNodeId() {
         return id;
     }
 
@@ -64,8 +64,8 @@
     /**
      * @return The publication.
      */
-    public Publication getPublication() {
-        return publication;
+    public String getPublicationId() {
+        return publicationId;
     }
     
     public boolean equals(Object obj) {
@@ -77,6 +77,6 @@
     }
     
     protected String getKey() {
-        return this.publication.getId() + ":" + this.area + ":" + this.id + ":" + this.language;
+        return this.publicationId + ":" + this.area + ":" + this.id + ":" + this.language;
     }
 }
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentIdentityMap.java b/src/java/org/apache/lenya/cms/publication/DocumentIdentityMap.java
deleted file mode 100644
index 3981d9d..0000000
--- a/src/java/org/apache/lenya/cms/publication/DocumentIdentityMap.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.ServiceSelector;
-import org.apache.lenya.cms.repository.Session;
-import org.apache.lenya.transaction.Identifiable;
-import org.apache.lenya.transaction.IdentifiableFactory;
-import org.apache.lenya.transaction.IdentityMap;
-
-/**
- * A DocumentIdentityMap avoids the multiple instanciation of a document object.
- * 
- * @version $Id$
- */
-public class DocumentIdentityMap extends AbstractLogEnabled implements IdentifiableFactory {
-
-    private IdentityMap map;
-    protected ServiceManager manager;
-
-    /**
-     * @return The identity map.
-     */
-    public IdentityMap getIdentityMap() {
-        return this.map;
-    }
-
-    /**
-     * Ctor.
-     * @param session The session to use.
-     * @param manager The service manager.
-     * @param logger The logger to use.
-     */
-    public DocumentIdentityMap(Session session, ServiceManager manager, Logger logger) {
-        this.map = session.getUnitOfWork().getIdentityMap();
-        this.manager = manager;
-        ContainerUtil.enableLogging(this, logger);
-    }
-
-    /**
-     * Ctor.
-     * @param map The identity map to use.
-     * @param manager The service manager.
-     * @param logger The logger to use.
-     */
-    public DocumentIdentityMap(IdentityMap map, ServiceManager manager, Logger logger) {
-        this.map = map;
-        this.manager = manager;
-        ContainerUtil.enableLogging(this, logger);
-    }
-
-    /**
-     * Returns a document.
-     * @param publication The publication.
-     * @param area The area.
-     * @param documentId The document ID.
-     * @param language The language.
-     * @return A document.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document get(Publication publication, String area, String documentId, String language)
-            throws DocumentBuildException {
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DocumentIdentityMap::get() called on publication ["
-                    + publication.getId() + "], area [" + area + "], documentId [" + documentId
-                    + "], language [" + language + "]");
-
-        String key = getKey(publication, area, documentId, language);
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DocumentIdentityMap::get() got key [" + key
-                    + "] from DocumentFactory");
-
-        return (Document) getIdentityMap().get(this, key);
-    }
-
-    /**
-     * Returns the document identified by a certain web application URL.
-     * @param webappUrl The web application URL.
-     * @return A document.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document getFromURL(String webappUrl) throws DocumentBuildException {
-        String key = getKey(webappUrl);
-        return (Document) getIdentityMap().get(this, key);
-    }
-
-    /**
-     * Builds a clone of a document for another language.
-     * @param document The document to clone.
-     * @param language The language of the target document.
-     * @return A document.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document getLanguageVersion(Document document, String language)
-            throws DocumentBuildException {
-        return get(document.getPublication(), document.getArea(), document.getId(), language);
-    }
-
-    /**
-     * Builds a clone of a document for another area.
-     * @param document The document to clone.
-     * @param area The area of the target document.
-     * @return A document.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document getAreaVersion(Document document, String area) throws DocumentBuildException {
-        return get(document.getPublication(), area, document.getId(), document.getLanguage());
-    }
-
-    /**
-     * Returns the parent of a document.
-     * @param document A document.
-     * @return A document or <code>null</code> if the document has no parent.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document getParent(Document document) throws DocumentBuildException {
-        Document parent = null;
-        int lastSlashIndex = document.getId().lastIndexOf("/");
-        if (lastSlashIndex > 0) {
-            String parentId = document.getId().substring(0, lastSlashIndex);
-            parent = get(document.getPublication(),
-                    document.getArea(),
-                    parentId,
-                    document.getLanguage());
-        }
-        return parent;
-    }
-
-    /**
-     * Returns the parent of a document.
-     * @param document A document.
-     * @param defaultDocumentId The document ID to use if the document has no parent.
-     * @return A document.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document getParent(Document document, String defaultDocumentId)
-            throws DocumentBuildException {
-        Document parent = getParent(document);
-        if (parent == null) {
-            parent = get(document.getPublication(),
-                    document.getArea(),
-                    defaultDocumentId,
-                    document.getLanguage());
-        }
-        return parent;
-    }
-
-    /**
-     * Builds a document for the default language.
-     * @param publication The publication.
-     * @param area The area.
-     * @param documentId The document ID.
-     * @return A document.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public Document get(Publication publication, String area, String documentId)
-            throws DocumentBuildException {
-        return get(publication, area, documentId, publication.getDefaultLanguage());
-    }
-
-    /**
-     * Checks if a string represents a valid document ID.
-     * @param id The string.
-     * @return A boolean value.
-     */
-    public boolean isValidDocumentId(String id) {
-
-        if (!id.startsWith("/")) {
-            return false;
-        }
-
-        String[] snippets = id.split("/");
-
-        if (snippets.length < 2) {
-            return false;
-        }
-
-        for (int i = 1; i < snippets.length; i++) {
-            if (!snippets[i].matches("[a-zA-Z0-9\\-]+")) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Checks if a webapp URL represents a document.
-     * @param webappUrl A web application URL.
-     * @return A boolean value.
-     * @throws DocumentBuildException if an error occurs.
-     */
-    public boolean isDocument(String webappUrl) throws DocumentBuildException {
-
-        try {
-            Publication publication = PublicationUtil.getPublicationFromUrl(this.manager, webappUrl);
-            if (publication.exists()) {
-
-                ServiceSelector selector = null;
-                DocumentBuilder builder = null;
-                try {
-                    selector = (ServiceSelector) this.manager.lookup(DocumentBuilder.ROLE
-                            + "Selector");
-                    builder = (DocumentBuilder) selector.select(publication.getDocumentBuilderHint());
-                    return builder.isDocument(webappUrl);
-                } finally {
-                    if (selector != null) {
-                        if (builder != null) {
-                            selector.release(builder);
-                        }
-                        this.manager.release(selector);
-                    }
-                }
-            } else {
-                return false;
-            }
-        } catch (ServiceException e) {
-            throw new DocumentBuildException(e);
-        } catch (PublicationException e) {
-            throw new DocumentBuildException(e);
-        }
-    }
-
-    /**
-     * Builds a document key.
-     * @param publication The publication.
-     * @param area The area.
-     * @param documentId The document ID.
-     * @param language The language.
-     * @return A key.
-     */
-    public String getKey(Publication publication, String area, String documentId, String language) {
-        return publication.getId() + ":" + area + ":" + documentId + ":" + language;
-    }
-
-    /**
-     * Builds a document key.
-     * @param webappUrl The web application URL.
-     * @return A key.
-     */
-    public String getKey(String webappUrl) {
-        ServiceSelector selector = null;
-        DocumentBuilder builder = null;
-        DocumentIdentifier identifier;
-        try {
-            Publication publication = PublicationUtil.getPublicationFromUrl(this.manager, webappUrl);
-            selector = (ServiceSelector) this.manager.lookup(DocumentBuilder.ROLE + "Selector");
-            builder = (DocumentBuilder) selector.select(publication.getDocumentBuilderHint());
-            identifier = builder.getIdentitfier(webappUrl);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (selector != null) {
-                if (builder != null) {
-                    selector.release(builder);
-                }
-                this.manager.release(selector);
-            }
-        }
-        return getKey(identifier.getPublication(),
-                identifier.getArea(),
-                identifier.getId(),
-                identifier.getLanguage());
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.IdentifiableFactory#build(org.apache.lenya.transaction.IdentityMap,
-     *      java.lang.String)
-     */
-    public Identifiable build(IdentityMap map, String key) throws Exception {
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DocumentFactory::build() called with key [" + key + "]");
-
-        String[] snippets = key.split(":");
-        String publicationId = snippets[0];
-        String area = snippets[1];
-        String documentId = snippets[2];
-        String language = snippets[3];
-
-        ServiceSelector selector = null;
-        DocumentBuilder builder = null;
-        Document document;
-        try {
-
-            Publication publication = PublicationUtil.getPublication(this.manager, publicationId);
-
-            selector = (ServiceSelector) this.manager.lookup(DocumentBuilder.ROLE + "Selector");
-            builder = (DocumentBuilder) selector.select(publication.getDocumentBuilderHint());
-            DocumentIdentifier identifier = new DocumentIdentifier(publication,
-                    area,
-                    documentId,
-                    language);
-            document = builder.buildDocument(this, identifier);
-        } finally {
-            if (selector != null) {
-                if (builder != null) {
-                    selector.release(builder);
-                }
-                this.manager.release(selector);
-            }
-        }
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("DocumentFactory::build() done.");
-
-        return document;
-    }
-
-    /**
-     * *
-     * @see org.apache.lenya.transaction.IdentifiableFactory#getType()
-     */
-    public String getType() {
-        return Document.TRANSACTIONABLE_TYPE;
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentManager.java b/src/java/org/apache/lenya/cms/publication/DocumentManager.java
deleted file mode 100644
index 1eecf8f..0000000
--- a/src/java/org/apache/lenya/cms/publication/DocumentManager.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.util.Map;
-import org.apache.lenya.cms.publication.util.DocumentSet;
-
-/**
- * Helper to manage documents. It takes care of attachments etc.
- * 
- * @version $Id$
- */
-public interface DocumentManager {
-
-    /**
-     * The Avalon component role.
-     */
-    String ROLE = DocumentManager.class.getName();
-
-    /**
-     * Copies a document from one location to another location.
-     * @param sourceDocument The document to copy.
-     * @param destinationDocument The destination document.
-     * @throws PublicationException if a document which destinationDocument depends on does not
-     *             exist.
-     */
-    void copy(Document sourceDocument, Document destinationDocument) throws PublicationException;
-
-    /**
-     * Copies a document to another area.
-     * @param sourceDocument The document to copy.
-     * @param destinationArea The destination area.
-     * @throws PublicationException if a document which the destination document depends on does not
-     *             exist.
-     */
-    void copyToArea(Document sourceDocument, String destinationArea) throws PublicationException;
-
-    /**
-     * Copies a document set to another area.
-     * @param documentSet The document set to copy.
-     * @param destinationArea The destination area.
-     * @throws PublicationException if a document which one of the destination documents depends on
-     *             does not exist.
-     */
-    void copyToArea(DocumentSet documentSet, String destinationArea) throws PublicationException;
-
-    /**
-     * Creates a new document in the same publication the <code>parentDocument</code> belongs to
-     * with the given parameters:
-     * 
-     * @param document The document to add.
-     * @param resourceType the document type (aka resource type) of the new document
-     * @param navigationTitle navigation title
-     * @param visibleInNav determines the visibility of a node in the navigation
-     * @param parameters any parameters the caller needs to pass to the creator
-     * 
-     * @throws DocumentBuildException if the document can not be created
-     * @throws PublicationException if the document is already contained.
-     */
-    void add(Document document,
-            ResourceType resourceType,
-            String navigationTitle,
-            boolean visibleInNav,
-            Map parameters) throws DocumentBuildException, PublicationException;
-
-    /**
-     * Creates a new document in the same publication the <code>parentDocument</code> belongs to
-     * with the given parameters:
-     * 
-     * @param document The document to add.
-     * @param sourceDocument The document to initialize the contents and meta data from.
-     * @param navigationTitle navigation title
-     * @param visibleInNav determines the visibility of a node in the navigation
-     * @param parameters any parameters the caller needs to pass to the creator
-     * 
-     * @throws DocumentBuildException if the document can not be created
-     * @throws PublicationException if the document is already contained.
-     */
-    void add(Document document,
-            Document sourceDocument,
-            String navigationTitle,
-            boolean visibleInNav,
-            Map parameters) throws DocumentBuildException, PublicationException;
-
-    /**
-     * Deletes a document.
-     * @param document The document to delete.
-     * @throws PublicationException when something went wrong.
-     */
-    void delete(Document document) throws PublicationException;
-
-    /**
-     * Moves a document from one location to another.
-     * @param sourceDocument The source document.
-     * @param destinationDocument The destination document.
-     * @throws PublicationException if a document which the destination document depends on does not
-     *             exist.
-     */
-    void move(Document sourceDocument, Document destinationDocument) throws PublicationException;
-
-    /**
-     * Moves a document set from one location to another. A source is moved to the destination of
-     * the same position in the set.
-     * @param sources The source documents.
-     * @param destinations The destination documents.
-     * @throws PublicationException if a document which the destination document depends on does not
-     *             exist.
-     */
-    void move(DocumentSet sources, DocumentSet destinations) throws PublicationException;
-
-    /**
-     * Copies a document set from one location to another. A source is copied to the destination of
-     * the same position in the set.
-     * @param sources The source documents.
-     * @param destinations The destination documents.
-     * @throws PublicationException if a document which the destination document depends on does not
-     *             exist.
-     */
-    void copy(DocumentSet sources, DocumentSet destinations) throws PublicationException;
-    
-    /**
-     * Checks if a document name is valid.
-     * @param documentName The document name.
-     * @return A boolean value.
-     */
-    boolean isValidDocumentName(String documentName);
-
-    /**
-     * Moves a document to another location, incl. all requiring documents. If a sitetree is used,
-     * this means that the whole subtree is moved.
-     * @param source The source document.
-     * @param target The target document.
-     * @throws PublicationException if an error occurs.
-     */
-    void moveAll(Document source, Document target) throws PublicationException;
-
-    /**
-     * Moves all language versions of a document to another location.
-     * @param source The source.
-     * @param target The target.
-     * @throws PublicationException if the documents could not be moved.
-     */
-    void moveAllLanguageVersions(Document source, Document target) throws PublicationException;
-
-    /**
-     * Copies a document to another location, incl. all requiring documents. If a sitetree is used,
-     * this means that the whole subtree is copied.
-     * @param source The source document.
-     * @param target The target document.
-     * @throws PublicationException if an error occurs.
-     */
-    void copyAll(Document source, Document target) throws PublicationException;
-
-    /**
-     * Copies all language versions of a document to another location.
-     * @param source The source.
-     * @param target The target.
-     * @throws PublicationException if the documents could not be copied.
-     */
-    void copyAllLanguageVersions(Document source, Document target) throws PublicationException;
-
-    /**
-     * Deletes a document, incl. all requiring documents. If a sitetree is used, this means that the
-     * whole subtree is deleted.
-     * @param document The document.
-     * @throws PublicationException if an error occurs.
-     */
-    void deleteAll(Document document) throws PublicationException;
-
-    /**
-     * Deletes all language versions of a document.
-     * @param document The document.
-     * @throws PublicationException if the documents could not be copied.
-     */
-    void deleteAllLanguageVersions(Document document) throws PublicationException;
-
-    /**
-     * Deletes a set of documents.
-     * @param documents The documents.
-     * @throws PublicationException if an error occurs.
-     */
-    void delete(DocumentSet documents) throws PublicationException;
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java b/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java
deleted file mode 100644
index 9038962..0000000
--- a/src/java/org/apache/lenya/cms/publication/DocumentManagerImpl.java
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.util.HashMap;
-import java.util.Map;
-
-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.ServiceSelector;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.lenya.cms.authoring.NodeCreatorInterface;
-import org.apache.lenya.cms.metadata.LenyaMetaData;
-import org.apache.lenya.cms.metadata.MetaDataManager;
-import org.apache.lenya.cms.publication.util.DocumentSet;
-import org.apache.lenya.cms.publication.util.DocumentVisitor;
-import org.apache.lenya.cms.repository.Node;
-import org.apache.lenya.cms.repository.RepositoryManager;
-import org.apache.lenya.cms.site.SiteManager;
-import org.apache.lenya.cms.site.SiteUtil;
-
-/**
- * DocumentManager implementation.
- * 
- * @version $Id$
- */
-public class DocumentManagerImpl extends AbstractLogEnabled implements DocumentManager,
-        Serviceable, Contextualizable {
-
-    /**
-     * The instance of Document will be built by the implementation of DocumentBuilder; the physical
-     * representation will be built by the implementation of NodeCreatorInterface, where the
-     * implementation to be used is specified in doctypes.xconf (and thus depends on the publication
-     * and the resource type to be used)
-     * 
-     * @see DocumentManager#add(Document, ResourceType, String, boolean, Map)
-     * @see org.apache.lenya.cms.authoring.NodeCreatorInterface
-     * @see org.apache.lenya.cms.publication.DocumentBuilder
-     */
-    public void add(Document document, ResourceType documentType, String navigationTitle,
-            boolean visibleInNav, 
-            Map parameters) throws DocumentBuildException, PublicationException {
-
-        String contentsURI = documentType.getSampleURI();
-        add(document, documentType, navigationTitle, visibleInNav, parameters, contentsURI);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#add(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document, java.lang.String, boolean, 
-     *      java.util.Map)
-     */
-    public void add(Document document, Document sourceDocument, String navigationTitle,
-            boolean visibleInNav,
-            Map parameters) throws DocumentBuildException, PublicationException {
-        String contentsURI = sourceDocument.getSourceURI();
-        add(document, sourceDocument.getResourceType(), navigationTitle, visibleInNav, parameters, contentsURI);
-        MetaDataManager mgr = document.getMetaDataManager();
-        MetaDataManager srcMgr = sourceDocument.getMetaDataManager();
-        mgr.getLenyaMetaData().replaceBy(srcMgr.getLenyaMetaData());
-        mgr.getDublinCoreMetaData().replaceBy(srcMgr.getDublinCoreMetaData());
-        mgr.getCustomMetaData().replaceBy(srcMgr.getCustomMetaData());
-    }
-
-    /**
-     * Adds a document.
-     * @param document The document.
-     * @param documentType The document type.
-     * @param navigationTitle The navigation title.
-     * @param visibleInNav determines the visibility of a node in the navigation
-     * @param parameters The parameters for the creator.
-     * @param initialContentsURI A URI to read the contents from.
-     * @throws DocumentBuildException if an error occurs.
-     * @throws DocumentException if an error occurs.
-     * @throws PublicationException if an error occurs.
-     */
-
-    protected void add(Document document, ResourceType documentType, String navigationTitle,
-            boolean visibleInNav, Map parameters, String initialContentsURI) throws DocumentBuildException,
-            DocumentException, PublicationException {
-
-        try {
-
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("Create");
-                getLogger().debug("    document:     [" + document + "]");
-                getLogger().debug("    nav title:    [" + navigationTitle + "]");
-                getLogger().debug("    contents URI: [" + initialContentsURI + "]");
-            }
-
-            // look up creator for documents of this type
-            NodeCreatorInterface creator = documentType.getCreator();
-
-            // now that the source is determined, lock involved nodes
-            Node node = document.getRepositoryNode();
-            node.lock();
-
-            //
-            creator.create(initialContentsURI, document, parameters);
-        } catch (Exception e) {
-            throw new DocumentBuildException("call to creator for new document failed", e);
-        }
-
-        // Write Lenya-internal meta-data
-        Map lenyaMetaData = new HashMap(2);
-        lenyaMetaData.put(LenyaMetaData.ELEMENT_RESOURCE_TYPE, documentType.getName());
-        lenyaMetaData.put(LenyaMetaData.ELEMENT_CONTENT_TYPE, "xml");
-        document.getMetaDataManager().setLenyaMetaData(lenyaMetaData);
-
-        // Notify site manager about new document
-        addToSiteManager(document, navigationTitle, visibleInNav);
-    }
-
-    private void addToSiteManager(Document document, String navigationTitle, boolean visibleInNav)
-            throws PublicationException {
-        Publication publication = document.getPublication();
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        try {
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            siteManager = (SiteManager) selector.select(publication.getSiteManagerHint());
-            if (siteManager.contains(document)) {
-                throw new PublicationException("The document [" + document
-                        + "] is already contained in this publication!");
-            }
-
-            siteManager.add(document);
-            siteManager.setLabel(document, navigationTitle);
-            siteManager.setVisibleInNav(document, visibleInNav);
-        } catch (final ServiceException e) {
-            throw new PublicationException(e);
-        } finally {
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-    }
-
-    /**
-     * Template method to copy a document. Override {@link #copyDocumentSource(Document, Document)}
-     * to implement access to a custom repository.
-     * @see org.apache.lenya.cms.publication.DocumentManager#copy(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void copy(Document sourceDocument, Document destinationDocument)
-            throws PublicationException {
-
-        Publication publication = sourceDocument.getPublication();
-        copyDocumentSource(sourceDocument, destinationDocument);
-
-        ResourcesManager resourcesManager = null;
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        try {
-            resourcesManager = (ResourcesManager) this.manager.lookup(ResourcesManager.ROLE);
-            resourcesManager.copyResources(sourceDocument, destinationDocument);
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            siteManager = (SiteManager) selector.select(publication.getSiteManagerHint());
-            siteManager.copy(sourceDocument, destinationDocument);
-        } catch (Exception e) {
-            throw new PublicationException(e);
-        } finally {
-            if (resourcesManager != null) {
-                this.manager.release(resourcesManager);
-            }
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#delete(org.apache.lenya.cms.publication.Document)
-     */
-    public void delete(Document document) throws PublicationException {
-        if (!document.exists()) {
-            throw new PublicationException("Document [" + document + "] does not exist!");
-        }
-
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        ResourcesManager resourcesManager = null;
-        try {
-            resourcesManager = (ResourcesManager) this.manager.lookup(ResourcesManager.ROLE);
-            resourcesManager.deleteResources(document);
-
-            Publication publication = document.getPublication();
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            siteManager = (SiteManager) selector.select(publication.getSiteManagerHint());
-            siteManager.delete(document);
-
-            document.delete();
-        } catch (Exception e) {
-            throw new PublicationException(e);
-        } finally {
-            if (resourcesManager != null) {
-                this.manager.release(resourcesManager);
-            }
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#move(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void move(Document sourceDocument, Document destinationDocument)
-            throws PublicationException {
-        copy(sourceDocument, destinationDocument);
-        delete(sourceDocument);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#copyToArea(org.apache.lenya.cms.publication.Document,
-     *      java.lang.String)
-     */
-    public void copyToArea(Document sourceDocument, String destinationArea)
-            throws PublicationException {
-        Document destinationDocument = sourceDocument.getIdentityMap()
-                .getAreaVersion(sourceDocument, destinationArea);
-        copy(sourceDocument, destinationDocument);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#copyToArea(org.apache.lenya.cms.publication.util.DocumentSet,
-     *      java.lang.String)
-     */
-    public void copyToArea(DocumentSet documentSet, String destinationArea)
-            throws PublicationException {
-        Document[] documents = documentSet.getDocuments();
-        for (int i = 0; i < documents.length; i++) {
-            copyToArea(documents[i], destinationArea);
-        }
-    }
-
-    protected ServiceManager manager;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager _manager) throws ServiceException {
-        this.manager = _manager;
-    }
-
-    private 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;
-    }
-
-    /**
-     * @return The Avalon context.
-     */
-    protected Context getContext() {
-        return this.context;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#isValidDocumentName(java.lang.String)
-     */
-    public boolean isValidDocumentName(String documentName) {
-        return documentName.matches("[a-zA-Z0-9]+");
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#moveAll(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void moveAll(Document source, Document target) throws PublicationException {
-        copyAll(source, target);
-        deleteAll(source);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#moveAllLanguageVersions(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void moveAllLanguageVersions(Document source, Document target)
-            throws PublicationException {
-        copyAllLanguageVersions(source, target);
-        deleteAllLanguageVersions(source);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#copyAll(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void copyAll(Document source, Document target) throws PublicationException {
-
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        try {
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            siteManager = (SiteManager) selector.select(source.getPublication()
-                    .getSiteManagerHint());
-
-            DocumentSet subsite = SiteUtil.getSubSite(this.manager, source);
-            siteManager.sortAscending(subsite);
-
-            DocumentVisitor visitor = new CopyVisitor(this, source, target);
-            subsite.visit(visitor);
-        } catch (ServiceException e) {
-            throw new PublicationException(e);
-        } finally {
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#copyAllLanguageVersions(org.apache.lenya.cms.publication.Document,
-     *      org.apache.lenya.cms.publication.Document)
-     */
-    public void copyAllLanguageVersions(Document source, Document target)
-            throws PublicationException {
-        DocumentIdentityMap identityMap = source.getIdentityMap();
-        String[] languages = source.getLanguages();
-        for (int i = 0; i < languages.length; i++) {
-
-            Document sourceVersion = identityMap.getLanguageVersion(source, languages[i]);
-            Document targetVersion = identityMap.get(target.getPublication(),
-                    target.getArea(),
-                    target.getId(),
-                    languages[i]);
-            copy(sourceVersion, targetVersion);
-        }
-    }
-
-    /**
-     * Copies a document source.
-     * @param sourceDocument The source document.
-     * @param destinationDocument The destination document.
-     * @throws PublicationException when something went wrong.
-     */
-    public void copyDocumentSource(Document sourceDocument, Document destinationDocument)
-            throws PublicationException {
-
-        RepositoryManager repoManager = null;
-        try {
-            repoManager = (RepositoryManager) this.manager.lookup(RepositoryManager.ROLE);
-            repoManager.copy(sourceDocument.getRepositoryNode(), destinationDocument.getRepositoryNode());
-        } catch (Exception e) {
-            throw new PublicationException(e);
-        } finally {
-            if (repoManager != null) {
-                this.manager.release(repoManager);
-            }
-        }
-    }
-
-    /**
-     * Abstract base class for document visitors which operate on a source and target document.
-     */
-    public abstract class SourceTargetVisitor implements DocumentVisitor {
-
-        private Document rootSource;
-        private Document rootTarget;
-        private DocumentManager manager;
-
-        /**
-         * Ctor.
-         * @param manager The document manager.
-         * @param source The root source.
-         * @param target The root target.
-         */
-        public SourceTargetVisitor(DocumentManager manager, Document source, Document target) {
-            this.manager = manager;
-            this.rootSource = source;
-            this.rootTarget = target;
-        }
-
-        /**
-         * @return the root source
-         */
-        protected Document getRootSource() {
-            return rootSource;
-        }
-
-        /**
-         * @return the root target
-         */
-        protected Document getRootTarget() {
-            return rootTarget;
-        }
-
-        /**
-         * @return the document manager
-         */
-        protected DocumentManager getDocumentManager() {
-            return this.manager;
-        }
-
-        /**
-         * Returns the target corresponding to a source relatively to the root target document.
-         * @param source The source.
-         * @return A document.
-         * @throws DocumentBuildException if the target could not be built.
-         */
-        protected Document getTarget(Document source) throws DocumentBuildException {
-            String rootSourceId = getRootSource().getId();
-            String rootTargetId = getRootTarget().getId();
-            String childId = source.getId().substring(rootSourceId.length());
-            String targetId = rootTargetId + childId;
-            return getRootTarget().getIdentityMap().get(getRootTarget().getPublication(),
-                    getRootTarget().getArea(),
-                    targetId,
-                    source.getLanguage());
-        }
-    }
-
-    /**
-     * DocumentVisitor to copy documents.
-     */
-    public class CopyVisitor extends SourceTargetVisitor {
-
-        /**
-         * Ctor.
-         * @param manager The document manager.
-         * @param source The root source.
-         * @param target The root target.
-         */
-        public CopyVisitor(DocumentManager manager, Document source, Document target) {
-            super(manager, source, target);
-        }
-
-        /**
-         * @see org.apache.lenya.cms.publication.util.DocumentVisitor#visitDocument(org.apache.lenya.cms.publication.Document)
-         */
-        public void visitDocument(Document source) throws PublicationException {
-            Document target = getTarget(source);
-            getDocumentManager().copyAllLanguageVersions(source, target);
-        }
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#deleteAll(org.apache.lenya.cms.publication.Document)
-     */
-    public void deleteAll(Document document) throws PublicationException {
-
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        try {
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            siteManager = (SiteManager) selector.select(document.getPublication()
-                    .getSiteManagerHint());
-
-            DocumentSet subsite = SiteUtil.getSubSite(this.manager, document);
-            delete(subsite);
-        } catch (ServiceException e) {
-            throw new PublicationException(e);
-        } finally {
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#deleteAllLanguageVersions(org.apache.lenya.cms.publication.Document)
-     */
-    public void deleteAllLanguageVersions(Document document) throws PublicationException {
-        DocumentIdentityMap identityMap = document.getIdentityMap();
-        String[] languages = document.getLanguages();
-        for (int i = 0; i < languages.length; i++) {
-            Document version = identityMap.getLanguageVersion(document, languages[i]);
-            delete(version);
-        }
-    }
-
-    /**
-     * Visitor to delete documents.
-     */
-    public class DeleteVisitor implements DocumentVisitor {
-
-        private DocumentManager manager;
-
-        /**
-         * Ctor.
-         * @param manager The document manager.
-         */
-        public DeleteVisitor(DocumentManager manager) {
-            this.manager = manager;
-        }
-
-        protected DocumentManager getDocumentManager() {
-            return this.manager;
-        }
-
-        /**
-         * @see org.apache.lenya.cms.publication.util.DocumentVisitor#visitDocument(org.apache.lenya.cms.publication.Document)
-         */
-        public void visitDocument(Document document) throws PublicationException {
-            getDocumentManager().deleteAllLanguageVersions(document);
-        }
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#delete(org.apache.lenya.cms.publication.util.DocumentSet)
-     */
-    public void delete(DocumentSet documents) throws PublicationException {
-
-        if (documents.isEmpty()) {
-            return;
-        }
-
-        SiteManager siteManager = null;
-        ServiceSelector selector = null;
-        try {
-            selector = (ServiceSelector) this.manager.lookup(SiteManager.ROLE + "Selector");
-            Publication pub = documents.getDocuments()[0].getPublication();
-            siteManager = (SiteManager) selector.select(pub.getSiteManagerHint());
-
-            DocumentSet set = new DocumentSet(documents.getDocuments());
-            siteManager.sortAscending(set);
-            set.reverse();
-
-            DocumentVisitor visitor = new DeleteVisitor(this);
-            set.visit(visitor);
-        } catch (ServiceException e) {
-            throw new PublicationException(e);
-        } finally {
-            if (selector != null) {
-                if (siteManager != null) {
-                    selector.release(siteManager);
-                }
-                this.manager.release(selector);
-            }
-        }
-
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#move(org.apache.lenya.cms.publication.util.DocumentSet,
-     *      org.apache.lenya.cms.publication.util.DocumentSet)
-     */
-    public void move(DocumentSet sources, DocumentSet destinations) throws PublicationException {
-        copy(sources, destinations);
-        delete(sources);
-        /*
-         * Document[] sourceDocs = sources.getDocuments(); Document[] targetDocs =
-         * destinations.getDocuments();
-         * 
-         * if (sourceDocs.length != targetDocs.length) { throw new PublicationException( "The number
-         * of source and destination documents must be equal!"); }
-         * 
-         * Map source2target = new HashMap(); for (int i = 0; i < sourceDocs.length; i++) {
-         * source2target.put(sourceDocs[i], targetDocs[i]); }
-         * 
-         * DocumentSet sortedSources = new DocumentSet(sourceDocs);
-         * SiteUtil.sortAscending(this.manager, sortedSources); Document[] sortedSourceDocs =
-         * sortedSources.getDocuments();
-         * 
-         * for (int i = 0; i < sortedSourceDocs.length; i++) { move(sortedSourceDocs[i], (Document)
-         * source2target.get(sortedSourceDocs[i])); }
-         */
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentManager#copy(org.apache.lenya.cms.publication.util.DocumentSet,
-     *      org.apache.lenya.cms.publication.util.DocumentSet)
-     */
-    public void copy(DocumentSet sources, DocumentSet destinations) throws PublicationException {
-        Document[] sourceDocs = sources.getDocuments();
-        Document[] targetDocs = destinations.getDocuments();
-
-        if (sourceDocs.length != targetDocs.length) {
-            throw new PublicationException("The number of source and destination documents must be equal!");
-        }
-
-        Map source2target = new HashMap();
-        for (int i = 0; i < sourceDocs.length; i++) {
-            source2target.put(sourceDocs[i], targetDocs[i]);
-        }
-
-        DocumentSet sortedSources = new DocumentSet(sourceDocs);
-        SiteUtil.sortAscending(this.manager, sortedSources);
-        Document[] sortedSourceDocs = sortedSources.getDocuments();
-
-        for (int i = 0; i < sortedSourceDocs.length; i++) {
-            copy(sortedSourceDocs[i], (Document) source2target.get(sortedSourceDocs[i]));
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/IdentityDocumentIdToPathMapper.java b/src/java/org/apache/lenya/cms/publication/IdentityDocumentIdToPathMapper.java
deleted file mode 100644
index b87f01d..0000000
--- a/src/java/org/apache/lenya/cms/publication/IdentityDocumentIdToPathMapper.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-
-/**
- * Identity Document Id to path mapper
- */
-public class IdentityDocumentIdToPathMapper implements DocumentIdToPathMapper {
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentIdToPathMapper#getFile(org.apache.lenya.cms.publication.Publication, java.lang.String, java.lang.String, java.lang.String)
-     */
-    public File getFile(Publication publication, String area, String documentId, String language) {
-        File areaDirectory =
-            new File(publication.getDirectory(), Publication.CONTENT_PATH + File.separator + area);
-        File file = new File(areaDirectory, getPath(documentId, language));
-        return file;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentIdToPathMapper#getDirectory(org.apache.lenya.cms.publication.Publication, java.lang.String, java.lang.String)
-     */
-    public File getDirectory(Publication publication, String area, String documentId) {
-        return getFile(publication, area, documentId, null).getParentFile();
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.DocumentIdToPathMapper#getPath(java.lang.String, java.lang.String)
-     */
-    public String getPath(String documentId, String language) {
-        assert documentId.startsWith("/");
-        // remove leading slash
-        documentId = documentId.substring(1);
-        return documentId + getSuffix(language);
-    }
-
-    /**
-     * Constructs the filename for a given language.
-     * @param language The language.
-     * @return A string value.
-     */
-    protected String getSuffix(String language) {
-        String languageSuffix = "";
-        if (language != null && !"".equals(language)) {
-            languageSuffix = "_" + language;
-        }
-        return languageSuffix + ".xml";
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/PageEnvelope.java b/src/java/org/apache/lenya/cms/publication/PageEnvelope.java
deleted file mode 100644
index 5ff8f7b..0000000
--- a/src/java/org/apache/lenya/cms/publication/PageEnvelope.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-
-import org.apache.cocoon.environment.Request;
-import org.apache.lenya.cms.rc.RCEnvironment;
-
-/**
- * A page envelope carries a set of information that are needed during the presentation of a
- * document.
- */
-public class PageEnvelope {
-    /**
-     * The names of the page envelope parameters.
-     */
-    public static final String[] PARAMETER_NAMES = { PageEnvelope.AREA, PageEnvelope.CONTEXT,
-            PageEnvelope.PUBLICATION_ID, PageEnvelope.PUBLICATION,
-            PageEnvelope.PUBLICATION_LANGUAGES_CSV, PageEnvelope.DOCUMENT,
-            PageEnvelope.DOCUMENT_ID, PageEnvelope.DOCUMENT_NAME, PageEnvelope.DOCUMENT_LABEL,
-            PageEnvelope.DOCUMENT_URL, PageEnvelope.DOCUMENT_URL_WITHOUT_LANGUAGE,
-            PageEnvelope.DOCUMENT_PATH, PageEnvelope.DOCUMENT_EXTENSION,
-            PageEnvelope.DOCUMENT_TYPE, PageEnvelope.DEFAULT_LANGUAGE,
-            PageEnvelope.DOCUMENT_LANGUAGE, PageEnvelope.DOCUMENT_LANGUAGES,
-            PageEnvelope.DOCUMENT_LANGUAGES_CSV, PageEnvelope.DOCUMENT_LASTMODIFIED,
-            PageEnvelope.BREADCRUMB_PREFIX, PageEnvelope.SSL_PREFIX };
-    /**
-     * <code>PUBLICATION_ID</code> The publication id
-     */
-    public static final String PUBLICATION_ID = "publication-id";
-    /**
-     * <code>PUBLICATION</code> The publication
-     */
-    public static final String PUBLICATION = "publication";
-    /**
-     * <code>PUBLICATION_LANGUAGES_CSV</code> A list of the publication's languages,
-     * comma-seperated
-     */
-    public static final String PUBLICATION_LANGUAGES_CSV = "publication-languages-csv";
-    /**
-     * <code>CONTEXT</code> The context prefix
-     */
-    public static final String CONTEXT = "context-prefix";
-    /**
-     * <code>AREA</code> The area
-     */
-    public static final String AREA = "area";
-    /**
-     * <code>DEFAULT_LANGUAGE</code> The default language of the publication
-     */
-    public static final String DEFAULT_LANGUAGE = "default-language";
-    /**
-     * <code>DOCUMENT</code> The current document
-     */
-    public static final String DOCUMENT = "document";
-    /**
-     * <code>DOCUMENT_ID</code> The document id of the current document
-     */
-    public static final String DOCUMENT_ID = "document-id";
-    /**
-     * <code>DOCUMENT_NAME</code> The name of the current document
-     */
-    public static final String DOCUMENT_NAME = "document-name";
-    /**
-     * <code>DOCUMENT_TYPE</code> The type of the current document
-     */
-    public static final String DOCUMENT_TYPE = "document-type";
-    /**
-     * <code>DOCUMENT_LABEL</code> The label of the current document
-     */
-    public static final String DOCUMENT_LABEL = "document-label";
-    /**
-     * <code>DOCUMENT_URL</code> The URL of the current document
-     */
-    public static final String DOCUMENT_URL = "document-url";
-    /**
-     * <code>DOCUMENT_URL_WITHOUT_LANGUAGE</code> The URL of the current document without a
-     * language extension.
-     */
-    public static final String DOCUMENT_URL_WITHOUT_LANGUAGE = "document-url-without-language";
-    /**
-     * <code>DOCUMENT_FILE</code> The file of the current document
-     */
-    public static final String DOCUMENT_FILE = "document-file";
-    /**
-     * <code>DOCUMENT_PATH</code> The path of the current document
-     */
-    public static final String DOCUMENT_PATH = "document-path";
-    /**
-     * <code>DOCUMENT_EXTENSION</code> The extension of the current document
-     */
-    public static final String DOCUMENT_EXTENSION = "document-extension";
-    /**
-     * <code>DOCUMENT_LANGUAGE</code> The language of the current document
-     */
-    public static final String DOCUMENT_LANGUAGE = "document-language";
-    /**
-     * <code>DOCUMENT_LANGUAGES</code> The languages the current document is available in
-     */
-    public static final String DOCUMENT_LANGUAGES = "document-languages";
-    /**
-     * <code>DOCUMENT_LANGUAGES_CSV</code> The languages the current document is available in,
-     * comma-seperated
-     */
-    public static final String DOCUMENT_LANGUAGES_CSV = "document-languages-csv";
-    /**
-     * <code>DOCUMENT_LASTMODIFIED</code> The last modified date of the current document
-     */
-    public static final String DOCUMENT_LASTMODIFIED = "document-lastmodified";
-    /**
-     * <code>BREADCRUMB_PREFIX</code> The breadcrumb prefix of the publication, used for
-     * navigation
-     */
-    public static final String BREADCRUMB_PREFIX = "breadcrumb-prefix";
-    /**
-     * <code>SSL_PREFIX</code> The SSL prefix of the publication
-     */
-    public static final String SSL_PREFIX = "ssl-prefix";
-    /**
-     * <code>NAMESPACE</code> The page envelope namespace
-     */
-    public static final String NAMESPACE = "http://apache.org/cocoon/lenya/page-envelope/1.0";
-    /**
-     * <code>DEFAULT_PREFIX</code> The default prefix
-     */
-    public static final String DEFAULT_PREFIX = "lenya";
-
-    private String context;
-    private String area;
-    private Publication publication;
-
-    /**
-     * Constructor.
-     */
-    protected PageEnvelope() {
-        // do nothing
-    }
-
-    /**
-     * Creates a page envelope from an object model.
-     * @param map The identity map to use.
-     * @param contextPath The servlet context prefix.
-     * @param webappUrl The web application URL.
-     * @param servletContext The servlet context directory.
-     * @param publication The publication.
-     * @throws PageEnvelopeException when something went wrong.
-     */
-    public PageEnvelope(DocumentIdentityMap map, String contextPath, String webappUrl,
-            File servletContext, Publication publication) throws PageEnvelopeException {
-        this.identityMap = map;
-        this.context = contextPath;
-        this.webappUrl = webappUrl;
-        this.publication = publication;
-    }
-
-    private String webappUrl;
-
-    private DocumentIdentityMap identityMap;
-
-    /**
-     * Returns the identity map.
-     * @return An identity map.
-     */
-    public DocumentIdentityMap getIdentityMap() {
-        return this.identityMap;
-    }
-
-    /**
-     * Creates the message to report when creating the envelope failed.
-     * @param request The request.
-     * @return A string.
-     */
-    protected String createExceptionMessage(Request request) {
-        return "Resolving page envelope failed:" + "\n  URI: " + request.getRequestURI()
-                + "\n  Context: " + getContext() + "\n  Publication ID: "
-                + getPublication().getId() + "\n  Area: " + this.document.getArea()
-                + "\n  Document ID: " + this.document.getId();
-    }
-
-    /**
-     * Returns the publication of this PageEnvelope.
-     * @return a <code>Publication</code> value
-     */
-    public Publication getPublication() {
-        /*
-        if (this.publication == null) {
-            try {
-                Publication pub = PublicationManagerImpl.getInstance(new ConsoleLogger())
-                        .getPublication(this.webappUrl, this.servletContext);
-                if (pub.exists()) {
-                    this.publication = pub;
-                    if (getIdentityMap().isDocument(this.webappUrl)) {
-                        Document _document = getIdentityMap().getFromURL(this.webappUrl);
-                        setDocument(_document);
-                    }
-                }
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-        */
-        return this.publication;
-    }
-
-    /**
-     * @return The current area.
-     */
-    public String getArea() {
-        if (this.area == null) {
-            URLInformation info = new URLInformation(this.webappUrl);
-            this.area = info.getArea();
-        }
-        return this.area;
-    }
-
-    /**
-     * Returns the rcEnvironment.
-     * 
-     * @return a <code>RCEnvironment</code> value
-     * @deprecated We should detach the RC environment from the page envelope.
-     */
-    public RCEnvironment getRCEnvironment() {
-        return RCEnvironment.getInstance(getPublication().getServletContext().getAbsolutePath());
-    }
-
-    /**
-     * Returns the context, e.g. "/lenya".
-     * @return a <code>String</code> value
-     */
-    public String getContext() {
-        return this.context;
-    }
-
-    /**
-     * Returns the document-path.
-     * @return a <code>File<code> value
-     */
-    public String getDocumentPath() {
-        return getPublication().getPathMapper().getPath(getDocument().getId(),
-                getDocument().getLanguage());
-    }
-
-    /**
-     * @param string The context.
-     */
-    protected void setContext(String string) {
-        this.context = string;
-    }
-
-    private Document document;
-    private boolean documentChecked = false;
-
-    /**
-     * Returns the document or <code>null</code> if the current URL does not represent a document.
-     * @return A document
-     */
-    public Document getDocument() {
-        if (!documentChecked) {
-            try {
-                documentChecked = true;
-                if (getIdentityMap().isDocument(this.webappUrl)) {
-                    this.document = getIdentityMap().getFromURL(this.webappUrl);
-                }
-            } catch (final DocumentBuildException e) {
-                throw new RuntimeException(e);
-            }
-        }
-        return this.document;
-    }
-
-    /**
-     * Sets the document.
-     * @param _document A document.
-     */
-    public void setDocument(Document _document) {
-        this.document = _document;
-    }
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/PageEnvelopeException.java b/src/java/org/apache/lenya/cms/publication/PageEnvelopeException.java
deleted file mode 100644
index 5c4f161..0000000
--- a/src/java/org/apache/lenya/cms/publication/PageEnvelopeException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-
-/**
- * This exception is thrown when the creation of a {@link PageEnvelope} object fails.
- */
-public class PageEnvelopeException extends Exception {
-    /**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/**
-     * Creates a new PageEnvelopeException.
-     */
-    public PageEnvelopeException() {
-	    // do nothing
-    }
-
-    /**
-     * Creates a new PageEnvelopeException.
-     * @param message the exception message
-     */
-    public PageEnvelopeException(String message) {
-        super(message);
-    }
-
-    /**
-     * Creates a new PageEnvelopeException.
-     * @param message the exception message
-     * @param cause the cause of the exception
-     */
-    public PageEnvelopeException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    /**
-     * Creates a new PageEnvelopeException.
-     * @param cause  the cause of the exception
-     */
-    public PageEnvelopeException(Throwable cause) {
-        super(cause);
-    }
-}
diff --git a/src/java/org/apache/lenya/cms/publication/PageEnvelopeFactory.java b/src/java/org/apache/lenya/cms/publication/PageEnvelopeFactory.java
deleted file mode 100644
index 969c8bc..0000000
--- a/src/java/org/apache/lenya/cms/publication/PageEnvelopeFactory.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-import java.util.Map;
-
-import org.apache.cocoon.environment.Context;
-import org.apache.cocoon.environment.ObjectModelHelper;
-import org.apache.cocoon.environment.Request;
-import org.apache.lenya.util.ServletHelper;
-
-/**
- * Common entry point for creating page envelopes.
- */
-public class PageEnvelopeFactory {
-    /**
-     * Creates a new PageEnvelopeFactory.
-     */
-    protected PageEnvelopeFactory() {
-        // do nothing
-    }
-
-    private static PageEnvelopeFactory instance;
-
-    /**
-     * Returns the singleton PageEnvelopeFactory.
-     * @return The factory.
-     */
-    public static PageEnvelopeFactory getInstance() {
-        if (instance == null) {
-            instance = new PageEnvelopeFactory();
-        }
-        return instance;
-    }
-
-    /**
-     * Returns the page envelope for the object model of a Cocoon component.
-     * @param map The document identity map to use.
-     * @param objectModel The object model.
-     * @param pub The publication.
-     * @return A page envelope.
-     * @throws PageEnvelopeException if something went wrong.
-     */
-    public PageEnvelope getPageEnvelope(DocumentIdentityMap map, Map objectModel, Publication pub)
-            throws PageEnvelopeException {
-        Request request = ObjectModelHelper.getRequest(objectModel);
-        String contextPath = request.getContextPath();
-        Context context = ObjectModelHelper.getContext(objectModel);
-        String webappUrl = ServletHelper.getWebappURI(request);
-        String servletContextPath = context.getRealPath("");
-        return getPageEnvelope(map, contextPath, webappUrl, new File(servletContextPath), pub);
-    }
-
-    /**
-     * Creates a page envelope.
-     * @param map The document identity map to use.
-     * @param contextPath The servlet context prefix.
-     * @param webappUrl The web application URL.
-     * @param servletContext The servlet context directory.
-     * @param pub The publication.
-     * @return A page envelope.
-     * @throws PageEnvelopeException if something went wrong.
-     */
-    public PageEnvelope getPageEnvelope(DocumentIdentityMap map, String contextPath,
-            String webappUrl, File servletContext, Publication pub) throws PageEnvelopeException {
-        PageEnvelope envelope = new PageEnvelope(map, contextPath, webappUrl, servletContext, pub);
-        return envelope;
-    }
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/PathToDocumentIdMapper.java b/src/java/org/apache/lenya/cms/publication/PathToDocumentIdMapper.java
deleted file mode 100644
index 8303997..0000000
--- a/src/java/org/apache/lenya/cms/publication/PathToDocumentIdMapper.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-
-/**
- * This interface is basically the reverse of DocumentIdToPathMapper.
- */
-public interface PathToDocumentIdMapper {
-
-    /**
-     * Compute the document-id for a given file.
-     * @param publication the publication where the file is.
-     * @param area the area where the file is.
-     * @param file the file that is associated with the document
-     * @return the document-id of the document associated with the given file.
-     * @throws DocumentDoesNotExistException if there is no document associated with this file.
-     */
-    String getDocumentId(Publication publication, String area, File file)
-        throws DocumentDoesNotExistException;
-        
-    /**
-     * Returns the language for a given file
-     * @param file the document file
-     * @return the language for the given document file or null if the file
-     * has no language.
-     */
-    public String getLanguage(File file);
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/Proxy.java b/src/java/org/apache/lenya/cms/publication/Proxy.java
deleted file mode 100644
index 5b9f338..0000000
--- a/src/java/org/apache/lenya/cms/publication/Proxy.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-/**
- * <p>
- * An object of this class represents a proxy configuration.
- * </p>
- * <p>
- * Configuration example:
- * </p>
- * <pre>
- * &lt;proxy area="live" ssl="true" url="https://www.host.com/ssl/default"/&gt;
- * &lt;proxy area="live" ssl="false" url="http://www.host.com/default"/&gt;
- * &lt;proxy area="authoring" ssl="true" url="https://www.host.com/lenya/default/authoring"/&gt;
- * &lt;proxy area="authoring" ssl="false" url="http://www.host.com/lenya/default/authoring"/&gt;
- * </pre>
- * 
- * @version $Id$
- */
-public class Proxy {
-
-    private String url;
-
-    /**
-     * Returns the absolute URL of a particular document.
-     * @param document The document.
-     * @return A string.
-     */
-    public String getURL(Document document) {
-        return getUrl() + document.getCanonicalDocumentURL();
-    }
-
-    /**
-     * Returns the proxy URL.
-     * @return A string.
-     */
-    public String getUrl() {
-        return this.url;
-    }
-
-    /**
-     * Sets the proxy URL.
-     * @param _url The url to set.
-     */
-    public void setUrl(String _url) {
-        this.url = _url;
-    }
-
-    /**
-     * @see java.lang.Object#toString()
-     */
-    public String toString() {
-        return "Proxy URL=[" + getUrl() + "]";
-    }
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/Publication.java b/src/java/org/apache/lenya/cms/publication/Publication.java
deleted file mode 100644
index 19f9a00..0000000
--- a/src/java/org/apache/lenya/cms/publication/Publication.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id$  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-
-/**
- * A Lenya publication.
- */
-public interface Publication {
-
-    /**
-     * <code>AUTHORING_AREA</code> The authoring area
-     */
-    String AUTHORING_AREA = "authoring";
-    /**
-     * <code>STAGING_AREA</code> The staging area
-     */
-    String STAGING_AREA = "staging";
-    /**
-     * <code>LIVE_AREA</code> The live area
-     */
-    String LIVE_AREA = "live";
-    /**
-     * <code>ADMIN_AREA</code> The admin area
-     */
-    String ADMIN_AREA = "admin";
-    /**
-     * <code>ARCHIVE_AREA</code> The archive area
-     */
-    String ARCHIVE_AREA = "archive";
-    /**
-     * <code>TRASH_AREA</code> The trash area
-     */
-    String TRASH_AREA = "trash";
-    /**
-     * <code>PUBLICATION_PREFIX</code> The publication prefix
-     */
-    String PUBLICATION_PREFIX = "lenya" + File.separator + "pubs";
-    /**
-     * <code>PUBLICATION_PREFIX_URI</code> The publication prefix URI
-     */
-    String PUBLICATION_PREFIX_URI = "lenya/pubs";
-    /**
-     * <code>CONFIGURATION_PATH</code> The configuration path
-     */
-    String CONFIGURATION_PATH = "config";
-    /**
-     * <code>CONTENT_PATH</code> The content path
-     */
-    String CONTENT_PATH = "content";
-    /**
-     * <code>PENDING_PATH</code> The pending path
-     */
-    String PENDING_PATH = "pending";
-    /**
-     * <code>DELETE_PATH</code> The delete path
-     */
-    String DELETE_PATH = "delete";
-    /**
-     * <code>SEARCH_AREA_PREFIX</code> The search area prefix
-     */
-    String SEARCH_AREA_PREFIX = "search-";
-
-    /**
-     * Returns the publication ID.
-     * @return A string value.
-     */
-    String getId();
-
-    /**
-     * Returns the servlet context this publication belongs to (usually, the
-     * <code>webapps/lenya</code> directory).
-     * @return A <code>File</code> object.
-     */
-    File getServletContext();
-
-    /**
-     * @return if this publication exists.
-     */
-    boolean exists();
-
-    /**
-     * Returns the publication directory.
-     * @return A <code>File</code> object.
-     */
-    File getDirectory();
-
-    /**
-     * Return the directory of a specific area.
-     * @param area a <code>File</code> representing the root of the area content directory.
-     * @return the directory of the given content area.
-     */
-    File getContentDirectory(String area);
-
-    /**
-     * Set the path mapper
-     * @param mapper The path mapper
-     */
-    void setPathMapper(DefaultDocumentIdToPathMapper mapper);
-
-    /**
-     * Returns the path mapper.
-     * @return a <code>DocumentIdToPathMapper</code>
-     */
-    DocumentIdToPathMapper getPathMapper();
-
-    /**
-     * Get the default language
-     * @return the default language
-     */
-    String getDefaultLanguage();
-
-    /**
-     * Set the default language
-     * @param language the default language
-     */
-    void setDefaultLanguage(String language);
-
-    /**
-     * Get all available languages for this publication
-     * @return an <code>Array</code> of languages
-     */
-    String[] getLanguages();
-
-    /**
-     * Get the breadcrumb prefix. It can be used as a prefix if a publication is part of a larger
-     * site
-     * @return the breadcrumb prefix
-     */
-    String getBreadcrumbPrefix();
-
-    /**
-     * Returns the hint of the site manager service that is used by this publication.
-     * @return A hint to use for service selection.
-     */
-    String getSiteManagerHint();
-
-    /**
-     * Returns the document builder class of this instance.
-     * @return A hint to use for service selection.
-     */
-    String getDocumentBuilderHint();
-
-    /**
-     * Returns the publication template instantiator hint. If the publication does not allow
-     * templating, <code>null</code> is returned.
-     * @return A hint to use for service selection.
-     */
-    String getInstantiatorHint();
-
-    /**
-     * Returns the proxy which is used for a particular document.
-     * @param document The document.
-     * @param isSslProtected A boolean value.
-     * @return A proxy or <code>null</code> if no proxy is defined for this version.
-     */
-    Proxy getProxy(Document document, boolean isSslProtected);
-
-    /**
-     * @return The templates of the publication.
-     */
-    String[] getTemplateIds();
-
-    /**
-     * @return the URI base for this publication
-     */
-    String getSourceURI();
-
-    /**
-     * @param area The area.
-     * @return the URI base under which contents in this publication are accessed
-     */
-    String getContentURI(String area);
-
-    /**
-     * @param resourceType The resource type or <code>null</code> if no workflow is registered for
-     *            this resource type.
-     * @return The workflow schema to use for this resource type.
-     */
-    String getWorkflowSchema(ResourceType resourceType);
-    
-    /**
-     * @return The resource types that are supported by this publication.
-     */
-    String[] getResourceTypeNames();
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/PublicationImpl.java b/src/java/org/apache/lenya/cms/publication/PublicationImpl.java
deleted file mode 100644
index d99124c..0000000
--- a/src/java/org/apache/lenya/cms/publication/PublicationImpl.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.lenya.cms.repository.Node;
-
-/**
- * A publication.
- * @version $Id$
- */
-public class PublicationImpl extends AbstractLogEnabled implements Publication {
-
-    private static final String[] areas = { AUTHORING_AREA, STAGING_AREA, LIVE_AREA, ADMIN_AREA,
-            ARCHIVE_AREA, TRASH_AREA };
-
-    private String id;
-    private File servletContext;
-    private DocumentIdToPathMapper mapper = null;
-    private ArrayList languages = new ArrayList();
-    private String defaultLanguage = null;
-    private String breadcrumbprefix = null;
-    private String instantiatorHint = null;
-
-    private static final String ELEMENT_PROXY = "proxy";
-    private static final String ATTRIBUTE_AREA = "area";
-    private static final String ATTRIBUTE_URL = "url";
-    private static final String ATTRIBUTE_SSL = "ssl";
-
-    private boolean isConfigLoaded = false;
-
-    /**
-     * <code>CONFIGURATION_FILE</code> The publication configuration file
-     */
-    public static final String CONFIGURATION_FILE = CONFIGURATION_PATH + File.separator
-            + "publication.xconf";
-
-    private static final String ELEMENT_TEMPLATES = "templates";
-    private static final String ELEMENT_TEMPLATE = "template";
-    private static final String ATTRIBUTE_ID = "id";
-    private static final String ELEMENT_PATH_MAPPER = "path-mapper";
-    private static final String ELEMENT_DOCUMENT_BUILDER = "document-builder";
-    private static final String ELEMENT_SITE_MANAGER = "site-manager";
-    private static final String ATTRIBUTE_NAME = "name";
-    private static final String ELEMENT_TEMPLATE_INSTANTIATOR = "template-instantiator";
-    private static final String LANGUAGES = "languages";
-    private static final String DEFAULT_LANGUAGE_ATTR = "default";
-    private static final String BREADCRUMB_PREFIX = "breadcrumb-prefix";
-    private static final String ELEMENT_RESOURCE_TYPE = "resource-type";
-    private static final String ATTRIBUTE_WORKFLOW = "workflow";
-
-    /**
-     * Creates a new instance of Publication
-     * @param _id the publication id
-     * @param servletContextPath the servlet context of this publication
-     * @throws PublicationException if there was a problem reading the config file
-     */
-    protected PublicationImpl(String _id, String servletContextPath) throws PublicationException {
-        this.id = _id;
-        this.servletContext = new File(servletContextPath);
-    }
-
-    /**
-     * Loads the configuration.
-     */
-    protected void loadConfiguration() {
-
-        if (isConfigLoaded) {
-            return;
-        }
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Loading configuration for publication [" + getId() + "]");
-        }
-
-        File configFile = getConfigurationFile();
-
-        if (!configFile.exists()) {
-            getLogger().error("Config file [" + configFile.getAbsolutePath() + "] does not exist: ",
-                    new RuntimeException());
-            throw new RuntimeException("The configuration file [" + configFile
-                    + "] does not exist!");
-        } else {
-            getLogger().debug("Configuration file [" + configFile + "] exists.");
-        }
-
-        DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
-
-        Configuration config;
-
-        String pathMapperClassName = null;
-
-        try {
-            config = builder.buildFromFile(configFile);
-
-            try {
-                pathMapperClassName = config.getChild(ELEMENT_PATH_MAPPER).getValue();
-                Class pathMapperClass = Class.forName(pathMapperClassName);
-                this.mapper = (DocumentIdToPathMapper) pathMapperClass.newInstance();
-            } catch (final ClassNotFoundException e) {
-                throw new PublicationException("Cannot instantiate documentToPathMapper: ["
-                        + pathMapperClassName + "]", e);
-            }
-
-            Configuration documentBuilderConfiguration = config.getChild(ELEMENT_DOCUMENT_BUILDER,
-                    false);
-            if (documentBuilderConfiguration != null) {
-                this.documentBuilderHint = documentBuilderConfiguration.getAttribute(ATTRIBUTE_NAME);
-            }
-
-            Configuration[] _languages = config.getChild(LANGUAGES).getChildren();
-            for (int i = 0; i < _languages.length; i++) {
-                Configuration languageConfig = _languages[i];
-                String language = languageConfig.getValue();
-                this.languages.add(language);
-                if (languageConfig.getAttribute(DEFAULT_LANGUAGE_ATTR, null) != null) {
-                    this.defaultLanguage = language;
-                }
-            }
-
-            Configuration siteManagerConfiguration = config.getChild(ELEMENT_SITE_MANAGER, false);
-            if (siteManagerConfiguration != null) {
-                this.siteManagerName = siteManagerConfiguration.getAttribute(ATTRIBUTE_NAME);
-            }
-
-            Configuration[] proxyConfigs = config.getChildren(ELEMENT_PROXY);
-            for (int i = 0; i < proxyConfigs.length; i++) {
-                String url = proxyConfigs[i].getAttribute(ATTRIBUTE_URL);
-                String ssl = proxyConfigs[i].getAttribute(ATTRIBUTE_SSL);
-                String area = proxyConfigs[i].getAttribute(ATTRIBUTE_AREA);
-
-                Proxy proxy = new Proxy();
-                proxy.setUrl(url);
-
-                Object key = getProxyKey(area, Boolean.valueOf(ssl).booleanValue());
-                this.areaSsl2proxy.put(key, proxy);
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("Adding proxy: [" + proxy + "] for area=[" + area + "] SSL=["
-                            + ssl + "]");
-                }
-            }
-
-            Configuration templatesConfig = config.getChild(ELEMENT_TEMPLATES);
-            if (templatesConfig != null) {
-                Configuration[] templateConfigs = templatesConfig.getChildren(ELEMENT_TEMPLATE);
-                this.templates = new String[templateConfigs.length];
-                for (int i = 0; i < templateConfigs.length; i++) {
-                    String templateId = templateConfigs[i].getAttribute(ATTRIBUTE_ID);
-                    this.templates[i] = templateId;
-                }
-            }
-
-            Configuration templateInstantiatorConfig = config.getChild(ELEMENT_TEMPLATE_INSTANTIATOR,
-                    false);
-            if (templateInstantiatorConfig != null) {
-                this.instantiatorHint = templateInstantiatorConfig.getAttribute(PublicationImpl.ATTRIBUTE_NAME);
-            }
-
-            Configuration[] resourceTypeConfigs = config.getChildren(ELEMENT_RESOURCE_TYPE);
-            for (int i = 0; i < resourceTypeConfigs.length; i++) {
-                String name = resourceTypeConfigs[i].getAttribute(ATTRIBUTE_NAME);
-                this.resourceTypes.add(name);
-
-                String workflow = resourceTypeConfigs[i].getAttribute(ATTRIBUTE_WORKFLOW, null);
-                if (workflow != null) {
-                    this.resourceType2workflow.put(name, workflow);
-                }
-            }
-
-        } catch (final Exception e) {
-            throw new RuntimeException("Problem with config file: " + configFile.getAbsolutePath(),
-                    e);
-        }
-
-        this.breadcrumbprefix = config.getChild(BREADCRUMB_PREFIX).getValue("");
-
-        isConfigLoaded = true;
-    }
-
-    /**
-     * @return The configuration file (publication.xconf).
-     */
-    protected File getConfigurationFile() {
-        File configFile = new File(getDirectory(), CONFIGURATION_FILE);
-        return configFile;
-    }
-
-    /**
-     * Returns the publication ID.
-     * @return A string value.
-     */
-    public String getId() {
-        return this.id;
-    }
-
-    /**
-     * Returns the servlet context this publication belongs to (usually, the
-     * <code>webapps/lenya</code> directory).
-     * @return A <code>File</code> object.
-     */
-    public File getServletContext() {
-        return this.servletContext;
-    }
-
-    /**
-     * Returns the publication directory.
-     * @return A <code>File</code> object.
-     */
-    public File getDirectory() {
-        return new File(getServletContext(), PUBLICATION_PREFIX + File.separator + getId());
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getContentDirectory(String)
-     */
-    public File getContentDirectory(String area) {
-        return new File(getDirectory(), CONTENT_PATH + File.separator + area);
-    }
-
-    /**
-     * Set the path mapper
-     * @param _mapper The path mapper
-     */
-    public void setPathMapper(DefaultDocumentIdToPathMapper _mapper) {
-        assert _mapper != null;
-        this.mapper = _mapper;
-    }
-
-    /**
-     * Returns the path mapper.
-     * @return a <code>DocumentIdToPathMapper</code>
-     */
-    public DocumentIdToPathMapper getPathMapper() {
-        if (this.mapper == null) {
-            loadConfiguration();
-        }
-        return this.mapper;
-    }
-
-    /**
-     * Returns if a given string is a valid area name.
-     * @param area The area string to test.
-     * @return A boolean value.
-     */
-    public static boolean isValidArea(String area) {
-        return area != null && Arrays.asList(areas).contains(area);
-    }
-
-    /**
-     * Get the default language
-     * @return the default language
-     */
-    public String getDefaultLanguage() {
-        if (this.defaultLanguage == null) {
-            loadConfiguration();
-        }
-        return this.defaultLanguage;
-    }
-
-    /**
-     * Set the default language
-     * @param language the default language
-     */
-    public void setDefaultLanguage(String language) {
-        this.defaultLanguage = language;
-    }
-
-    /**
-     * Get all available languages for this publication
-     * @return an <code>Array</code> of languages
-     */
-    public String[] getLanguages() {
-        loadConfiguration();
-        return (String[]) this.languages.toArray(new String[this.languages.size()]);
-    }
-
-    /**
-     * Get the breadcrumb prefix. It can be used as a prefix if a publication is part of a larger
-     * site
-     * @return the breadcrumb prefix
-     */
-    public String getBreadcrumbPrefix() {
-        loadConfiguration();
-        return this.breadcrumbprefix;
-    }
-
-    private String documentBuilderHint;
-
-    /**
-     * Returns the document builder of this instance.
-     * @return A document builder.
-     */
-    public String getDocumentBuilderHint() {
-        loadConfiguration();
-        return this.documentBuilderHint;
-    }
-
-    /**
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    public boolean equals(Object object) {
-        boolean equals = false;
-
-        if (getClass().isInstance(object)) {
-            Publication publication = (Publication) object;
-            equals = getId().equals(publication.getId())
-                    && getServletContext().equals(publication.getServletContext());
-        }
-
-        return equals;
-    }
-
-    /**
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-        String key = getServletContext() + ":" + getId();
-        return key.hashCode();
-    }
-
-    private Map areaSsl2proxy = new HashMap();
-
-    /**
-     * Generates a hash key for a area-SSL combination.
-     * @param area The area.
-     * @param isSslProtected If the proxy is assigned for SSL-protected pages.
-     * @return An object.
-     */
-    protected Object getProxyKey(String area, boolean isSslProtected) {
-        return area + ":" + isSslProtected;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getProxy(org.apache.lenya.cms.publication.Document,
-     *      boolean)
-     */
-    public Proxy getProxy(Document document, boolean isSslProtected) {
-        loadConfiguration();
-        Object key = getProxyKey(document.getArea(), isSslProtected);
-        Proxy proxy = (Proxy) this.areaSsl2proxy.get(key);
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Resolving proxy for [" + document + "] SSL=[" + isSslProtected + "]");
-            getLogger().debug("Resolved proxy: [" + proxy + "]");
-        }
-
-        return proxy;
-    }
-
-    private String siteManagerName;
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#exists()
-     */
-    public boolean exists() {
-        return getConfigurationFile().exists();
-    }
-
-    private String[] templates;
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getTemplateIds()
-     */
-    public String[] getTemplateIds() {
-        loadConfiguration();
-        List list = Arrays.asList(this.templates);
-        return (String[]) list.toArray(new String[list.size()]);
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getSiteManagerHint()
-     */
-    public String getSiteManagerHint() {
-        loadConfiguration();
-        return this.siteManagerName;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getInstantiatorHint()
-     */
-    public String getInstantiatorHint() {
-        loadConfiguration();
-        return this.instantiatorHint;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getSourceURI()
-     */
-    public String getSourceURI() {
-        return Node.LENYA_PROTOCOL + PUBLICATION_PREFIX_URI + "/" + this.id;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getContentURI(java.lang.String)
-     */
-    public String getContentURI(String area) {
-        return getSourceURI() + "/" + CONTENT_PATH + "/" + area;
-    }
-
-    private Map resourceType2workflow = new HashMap();
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getWorkflowSchema(org.apache.lenya.cms.publication.ResourceType)
-     */
-    public String getWorkflowSchema(ResourceType resourceType) {
-        String workflow = (String) this.resourceType2workflow.get(resourceType.getName());
-        return workflow;
-    }
-
-    private List resourceTypes = new ArrayList();
-
-    /**
-     * @see org.apache.lenya.cms.publication.Publication#getResourceTypeNames()
-     */
-    public String[] getResourceTypeNames() {
-        return (String[]) resourceTypes.toArray(new String[resourceTypes.size()]);
-    }
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/PublicationManager.java b/src/java/org/apache/lenya/cms/publication/PublicationManager.java
deleted file mode 100644
index 58f8ddc..0000000
--- a/src/java/org/apache/lenya/cms/publication/PublicationManager.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-
-/**
- * Publication manager.
- */
-public interface PublicationManager {
-
-    /**
-     * The service's role.
-     */
-    String ROLE = PublicationManager.class.getName();
-    
-    /**
-     * @return All publications.
-     * @throws PublicationException if an error occurrs.
-     */
-    Publication[] getPublications() throws PublicationException;
-    
-    /**
-     * @param id The publication ID.
-     * @return A publication.
-     * @throws PublicationException if an error occurs.
-     */
-    Publication getPublication(String id) throws PublicationException;
-    
-}
diff --git a/src/java/org/apache/lenya/cms/publication/PublicationManagerImpl.java b/src/java/org/apache/lenya/cms/publication/PublicationManagerImpl.java
deleted file mode 100644
index 52456b7..0000000
--- a/src/java/org/apache/lenya/cms/publication/PublicationManagerImpl.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.
- *
- */
-
-/* $Id: PublicationFactory.java 177927 2005-05-23 05:32:20Z gregor $  */
-
-package org.apache.lenya.cms.publication;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.avalon.framework.activity.Initializable;
-import org.apache.avalon.framework.container.ContainerUtil;
-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.SourceResolver;
-import org.apache.excalibur.source.SourceUtil;
-
-/**
- * Factory for creating publication objects.
- */
-public final class PublicationManagerImpl extends AbstractLogEnabled implements PublicationManager,
-        Serviceable, Initializable, ThreadSafe {
-
-    /**
-     * Create a new <code>PublicationFactory</code>.
-     */
-    public PublicationManagerImpl() {
-    }
-
-    private static Map idToPublication = new HashMap();
-
-    /**
-     * Create a new publication with the given publication-id and servlet context path. These
-     * publications are cached and reused for similar requests.
-     * @param id the publication id
-     * @return a <code>Publication</code>
-     * @throws PublicationException if there was a problem creating the publication.
-     */
-    public synchronized Publication getPublication(String id) throws PublicationException {
-
-        assert id != null;
-        if (id.indexOf("/") != -1) {
-            throw new PublicationException("The publication ID [" + id + "] must not contain a slash!");
-        }
-
-        Publication publication = null;
-
-        if (idToPublication.containsKey(id)) {
-            publication = (Publication) idToPublication.get(id);
-        } else {
-            publication = new PublicationImpl(id, servletContextPath);
-            ContainerUtil.enableLogging(publication, getLogger());
-            idToPublication.put(id, publication);
-        }
-
-        if (publication == null) {
-            throw new PublicationException("The publication for ID [" + id
-                    + "] could not be created.");
-        }
-        return publication;
-    }
-
-    /**
-     * Returns a list of all available publications.
-     * @return An array of publications.
-     * @throws PublicationException if an error occurs.
-     */
-    public Publication[] getPublications() throws PublicationException {
-        List publications = new ArrayList();
-
-        try {
-            File servletContext = new File(this.servletContextPath);
-            File publicationsDirectory = new File(servletContext, Publication.PUBLICATION_PREFIX);
-            File[] publicationDirectories = publicationsDirectory.listFiles(new FileFilter() {
-                public boolean accept(File file) {
-                    return file.isDirectory();
-                }
-            });
-
-            for (int i = 0; i < publicationDirectories.length; i++) {
-                String publicationId = publicationDirectories[i].getName();
-                Publication publication = getPublication(publicationId);
-                publications.add(publication);
-            }
-
-        } catch (Exception e) {
-            throw new PublicationException(e);
-        }
-
-        return (Publication[]) publications.toArray(new Publication[publications.size()]);
-    }
-
-    private String servletContextPath;
-
-    private ServiceManager manager;
-
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-    }
-
-    public void initialize() throws Exception {
-        SourceResolver resolver = null;
-        Source source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = resolver.resolveURI("context:///");
-            this.servletContextPath = SourceUtil.getFile(source).getCanonicalPath();
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/publication/SingleLanguageIdentityMapper.java b/src/java/org/apache/lenya/cms/publication/SingleLanguageIdentityMapper.java
deleted file mode 100644
index e4b526e..0000000
--- a/src/java/org/apache/lenya/cms/publication/SingleLanguageIdentityMapper.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.lenya.cms.publication;
-
-/**
- * Single Language Identity mapper.
- * Similar to the {@link DefaultDocumentIdToPathMapper}, but doesn't add 
- * a language suffix to the source URIs. This is useful for publications
- * which do not have multiple language version of the same document,
- * such as the "blog" publication.
- * @version $Id$
- */
-public class SingleLanguageIdentityMapper extends IdentityDocumentIdToPathMapper {
-
-    /**
-     * The parameter <code>language</code> is ignored, since this mapper is used for situations where only one language version of a document exists
-     * @see org.apache.lenya.cms.publication.IdentityDocumentIdToPathMapper#getSuffix(java.lang.String)
-     */
-    protected String getSuffix(String language) {
-        return ".xml";
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/publication/URLInformation.java b/src/java/org/apache/lenya/cms/publication/URLInformation.java
index fb563d4..e8b85a4 100644
--- a/src/java/org/apache/lenya/cms/publication/URLInformation.java
+++ b/src/java/org/apache/lenya/cms/publication/URLInformation.java
@@ -83,8 +83,8 @@
                     this.documentUrl = "";
                 }
 
-                if (this.completeArea.startsWith(Publication.SEARCH_AREA_PREFIX)) {
-                    this.area = this.completeArea.substring(Publication.SEARCH_AREA_PREFIX.length());
+                if (this.completeArea.startsWith("search-")) {
+                    this.area = this.completeArea.substring("search-".length());
                 } else {
                     this.area = this.completeArea;
                 }
diff --git a/src/java/org/apache/lenya/cms/publication/templating/ExistingUsecaseResolver.java b/src/java/org/apache/lenya/cms/publication/templating/ExistingUsecaseResolver.java
index 8d2d7d8..ce1e1a7 100644
--- a/src/java/org/apache/lenya/cms/publication/templating/ExistingUsecaseResolver.java
+++ b/src/java/org/apache/lenya/cms/publication/templating/ExistingUsecaseResolver.java
@@ -20,8 +20,8 @@
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationImpl;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.impl.AbstractPublication;
 
 /**
  * Publication visitor which returns the first publication implementing a certain usecase.
@@ -46,12 +46,12 @@
     protected static final String ATTRIBUTE_NAME = "name";
 
     /**
-     * @see org.apache.lenya.cms.publication.templating.PublicationVisitor#visit(org.apache.lenya.cms.publication.Publication)
+     * @see org.apache.lenya.cms.publication.templating.PublicationVisitor#visit(org.apache.lenya.cms.repo.Publication)
      */
     public void visit(Publication _publication) {
 
         if (this.publication == null) {
-            File configFile = new File(_publication.getDirectory(), PublicationImpl.CONFIGURATION_FILE);
+            File configFile = ((AbstractPublication) _publication).getConfigurationFile();
             DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
 
             try {
diff --git a/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManager.java b/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManager.java
index 6a3ac20..395064f 100644
--- a/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManager.java
+++ b/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManager.java
@@ -18,7 +18,7 @@
 
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceSelector;
-import org.apache.lenya.cms.publication.Publication;
+import org.apache.lenya.cms.repo.Publication;
 
 /**
  * <p>
diff --git a/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManagerImpl.java b/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManagerImpl.java
index c8939fa..c614f31 100644
--- a/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManagerImpl.java
+++ b/src/java/org/apache/lenya/cms/publication/templating/PublicationTemplateManagerImpl.java
@@ -29,9 +29,8 @@
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationException;
-import org.apache.lenya.cms.publication.PublicationUtil;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.RepositoryException;
 
 /**
  * Manager for publication templates.
@@ -48,7 +47,7 @@
     }
 
     /**
-     * @see org.apache.lenya.cms.publication.templating.PublicationTemplateManager#visit(org.apache.lenya.cms.publication.Publication,
+     * @see org.apache.lenya.cms.publication.templating.PublicationTemplateManager#visit(org.apache.lenya.cms.repo.Publication,
      *      java.lang.String, org.apache.lenya.cms.publication.templating.SourceVisitor)
      */
     public void visit(Publication publication, String path, SourceVisitor visitor) {
@@ -129,13 +128,15 @@
      * @return A string.
      */
     public static String getBaseURI(Publication publication) {
-        String publicationUri = "context://" + Publication.PUBLICATION_PREFIX_URI + "/"
-                + publication.getId();
-        return publicationUri;
+        try {
+            return "context://lenya/pubs/" + publication.getPublicationId();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     /**
-     * @see org.apache.lenya.cms.publication.templating.PublicationTemplateManager#visit(org.apache.lenya.cms.publication.Publication,
+     * @see org.apache.lenya.cms.publication.templating.PublicationTemplateManager#visit(org.apache.lenya.cms.repo.Publication,
      *      org.apache.lenya.cms.publication.templating.PublicationVisitor)
      */
     public void visit(Publication publication, PublicationVisitor visitor) {
@@ -175,10 +176,10 @@
         String[] templateIds = publication.getTemplateIds();
         for (int i = 0; i < templateIds.length; i++) {
             try {
-                Publication template = PublicationUtil.getPublication(this.manager, templateIds[i]);
+                Publication template = publication.getSession().getPublication(templateIds[i]);
                 Publication[] templateTemplates = getPublications(template);
                 publications.addAll(Arrays.asList(templateTemplates));
-            } catch (PublicationException e) {
+            } catch (RepositoryException e) {
                 throw new RuntimeException(e);
             }
         }
@@ -187,7 +188,7 @@
     }
 
     /**
-     * @see org.apache.lenya.cms.publication.templating.PublicationTemplateManager#getSelectableHint(org.apache.lenya.cms.publication.Publication,
+     * @see org.apache.lenya.cms.publication.templating.PublicationTemplateManager#getSelectableHint(org.apache.lenya.cms.repo.Publication,
      *      org.apache.avalon.framework.service.ServiceSelector, java.lang.String)
      */
     public Object getSelectableHint(Publication publication, ServiceSelector selector,
@@ -196,7 +197,8 @@
         Object selectableHint = null;
 
         try {
-            ExistingServiceVisitor resolver = new ExistingServiceVisitor(selector, originalHint,
+            ExistingServiceVisitor resolver = new ExistingServiceVisitor(selector,
+                    originalHint,
                     getLogger());
             visit(publication, resolver);
             selectableHint = resolver.getSelectableHint();
@@ -239,10 +241,15 @@
         private Logger logger;
 
         /**
-         * @see org.apache.lenya.cms.publication.templating.PublicationVisitor#visit(org.apache.lenya.cms.publication.Publication)
+         * @see org.apache.lenya.cms.publication.templating.PublicationVisitor#visit(org.apache.lenya.cms.repo.Publication)
          */
         public void visit(Publication publication) {
-            String publicationHint = publication.getId() + "/" + this.hint;
+            String publicationHint;
+            try {
+                publicationHint = publication.getPublicationId() + "/" + this.hint;
+            } catch (RepositoryException e) {
+                throw new RuntimeException(e);
+            }
             boolean success = false;
             if (this.selector.isSelectable(publicationHint)) {
                 this.selectableHint = publicationHint;
diff --git a/src/java/org/apache/lenya/cms/publication/templating/PublicationVisitor.java b/src/java/org/apache/lenya/cms/publication/templating/PublicationVisitor.java
index d4cdf6d..ff79573 100644
--- a/src/java/org/apache/lenya/cms/publication/templating/PublicationVisitor.java
+++ b/src/java/org/apache/lenya/cms/publication/templating/PublicationVisitor.java
@@ -17,7 +17,7 @@
 
 package org.apache.lenya.cms.publication.templating;
 
-import org.apache.lenya.cms.publication.Publication;
+import org.apache.lenya.cms.repo.Publication;
 
 /**
  * Publication visitor interface.
diff --git a/src/java/org/apache/lenya/cms/repo/Area.java b/src/java/org/apache/lenya/cms/repo/Area.java
index d24b3ea..3b3fd15 100644
--- a/src/java/org/apache/lenya/cms/repo/Area.java
+++ b/src/java/org/apache/lenya/cms/repo/Area.java
@@ -45,4 +45,10 @@
      */
     String getAreaID() throws RepositoryException;
     
+    /**
+     * @return The publication the area belongs to.
+     * @throws RepositoryException if an error occurs.
+     */
+    Publication getPublication() throws RepositoryException;
+    
 }
diff --git a/src/java/org/apache/lenya/cms/repo/ContentNode.java b/src/java/org/apache/lenya/cms/repo/ContentNode.java
index 080a52a..7c642b6 100644
--- a/src/java/org/apache/lenya/cms/repo/ContentNode.java
+++ b/src/java/org/apache/lenya/cms/repo/ContentNode.java
@@ -80,5 +80,11 @@
      * @throws RepositoryException if the node is still referenced from the site structure.
      */
     void remove() throws RepositoryException;
-
+    
+    /**
+     * @return The content the node belongs to.
+     * @throws RepositoryException
+     */
+    Content getContent() throws RepositoryException;
+    
 }
diff --git a/src/java/org/apache/lenya/cms/repo/DocumentType.java b/src/java/org/apache/lenya/cms/repo/DocumentType.java
index b135d32..ed612fa 100644
--- a/src/java/org/apache/lenya/cms/repo/DocumentType.java
+++ b/src/java/org/apache/lenya/cms/repo/DocumentType.java
@@ -45,4 +45,14 @@
      */
     String getMimeType() throws RepositoryException;
     
+    /**
+     * @return All supported formats.
+     */
+    String[] getFormats();
+    
+    /**
+     * @param format The format.
+     * @return The URI to get the formatted content at.
+     */
+    String getFormatURI(String format);
 }
\ No newline at end of file
diff --git a/src/java/org/apache/lenya/cms/repo/Publication.java b/src/java/org/apache/lenya/cms/repo/Publication.java
index ad4f45e..bf80aae 100644
--- a/src/java/org/apache/lenya/cms/repo/Publication.java
+++ b/src/java/org/apache/lenya/cms/repo/Publication.java
@@ -16,25 +16,33 @@
  */
 package org.apache.lenya.cms.repo;
 
+import org.apache.lenya.cms.proxy.Proxy;
+
 /**
  * A publication.
  */
 public interface Publication {
 
     /**
+     * @return All existing areas.
+     * @throws RepositoryException if an error occurs.
+     */
+    Area[] getAreas() throws RepositoryException;
+
+    /**
      * @param area The area ID.
      * @return The area object.
      * @throws RepositoryException if the area does not exist.
      */
     Area getArea(String area) throws RepositoryException;
-    
+
     /**
      * @param area The area ID.
      * @return The area object.
      * @throws RepositoryException if the area already exists.
      */
     Area addArea(String area) throws RepositoryException;
-    
+
     /**
      * Checks if an area exists in this publication.
      * @param area The area.
@@ -42,11 +50,68 @@
      * @throws RepositoryException of an error occurs.
      */
     boolean existsArea(String area) throws RepositoryException;
-    
+
     /**
      * @return The publication ID.
      * @throws RepositoryException if an error occurs.
      */
     String getPublicationId() throws RepositoryException;
+
+    /**
+     * Get the default language
+     * @return the default language
+     */
+    String getDefaultLanguage();
+
+    /**
+     * Get all available languages for this publication
+     * @return an <code>Array</code> of languages
+     */
+    String[] getLanguages();
+
+    /**
+     * Returns the hint of the site manager service that is used by this publication.
+     * @return A hint to use for service selection.
+     */
+    String getSiteManagerHint();
+
+    /**
+     * Returns the publication template instantiator hint. If the publication does not allow
+     * templating, <code>null</code> is returned.
+     * @return A hint to use for service selection.
+     */
+    String getInstantiatorHint();
+
+    /**
+     * Returns the proxy which is used for a particular document.
+     * @param document The document.
+     * @param isSslProtected A boolean value.
+     * @return A proxy or <code>null</code> if no proxy is defined for this version.
+     * @throws RepositoryException if an error occurs.
+     */
+    Proxy getProxy(Document document, boolean isSslProtected) throws RepositoryException;
+
+    /**
+     * @return The templates of the publication.
+     */
+    String[] getTemplateIds();
+
+    /**
+     * @param documentType The document type.
+     * @return The workflow schema to use for this document type or <code>null</code> if no
+     *         workflow is registered for this document type.
+     */
+    String getWorkflowSchema(DocumentType documentType);
+
+    /**
+     * @return The resource types that are supported by this publication.
+     */
+    String[] getResourceTypeNames();
     
+    /**
+     * @return The session.
+     * @throws RepositoryException if an error occurs.
+     */
+    Session getSession() throws RepositoryException;
+
 }
diff --git a/src/java/org/apache/lenya/cms/repo/Session.java b/src/java/org/apache/lenya/cms/repo/Session.java
index df4cff8..119cb03 100644
--- a/src/java/org/apache/lenya/cms/repo/Session.java
+++ b/src/java/org/apache/lenya/cms/repo/Session.java
@@ -48,6 +48,12 @@
      * Saves the session.
      * @throws RepositoryException if an error occurs.
      */
-    public void save() throws RepositoryException;
+    void save() throws RepositoryException;
+    
+    /**
+     * @return The repository this session belongs to.
+     * @throws RepositoryException if an error occurs.
+     */
+    Repository getRepository() throws RepositoryException;
     
 }
diff --git a/src/java/org/apache/lenya/cms/repo/Site.java b/src/java/org/apache/lenya/cms/repo/Site.java
index 7fcfc11..2bedc7e 100644
--- a/src/java/org/apache/lenya/cms/repo/Site.java
+++ b/src/java/org/apache/lenya/cms/repo/Site.java
@@ -35,11 +35,11 @@
 
     /**
      * @param name The name.
-     * @param contentNode The content node which the site node refers to.
+     * @param document The document which the site node refers to.
      * @return a site node.
      * @throws RepositoryException if a node with this path already exists.
      */
-    SiteNode addChild(String name, ContentNode contentNode) throws RepositoryException;
+    SiteNode addChild(String name, Document document) throws RepositoryException;
 
     /**
      * @param name The name.
@@ -69,5 +69,19 @@
      *             does not exist.
      */
     void move(String srcAbsPath, String destAbsPath) throws RepositoryException;
+    
+    /**
+     * @param document A document.
+     * @return The nodes referencing the document.
+     * @throws RepositoryException if an error occurs.
+     */
+    SiteNode[] getReferences(Document document) throws RepositoryException;
+    
+    /**
+     * @param document A document.
+     * @return The first node referencing the document or <code>null</code> if the document is not referenced.
+     * @throws RepositoryException if an error occurs.
+     */
+    SiteNode getFirstReference(Document document) throws RepositoryException;
 
 }
diff --git a/src/java/org/apache/lenya/cms/repo/SiteNode.java b/src/java/org/apache/lenya/cms/repo/SiteNode.java
index f2bc55a..430fe6f 100644
--- a/src/java/org/apache/lenya/cms/repo/SiteNode.java
+++ b/src/java/org/apache/lenya/cms/repo/SiteNode.java
@@ -48,11 +48,11 @@
 
     /**
      * @param name The name.
-     * @param contentNode The content node which the site node refers to.
+     * @param document The document which the site node refers to.
      * @return a site node.
      * @throws RepositoryException if an error occurs.
      */
-    SiteNode addChild(String name, ContentNode contentNode) throws RepositoryException;
+    SiteNode addChild(String name, Document document) throws RepositoryException;
     
     /**
      * @return The path of the node, relative to the area.
@@ -61,10 +61,10 @@
     String getPath() throws RepositoryException;
     
     /**
-     * @return The referenced content node.
+     * @return The referenced document.
      * @throws RepositoryException if an error occurs.
      */
-    ContentNode getContentNode() throws RepositoryException;
+    Document getDocument() throws RepositoryException;
     
     /**
      * @return The parent node or <code>null</code> if this is a top-level node.
diff --git a/src/java/org/apache/lenya/cms/repo/impl/AbstractPublication.java b/src/java/org/apache/lenya/cms/repo/impl/AbstractPublication.java
new file mode 100644
index 0000000..af585c4
--- /dev/null
+++ b/src/java/org/apache/lenya/cms/repo/impl/AbstractPublication.java
@@ -0,0 +1,284 @@
+/*
+ * 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.lenya.cms.repo.impl;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.DefaultConfigurationBuilder;
+import org.apache.avalon.framework.logger.ConsoleLogger;
+import org.apache.avalon.framework.logger.LogEnabled;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.lenya.cms.proxy.Proxy;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.DocumentType;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.RepositoryException;
+
+/**
+ * Abstract publication implementation.
+ */
+public abstract class AbstractPublication implements Publication, LogEnabled {
+
+    private ArrayList languages = new ArrayList();
+    private String defaultLanguage = null;
+    private String instantiatorHint = null;
+    private String siteManagerName = null;
+
+    public String getSiteManagerHint() {
+        try {
+            loadConfiguration();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        return this.siteManagerName;
+    }
+
+    public String getInstantiatorHint() {
+        try {
+            loadConfiguration();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        return this.instantiatorHint;
+    }
+
+    public String getDefaultLanguage() {
+        try {
+            loadConfiguration();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        return this.defaultLanguage;
+    }
+
+    public String[] getLanguages() {
+        try {
+            loadConfiguration();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        return (String[]) this.languages.toArray(new String[this.languages.size()]);
+    }
+
+    /**
+     * Loads the configuration.
+     * @throws RepositoryException if an error occurs.
+     */
+    protected void loadConfiguration() throws RepositoryException {
+
+        if (isConfigLoaded) {
+            return;
+        }
+
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Loading configuration for publication [" + getPublicationId() + "]");
+        }
+
+        File configFile = getConfigurationFile();
+
+        if (!configFile.exists()) {
+            getLogger().error("Config file [" + configFile.getAbsolutePath() + "] does not exist: ",
+                    new RuntimeException());
+            throw new RuntimeException("The configuration file [" + configFile
+                    + "] does not exist!");
+        } else {
+            getLogger().debug("Configuration file [" + configFile + "] exists.");
+        }
+
+        DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
+
+        Configuration config;
+
+        try {
+            config = builder.buildFromFile(configFile);
+
+            Configuration[] _languages = config.getChild(LANGUAGES).getChildren();
+            for (int i = 0; i < _languages.length; i++) {
+                Configuration languageConfig = _languages[i];
+                String language = languageConfig.getValue();
+                this.languages.add(language);
+                if (languageConfig.getAttribute(DEFAULT_LANGUAGE_ATTR, null) != null) {
+                    this.defaultLanguage = language;
+                }
+            }
+
+            Configuration siteManagerConfiguration = config.getChild(ELEMENT_SITE_MANAGER, false);
+            if (siteManagerConfiguration != null) {
+                this.siteManagerName = siteManagerConfiguration.getAttribute(ATTRIBUTE_NAME);
+            }
+
+            Configuration[] proxyConfigs = config.getChildren(ELEMENT_PROXY);
+            for (int i = 0; i < proxyConfigs.length; i++) {
+                String url = proxyConfigs[i].getAttribute(ATTRIBUTE_URL);
+                String ssl = proxyConfigs[i].getAttribute(ATTRIBUTE_SSL);
+                String area = proxyConfigs[i].getAttribute(ATTRIBUTE_AREA);
+
+                Proxy proxy = new Proxy();
+                proxy.setUrl(url);
+
+                Object key = getProxyKey(area, Boolean.valueOf(ssl).booleanValue());
+                this.areaSsl2proxy.put(key, proxy);
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("Adding proxy: [" + proxy + "] for area=[" + area + "] SSL=["
+                            + ssl + "]");
+                }
+            }
+
+            Configuration templatesConfig = config.getChild(ELEMENT_TEMPLATES);
+            if (templatesConfig != null) {
+                Configuration[] templateConfigs = templatesConfig.getChildren(ELEMENT_TEMPLATE);
+                this.templates = new String[templateConfigs.length];
+                for (int i = 0; i < templateConfigs.length; i++) {
+                    String templateId = templateConfigs[i].getAttribute(ATTRIBUTE_ID);
+                    this.templates[i] = templateId;
+                }
+            }
+
+            Configuration templateInstantiatorConfig = config.getChild(ELEMENT_TEMPLATE_INSTANTIATOR,
+                    false);
+            if (templateInstantiatorConfig != null) {
+                this.instantiatorHint = templateInstantiatorConfig.getAttribute(ATTRIBUTE_NAME);
+            }
+
+            Configuration[] resourceTypeConfigs = config.getChildren(ELEMENT_RESOURCE_TYPE);
+            for (int i = 0; i < resourceTypeConfigs.length; i++) {
+                String name = resourceTypeConfigs[i].getAttribute(ATTRIBUTE_NAME);
+                this.resourceTypes.add(name);
+
+                String workflow = resourceTypeConfigs[i].getAttribute(ATTRIBUTE_WORKFLOW, null);
+                if (workflow != null) {
+                    this.doctype2workflow.put(name, workflow);
+                }
+            }
+
+        } catch (final Exception e) {
+            throw new RuntimeException("Problem with config file: " + configFile.getAbsolutePath(),
+                    e);
+        }
+
+        isConfigLoaded = true;
+    }
+
+    /**
+     * @return The configuration file.
+     */
+    public abstract File getConfigurationFile();
+
+    private static final String ELEMENT_PROXY = "proxy";
+    private static final String ATTRIBUTE_AREA = "area";
+    private static final String ATTRIBUTE_URL = "url";
+    private static final String ATTRIBUTE_SSL = "ssl";
+
+    private boolean isConfigLoaded = false;
+
+    /**
+     * <code>CONFIGURATION_PATH</code> The configuration path
+     */
+    private static String CONFIGURATION_PATH = "config";
+
+    /**
+     * <code>CONFIGURATION_FILE</code> The publication configuration file
+     */
+    protected static final String CONFIGURATION_FILE = CONFIGURATION_PATH + File.separator
+            + "publication.xconf";
+
+    private static final String ELEMENT_TEMPLATES = "templates";
+    private static final String ELEMENT_TEMPLATE = "template";
+    private static final String ATTRIBUTE_ID = "id";
+    private static final String ELEMENT_SITE_MANAGER = "site-manager";
+    private static final String ATTRIBUTE_NAME = "name";
+    private static final String ELEMENT_TEMPLATE_INSTANTIATOR = "template-instantiator";
+    private static final String LANGUAGES = "languages";
+    private static final String DEFAULT_LANGUAGE_ATTR = "default";
+    private static final String ELEMENT_RESOURCE_TYPE = "resource-type";
+    private static final String ATTRIBUTE_WORKFLOW = "workflow";
+
+    private Logger logger;
+
+    public void enableLogging(Logger logger) {
+        this.logger = logger;
+    }
+
+    protected Logger getLogger() {
+        if (this.logger == null) {
+            this.logger = new ConsoleLogger();
+        }
+        return this.logger;
+    }
+
+    private Map areaSsl2proxy = new HashMap();
+
+    /**
+     * Generates a hash key for a area-SSL combination.
+     * @param area The area.
+     * @param isSslProtected If the proxy is assigned for SSL-protected pages.
+     * @return An object.
+     */
+    protected Object getProxyKey(String area, boolean isSslProtected) {
+        return area + ":" + isSslProtected;
+    }
+
+    public Proxy getProxy(Document document, boolean isSslProtected) throws RepositoryException {
+        try {
+            loadConfiguration();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        Object key = getProxyKey(document.getContentNode().getContent().getArea().getAreaID(),
+                isSslProtected);
+        Proxy proxy = (Proxy) this.areaSsl2proxy.get(key);
+
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Resolving proxy for [" + document + "] SSL=[" + isSslProtected + "]");
+            getLogger().debug("Resolved proxy: [" + proxy + "]");
+        }
+
+        return proxy;
+    }
+
+    private String[] templates;
+
+    public String[] getTemplateIds() {
+        try {
+            loadConfiguration();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        List list = Arrays.asList(this.templates);
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+
+    private Map doctype2workflow = new HashMap();
+
+    public String getWorkflowSchema(DocumentType docType) {
+        String workflow = (String) this.doctype2workflow.get(docType.getName());
+        return workflow;
+    }
+
+    private List resourceTypes = new ArrayList();
+
+    public String[] getResourceTypeNames() {
+        return (String[]) resourceTypes.toArray(new String[resourceTypes.size()]);
+    }
+
+}
diff --git a/src/java/org/apache/lenya/cms/repo/impl/RepositoryUtil.java b/src/java/org/apache/lenya/cms/repo/impl/RepositoryUtil.java
new file mode 100644
index 0000000..d56f644
--- /dev/null
+++ b/src/java/org/apache/lenya/cms/repo/impl/RepositoryUtil.java
@@ -0,0 +1,125 @@
+/*
+ * 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.lenya.cms.repo.impl;
+
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.publication.URLInformation;
+import org.apache.lenya.cms.repo.Area;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.Repository;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.SiteNode;
+import org.apache.lenya.cms.repo.avalon.RepositoryFactory;
+import org.apache.lenya.util.ServletHelper;
+
+/**
+ * Repository utility class.
+ */
+public class RepositoryUtil {
+
+    /**
+     * @param manager The service manager.
+     * @param request The request object.
+     * @param logger The logger to use.
+     * @return A session.
+     */
+    public static Session getSession(ServiceManager manager, Request request, Logger logger) {
+        Session session = (Session) request.getAttribute(Session.class.getName());
+        if (session == null) {
+
+            RepositoryFactory factory = null;
+            try {
+                factory = (RepositoryFactory) manager.lookup(RepositoryFactory.ROLE);
+                Repository repository = factory.getRepository();
+                session = repository.createSession();
+                request.setAttribute(Session.class.getName(), session);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            } finally {
+                if (factory != null) {
+                    manager.release(factory);
+                }
+            }
+
+        }
+        return session;
+    }
+
+    /**
+     * @param session The session.
+     * @param webappUrl The web application URL.
+     * @return The document represented by the URL.
+     * @throws RepositoryException if an error occurs.
+     */
+    public static Document getDocument(Session session, String webappUrl)
+            throws RepositoryException {
+
+        URLInformation info = new URLInformation(webappUrl);
+        Publication pub = session.getPublication(info.getPublicationId());
+        Area area = pub.getArea(info.getArea());
+
+        String path = "";
+        final String docUrl = info.getDocumentUrl();
+        int firstDotIndex = docUrl.indexOf(".");
+        if (firstDotIndex > 0) {
+            path = docUrl.substring(0, firstDotIndex);
+        } else {
+            path = docUrl;
+        }
+        SiteNode siteNode = area.getSite().getNode(path);
+
+        Document document = null;
+        if (siteNode != null) {
+            document = siteNode.getDocument();
+        }
+        return document;
+    }
+
+    /**
+     * @param manager The service manager.
+     * @param request The request.
+     * @param logger The logger.
+     * @return A publication.
+     * @throws RepositoryException if an error occurs.
+     */
+    public static Publication getPublication(ServiceManager manager, Request request, Logger logger)
+            throws RepositoryException {
+        Session session = getSession(manager, request, logger);
+        String url = ServletHelper.getWebappURI(request);
+        String pubId = new URLInformation(url).getPublicationId();
+        return session.getPublication(pubId);
+    }
+
+    /**
+     * @param manager The service manager.
+     * @param request The request.
+     * @param logger The logger.
+     * @return A document.
+     * @throws RepositoryException if an error occurs.
+     */
+    public static Document getDocument(ServiceManager manager, Request request, Logger logger)
+            throws RepositoryException {
+        Session session = getSession(manager, request, logger);
+        String url = ServletHelper.getWebappURI(request);
+        return getDocument(session, url);
+    }
+
+}
diff --git a/src/java/org/apache/lenya/cms/repo/metadata/ElementSet.java b/src/java/org/apache/lenya/cms/repo/metadata/ElementSet.java
index 7331c15..bb0a6fd 100644
--- a/src/java/org/apache/lenya/cms/repo/metadata/ElementSet.java
+++ b/src/java/org/apache/lenya/cms/repo/metadata/ElementSet.java
@@ -32,4 +32,10 @@
      */
     Element getElement(String name);
     
+    /**
+     * @param name The name.
+     * @return If an element with this name is contained.
+     */
+    boolean contains(String name);
+    
 }
diff --git a/src/java/org/apache/lenya/cms/repo/metadata/MetaData.java b/src/java/org/apache/lenya/cms/repo/metadata/MetaData.java
index d61356d..d6d6ec5 100644
--- a/src/java/org/apache/lenya/cms/repo/metadata/MetaData.java
+++ b/src/java/org/apache/lenya/cms/repo/metadata/MetaData.java
@@ -23,18 +23,52 @@
  */
 public interface MetaData {
     
+    /**
+     * @return The element set these meta data belong to.
+     * @throws RepositoryException if an error occurs.
+     */
     ElementSet getElementSet() throws RepositoryException;
 
+    /**
+     * @param name The element's name.
+     * @return The value.
+     * @throws RepositoryException if an error occurs.
+     */
     String getValue(String name) throws RepositoryException;
     
+    /**
+     * @param name The element's name.
+     * @return The values.
+     * @throws RepositoryException if an error occurs.
+     */
     String[] getValues(String name) throws RepositoryException;
     
+    /**
+     * @param name The element's name.
+     * @param value The value.
+     * @throws RepositoryException if an error occurs.
+     */
     void setValue(String name, String value) throws RepositoryException;
     
+    /**
+     * @param name The element's name.
+     * @param value The value.
+     * @throws RepositoryException if an error occurs.
+     */
     void addValue(String name, String value) throws RepositoryException;
     
+    /**
+     * Removes all values.
+     * @param name The element's name.
+     * @throws RepositoryException if an error occurs.
+     */
     void clear(String name) throws RepositoryException;
     
+    /**
+     * @param name The element's name.
+     * @param value The value.
+     * @throws RepositoryException if an error occurs.
+     */
     void removeValue(String name, String value) throws RepositoryException;
     
 }
diff --git a/src/java/org/apache/lenya/cms/repository/NodeFactory.java b/src/java/org/apache/lenya/cms/repo/metadata/impl/DublinCoreElements.java
similarity index 62%
rename from src/java/org/apache/lenya/cms/repository/NodeFactory.java
rename to src/java/org/apache/lenya/cms/repo/metadata/impl/DublinCoreElements.java
index 346a20b..50ce149 100644
--- a/src/java/org/apache/lenya/cms/repository/NodeFactory.java
+++ b/src/java/org/apache/lenya/cms/repo/metadata/impl/DublinCoreElements.java
@@ -14,24 +14,16 @@
  *  limitations under the License.
  *
  */
-package org.apache.lenya.cms.repository;
-
-import org.apache.lenya.transaction.IdentifiableFactory;
+package org.apache.lenya.cms.repo.metadata.impl;
 
 /**
- * Factory to produce repository nodes.
- * @version $Id:$
+ * Dublin core elements.
  */
-public interface NodeFactory extends IdentifiableFactory {
-
-    /**
-     * The role of the service.
-     */
-    String ROLE = NodeFactory.class.getName();
+public interface DublinCoreElements {
     
     /**
-     * @param session The session.
+     * The name.
      */
-    void setSession(Session session);
+    String NAME = "DublinCoreElements";
 
 }
diff --git a/src/java/org/apache/lenya/cms/repository/NodeFactory.java b/src/java/org/apache/lenya/cms/repo/metadata/impl/DublinCoreTerms.java
similarity index 62%
copy from src/java/org/apache/lenya/cms/repository/NodeFactory.java
copy to src/java/org/apache/lenya/cms/repo/metadata/impl/DublinCoreTerms.java
index 346a20b..5dee990 100644
--- a/src/java/org/apache/lenya/cms/repository/NodeFactory.java
+++ b/src/java/org/apache/lenya/cms/repo/metadata/impl/DublinCoreTerms.java
@@ -14,24 +14,16 @@
  *  limitations under the License.
  *
  */
-package org.apache.lenya.cms.repository;
-
-import org.apache.lenya.transaction.IdentifiableFactory;
+package org.apache.lenya.cms.repo.metadata.impl;
 
 /**
- * Factory to produce repository nodes.
- * @version $Id:$
+ * Dublin core terms.
  */
-public interface NodeFactory extends IdentifiableFactory {
-
-    /**
-     * The role of the service.
-     */
-    String ROLE = NodeFactory.class.getName();
+public interface DublinCoreTerms {
     
     /**
-     * @param session The session.
+     * The name.
      */
-    void setSession(Session session);
+    String NAME = "DublinCoreTerms";
 
 }
diff --git a/src/java/org/apache/lenya/cms/repository/Node.java b/src/java/org/apache/lenya/cms/repository/Node.java
deleted file mode 100644
index 53689ea..0000000
--- a/src/java/org/apache/lenya/cms/repository/Node.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collection;
-
-import org.apache.lenya.cms.metadata.MetaDataOwner;
-
-/**
- * Repository node.
- * 
- * @version $Id$
- */
-public interface Node extends MetaDataOwner {
-    
-    /**
-     * @return The session this node belongs to.
-     */
-    Session getSession();
-
-    /**
-     * The protocol with which to find Lenya nodes
-     */
-    String LENYA_PROTOCOL = "lenya://";
-
-    /**
-     * The identifiable type.
-     */
-    String IDENTIFIABLE_TYPE = "node";
-
-    /**
-     * @return if the node exists.
-     * @throws RepositoryException if an error occurs.
-     */
-    boolean exists() throws RepositoryException;
-
-    /**
-     * @return if the node is a collection.
-     * @throws RepositoryException if an error occurs.
-     */
-    boolean isCollection() throws RepositoryException;
-
-    /**
-     * @return children
-     * @throws RepositoryException if an error occurs.
-     */
-    public Collection getChildren() throws RepositoryException;
-
-    /**
-     * @return The input stream.
-     * @throws RepositoryException if the node does not exist.
-     */
-    InputStream getInputStream() throws RepositoryException;
-
-    /**
-     * @return The output stream.
-     * @throws RepositoryException if the node does not exist.
-     */
-    OutputStream getOutputStream() throws RepositoryException;
-    
-    /**
-     * @return The last modification date.
-     * @throws RepositoryException if the node does not exist.
-     */
-    long getLastModified() throws RepositoryException;
-    
-    /**
-     * @return The content length.
-     * @throws RepositoryException if the node does not exist.
-     */
-    long getContentLength() throws RepositoryException;
-    
-    /**
-     * @return The MIME type.
-     * @throws RepositoryException if the node does not exist.
-     */
-    String getMimeType() throws RepositoryException;
-
-    /**
-     * Accessor for the source URI of this node
-     * @return the source URI
-     */
-    String getSourceURI();
-
-    /**
-     * Locks the node.
-     * @throws RepositoryException if an error occurs.
-     */
-    void lock() throws RepositoryException;
-
-    /**
-     * Unlocks the node.
-     * @throws RepositoryException if an error occurs.
-     */
-    void unlock() throws RepositoryException;
-
-    /**
-     * Checks out the node.
-     * @throws RepositoryException if an error occurs. 
-     */
-    void checkout() throws RepositoryException;
-
-    /**
-     * Checks in the node.
-     * @throws RepositoryException if an error occurs. 
-     */
-    void checkin() throws RepositoryException;
-
-    /**
-     * Registers the node as dirty.
-     * @throws RepositoryException if an error occurs.
-     */
-    void registerDirty() throws RepositoryException;
-
-    /**
-     * @return if the node is checked out.
-     * @throws RepositoryException if an error occurs.
-     */
-    boolean isCheckedOut() throws RepositoryException;
-
-    /**
-     * @return if the node is checked out by the current user.
-     * @throws RepositoryException if an error occurs.
-     */
-    boolean isCheckedOutByUser() throws RepositoryException;
-
-    /**
-     * @return if the node is locked.
-     * @throws RepositoryException if an error occurs.
-     */
-    boolean isLocked() throws RepositoryException;
-
-    /**
-     * Registers the node as removed.
-     * @throws RepositoryException if an error occurs.
-     */
-    void registerRemoved() throws RepositoryException;
-    
-}
diff --git a/src/java/org/apache/lenya/cms/repository/RepositoryException.java b/src/java/org/apache/lenya/cms/repository/RepositoryException.java
deleted file mode 100644
index b8ed639..0000000
--- a/src/java/org/apache/lenya/cms/repository/RepositoryException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-import org.apache.lenya.transaction.TransactionException;
-
-/**
- * Repository exception.
- * @version $Id:$
- */
-public class RepositoryException extends TransactionException {
-
-    /**
-     * Ctor.
-     */
-    public RepositoryException() {
-        super();
-    }
-
-    /**
-     * Ctor.
-     * @param arg0
-     * @param arg1
-     */
-    public RepositoryException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    /**
-     * Ctor.
-     * @param arg0
-     */
-    public RepositoryException(String arg0) {
-        super(arg0);
-    }
-
-    /**
-     * Ctor.
-     * @param arg0
-     */
-    public RepositoryException(Throwable arg0) {
-        super(arg0);
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/repository/RepositoryManager.java b/src/java/org/apache/lenya/cms/repository/RepositoryManager.java
deleted file mode 100644
index c90de6e..0000000
--- a/src/java/org/apache/lenya/cms/repository/RepositoryManager.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-/**
- * Repository manager.
- * @version $Id:$
- */
-public interface RepositoryManager {
-
-    /**
-     * The role of the service.
-     */
-    String ROLE = RepositoryManager.class.getName();
-    
-    /**
-     * Copies a node.
-     * @param source The source node.
-     * @param destination The destination node.
-     * @throws RepositoryException if an error occurs.
-     */
-    void copy(Node source, Node destination) throws RepositoryException;
-    
-    /**
-     * Deletes a node.
-     * @param node The node to delete.
-     * @throws RepositoryException if an error occurs.
-     */
-    void delete(Node node) throws RepositoryException;
-    
-}
diff --git a/src/java/org/apache/lenya/cms/repository/RepositoryManagerImpl.java b/src/java/org/apache/lenya/cms/repository/RepositoryManagerImpl.java
deleted file mode 100644
index c9a0c36..0000000
--- a/src/java/org/apache/lenya/cms/repository/RepositoryManagerImpl.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-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.excalibur.source.SourceResolver;
-import org.apache.lenya.cms.cocoon.source.SourceUtil;
-
-/**
- * Repository manager implementation.
- * @version $Id:$
- */
-public class RepositoryManagerImpl extends AbstractLogEnabled implements RepositoryManager,
-        Serviceable {
-
-    public void copy(Node source, Node destination) throws RepositoryException {
-
-        SourceResolver resolver = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            SourceUtil.copy(resolver, source.getSourceURI(), destination.getSourceURI());
-
-            destination.getMetaDataManager().replaceMetaData(source.getMetaDataManager());
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        } finally {
-            if (resolver != null) {
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    protected ServiceManager manager;
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.RepositoryManager#delete(org.apache.lenya.cms.repository.Node)
-     */
-    public void delete(Node node) throws RepositoryException {
-        if (!node.isLocked()) {
-            throw new RuntimeException("Cannot delete node [" + node + "]: not locked!");
-        } else {
-            node.registerRemoved();
-        }
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/repository/RepositoryUtil.java b/src/java/org/apache/lenya/cms/repository/RepositoryUtil.java
deleted file mode 100644
index 583c1c3..0000000
--- a/src/java/org/apache/lenya/cms/repository/RepositoryUtil.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.cocoon.environment.Request;
-import org.apache.lenya.ac.Identity;
-import org.apache.lenya.transaction.IdentityMapImpl;
-
-public class RepositoryUtil {
-
-    public static Session getSession(Request request, Logger logger) {
-        Session session = (Session) request.getAttribute(Session.class.getName());
-        if (session == null) {
-            org.apache.cocoon.environment.Session cocoonSession = request.getSession();
-            Identity identity = (Identity) cocoonSession.getAttribute(Identity.class.getName());
-            session = new Session(new IdentityMapImpl(logger), identity, logger);
-            request.setAttribute(Session.class.getName(), session);
-        }
-        return session;
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/repository/Session.java b/src/java/org/apache/lenya/cms/repository/Session.java
deleted file mode 100644
index 4ffa0ee..0000000
--- a/src/java/org/apache/lenya/cms/repository/Session.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.lenya.ac.Identity;
-import org.apache.lenya.transaction.IdentityMap;
-import org.apache.lenya.transaction.TransactionException;
-import org.apache.lenya.transaction.UnitOfWork;
-import org.apache.lenya.transaction.UnitOfWorkImpl;
-
-/**
- * Repository session.
- */
-public class Session extends AbstractLogEnabled {
-    
-    /**
-     * Ctor.
-     * @param map The identity map.
-     * @param identity The identity.
-     * @param logger The logger.
-     */
-    public Session(IdentityMap map, Identity identity, Logger logger) {
-        this.unitOfWork = new UnitOfWorkImpl(map, logger);
-        this.unitOfWork.setIdentity(identity);
-        ContainerUtil.enableLogging(this, logger);
-    }
-    
-    private UnitOfWork unitOfWork;
-    
-    /**
-     * @return The unit of work.
-     */
-    public UnitOfWork getUnitOfWork() {
-        return this.unitOfWork;
-    }
-
-    /**
-     * Commits the transaction.
-     * @throws RepositoryException if an error occurs.
-     */
-    public void commit() throws RepositoryException {
-        try {
-            getUnitOfWork().commit();
-        } catch (TransactionException e) {
-            throw new RepositoryException(e);
-        }
-    }
-    
-    /**
-     * Rolls the transaction back.
-     * @throws RepositoryException if an error occurs.
-     */
-    public void rollback() throws RepositoryException {
-        try {
-            getUnitOfWork().rollback();
-        } catch (TransactionException e) {
-            throw new RepositoryException(e);
-        }
-    }
-    
-}
diff --git a/src/java/org/apache/lenya/cms/repository/SourceNode.java b/src/java/org/apache/lenya/cms/repository/SourceNode.java
deleted file mode 100644
index cd3204e..0000000
--- a/src/java/org/apache/lenya/cms/repository/SourceNode.java
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collection;
-
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.logger.Logger;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.excalibur.source.ModifiableSource;
-import org.apache.excalibur.source.Source;
-import org.apache.excalibur.source.SourceNotFoundException;
-import org.apache.excalibur.source.SourceResolver;
-import org.apache.excalibur.source.TraversableSource;
-import org.apache.lenya.ac.Identity;
-import org.apache.lenya.ac.User;
-import org.apache.lenya.cms.cocoon.source.SourceUtil;
-import org.apache.lenya.cms.metadata.MetaDataManager;
-import org.apache.lenya.cms.publication.DocumentException;
-import org.apache.lenya.cms.publication.Publication;
-import org.apache.lenya.cms.publication.PublicationUtil;
-import org.apache.lenya.cms.rc.RCEnvironment;
-import org.apache.lenya.cms.rc.RCMLEntry;
-import org.apache.lenya.cms.rc.RevisionController;
-import org.apache.lenya.transaction.Lock;
-import org.apache.lenya.transaction.TransactionException;
-import org.apache.lenya.transaction.Transactionable;
-
-/**
- * A repository node.
- * 
- * @version $Id$
- */
-public class SourceNode extends AbstractLogEnabled implements Node, Transactionable {
-
-    private String sourceURI;
-    protected ServiceManager manager;
-
-    /**
-     * Ctor.
-     * @param session
-     * @param sourceURI
-     * @param manager
-     * @param logger
-     */
-    public SourceNode(Session session, String sourceURI, ServiceManager manager, Logger logger) {
-        this.sourceURI = sourceURI;
-        this.manager = manager;
-        enableLogging(logger);
-        this.session = session;
-    }
-
-    protected String getUserId() {
-        String userId = null;
-        Identity identity = getSession().getUnitOfWork().getIdentity();
-        if (identity != null) {
-            User user = identity.getUser();
-            if (user != null) {
-                userId = user.getId();
-            }
-        }
-        return userId;
-    }
-
-    /**
-     * Returns the URI of the actual source which is used.
-     * @return A string.
-     */
-    protected String getRealSourceURI() {
-        return "context://" + this.sourceURI.substring(Node.LENYA_PROTOCOL.length());
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#checkin()
-     */
-    public void checkin() throws RepositoryException {
-        if (!isCheckedOut()) {
-            throw new RepositoryException("Cannot check in node [" + this.sourceURI
-                    + "]: not checked out!");
-        }
-
-        try {
-            String userName = getUserId();
-            boolean newVersion = getSession().getUnitOfWork().isDirty(this);
-            getRevisionController().reservedCheckIn(getRCPath(), userName, true, newVersion);
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#isCheckedOut()
-     */
-    public boolean isCheckedOut() throws RepositoryException {
-        try {
-            return getRevisionController().isCheckedOut(getRCPath());
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#isCheckedOutByUser()
-     */
-    public boolean isCheckedOutByUser() throws RepositoryException {
-        try {
-            RCMLEntry entry = getRevisionController().getRCML(getRCPath()).getLatestEntry();
-            if (entry.getIdentity().equals(getUserId()) && isCheckedOut())
-                return true;
-            else
-                return false;
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#checkout()
-     */
-    public void checkout() throws RepositoryException {
-
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("SourceNode::checkout() called, sourceURI [" + sourceURI + "]");
-
-        if (!isCheckedOut()) {
-            try {
-                getRevisionController().reservedCheckOut(getRCPath(), getUserId());
-            } catch (Exception e) {
-                throw new RepositoryException(e);
-            }
-        }
-    }
-
-    /**
-     * @return The path to use for the revision controller.
-     * @throws IOException if an error occurs.
-     */
-    protected String getRCPath() throws IOException {
-        String pubBase = Node.LENYA_PROTOCOL + Publication.PUBLICATION_PREFIX_URI + "/";
-        String publicationsPath = this.sourceURI.substring(pubBase.length());
-        String publicationId = publicationsPath.split("/")[0];
-        String path = pubBase + publicationId + "/";
-        return this.sourceURI.substring(path.length());
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#deleteTransactionable()
-     */
-    public void deleteTransactionable() throws RepositoryException {
-        try {
-            if (!isCheckedOut()) {
-                throw new RuntimeException("Cannot delete source [" + this.sourceURI
-                        + "]: not checked out!");
-            } else {
-                SourceUtil.delete(getRealSourceURI(), this.manager);
-            }
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    private RevisionController revisionController;
-
-    protected RevisionController getRevisionController() throws RepositoryException {
-        if (this.revisionController == null) {
-            try {
-                String pubBase = Node.LENYA_PROTOCOL + Publication.PUBLICATION_PREFIX_URI + "/";
-                String publicationsPath = this.sourceURI.substring(pubBase.length());
-                String publicationId = publicationsPath.split("/")[0];
-
-                Publication pub = PublicationUtil.getPublication(this.manager, publicationId);
-
-                String publicationPath = pub.getDirectory().getCanonicalPath();
-                RCEnvironment rcEnvironment = RCEnvironment.getInstance(pub.getServletContext()
-                        .getCanonicalPath());
-                String rcmlDirectory = publicationPath + File.separator
-                        + rcEnvironment.getRCMLDirectory();
-                String backupDirectory = publicationPath + File.separator
-                        + rcEnvironment.getBackupDirectory();
-                this.revisionController = new RevisionController(rcmlDirectory,
-                        backupDirectory,
-                        publicationPath);
-
-            } catch (Exception e) {
-                throw new RepositoryException(e);
-            }
-        }
-        return this.revisionController;
-    }
-
-    private Lock lock;
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#hasChanged()
-     */
-    public boolean hasChanged() throws RepositoryException {
-        try {
-            int currentVersion = getRevisionController().getLatestVersion(getRCPath());
-            int lockVersion = getLock().getVersion();
-            return currentVersion > lockVersion;
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#saveTransactionable()
-     */
-    public synchronized void saveTransactionable() throws RepositoryException {
-        if (!isCheckedOut()) {
-            throw new RepositoryException("Cannot save node [" + this.sourceURI
-                    + "]: not checked out!");
-        }
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Saving [" + this + "] to source [" + getRealSourceURI() + "]");
-        }
-
-        if (this.data != null) {
-            SourceResolver resolver = null;
-            ModifiableSource source = null;
-            InputStream in = null;
-            OutputStream out = null;
-            try {
-
-                resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-                source = (ModifiableSource) resolver.resolveURI(getRealSourceURI());
-
-                out = source.getOutputStream();
-
-                byte[] buf = new byte[4096];
-                in = new ByteArrayInputStream(this.data);
-                int read = in.read(buf);
-
-                while (read > 0) {
-                    out.write(buf, 0, read);
-                    read = in.read(buf);
-                }
-
-            } catch (Exception e) {
-                throw new RepositoryException(e);
-            } finally {
-
-                try {
-                    if (in != null) {
-                        in.close();
-                    }
-                    if (out != null) {
-                        out.flush();
-                        out.close();
-                    }
-                } catch (Throwable t) {
-                    throw new RuntimeException("Could not close streams: ", t);
-                }
-
-                if (resolver != null) {
-                    if (source != null) {
-                        resolver.release(source);
-                    }
-                    manager.release(resolver);
-                }
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#createTransactionable()
-     */
-    public void createTransactionable() throws RepositoryException {
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#lock()
-     */
-    public void lock() throws RepositoryException {
-        if (isCheckedOut() && !isCheckedOutByUser()) {
-            throw new RepositoryException("Cannot lock [" + this + "]: node is checked out.");
-        }
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Locking [" + this + "]");
-        }
-        int currentVersion;
-        try {
-            currentVersion = getRevisionController().getLatestVersion(getRCPath());
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-        this.lock = new Lock(currentVersion);
-
-        if (!getSourceURI().endsWith(".meta")) {
-            lockMetaData();
-        }
-    }
-
-    protected void lockMetaData() throws RepositoryException {
-        SourceUtil.lock(getMetaSourceURI(), this.manager);
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#getLock()
-     */
-    public Lock getLock() {
-        return this.lock;
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#unlock()
-     */
-    public void unlock() throws RepositoryException {
-        this.lock = null;
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Transactionable#isLocked()
-     */
-    public boolean isLocked() throws RepositoryException {
-        return this.lock != null;
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.Identifiable#getIdentifiableType()
-     */
-    public String getIdentifiableType() {
-        return Node.IDENTIFIABLE_TYPE;
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#exists()
-     */
-    public boolean exists() throws RepositoryException {
-        loadData();
-        return this.data != null;
-    }
-
-    /**
-     * @see java.lang.Object#toString()
-     */
-    public String toString() {
-        return "node " + this.sourceURI;
-    }
-
-    byte[] data = null;
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getInputStream()
-     */
-    public synchronized InputStream getInputStream() throws RepositoryException {
-        if (!exists()) {
-            throw new RuntimeException(this + " does not exist!");
-        }
-        return new ByteArrayInputStream(this.data);
-    }
-
-    /**
-     * 
-     */
-    public Collection getChildren() throws RepositoryException {
-        SourceResolver resolver = null;
-        TraversableSource source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = (TraversableSource) resolver.resolveURI(getRealSourceURI());
-            Collection children = source.getChildren();
-            java.util.Iterator iterator = children.iterator();
-            java.util.Vector newChildren = new java.util.Vector();
-            while (iterator.hasNext()) {
-                TraversableSource child = (TraversableSource) iterator.next();
-                newChildren.add(new SourceNode(getSession(),
-                        sourceURI + "/" + child.getName(),
-                        this.manager,
-                        getLogger()));
-            }
-            return newChildren;
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * 
-     */
-    public boolean isCollection() throws RepositoryException {
-        SourceResolver resolver = null;
-        TraversableSource source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = (TraversableSource) resolver.resolveURI(getRealSourceURI());
-            return source.isCollection();
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    /**
-     * Loads the data from the real source.
-     * @throws RepositoryException if an error occurs.
-     */
-    protected synchronized void loadData() throws RepositoryException {
-
-        if (this.data != null) {
-            return;
-        }
-
-        ByteArrayOutputStream out = null;
-        InputStream in = null;
-        SourceResolver resolver = null;
-        TraversableSource source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = (TraversableSource) resolver.resolveURI(getRealSourceURI());
-
-            if (source.exists() && !source.isCollection()) {
-                byte[] buf = new byte[4096];
-                out = new ByteArrayOutputStream();
-                in = source.getInputStream();
-                int read = in.read(buf);
-
-                while (read > 0) {
-                    out.write(buf, 0, read);
-                    read = in.read(buf);
-                }
-
-                this.data = out.toByteArray();
-            }
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        } finally {
-            try {
-                if (in != null)
-                    in.close();
-                if (out != null)
-                    out.close();
-            } catch (Exception e) {
-                throw new RepositoryException(e);
-            }
-
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getOutputStream()
-     */
-    public synchronized OutputStream getOutputStream() throws RepositoryException {
-        if (getLogger().isDebugEnabled())
-            getLogger().debug("Get OutputStream for " + getSourceURI());
-        try {
-            if (!isLocked()) {
-                throw new RuntimeException("Cannot write to source [" + getSourceURI()
-                        + "]: not locked!");
-            }
-            if (getSession().getUnitOfWork() == null) {
-                throw new RuntimeException("Cannot write to source outside of a transaction (UnitOfWork is null)!");
-            }
-            registerDirty();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-        return new NodeOutputStream();
-    }
-
-    /**
-     * Output stream.
-     */
-    private class NodeOutputStream extends ByteArrayOutputStream {
-        /**
-         * @see java.io.OutputStream#close()
-         */
-        public synchronized void close() throws IOException {
-            SourceNode.this.data = super.toByteArray();
-            super.close();
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getContentLength()
-     */
-    public long getContentLength() throws RepositoryException {
-        SourceResolver resolver = null;
-        Source source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = resolver.resolveURI(getRealSourceURI());
-            if (source.exists()) {
-                return source.getContentLength();
-            } else {
-                throw new SourceNotFoundException("The source [" + getRealSourceURI()
-                        + "] does not exist!");
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getLastModified()
-     */
-    public long getLastModified() throws RepositoryException {
-        SourceResolver resolver = null;
-        Source source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = resolver.resolveURI(getRealSourceURI());
-            if (source.exists()) {
-                return source.getLastModified();
-            } else {
-                throw new RepositoryException("The source [" + getRealSourceURI()
-                        + "] does not exist!");
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getMimeType()
-     */
-    public String getMimeType() throws RepositoryException {
-        SourceResolver resolver = null;
-        Source source = null;
-        try {
-            resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-            source = resolver.resolveURI(getRealSourceURI());
-            if (source.exists()) {
-                return source.getMimeType();
-            } else {
-                throw new SourceNotFoundException("The source [" + getRealSourceURI()
-                        + "] does not exist!");
-            }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (resolver != null) {
-                if (source != null) {
-                    resolver.release(source);
-                }
-                this.manager.release(resolver);
-            }
-        }
-    }
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getSourceURI()
-     */
-    public String getSourceURI() {
-        return sourceURI;
-    }
-
-    protected String getMetaSourceURI() {
-        return getSourceURI() + ".meta";
-    }
-
-    private MetaDataManager metaDataManager;
-
-    /**
-     * @see org.apache.lenya.cms.metadata.MetaDataOwner#getMetaDataManager()
-     */
-    public MetaDataManager getMetaDataManager() throws DocumentException {
-        if (this.metaDataManager == null) {
-            this.metaDataManager = new MetaDataManager(getMetaSourceURI(),
-                    this.manager,
-                    getLogger());
-        }
-        return this.metaDataManager;
-    }
-
-    private Session session;
-
-    /**
-     * @see org.apache.lenya.cms.repository.Node#getSession()
-     */
-    public Session getSession() {
-        return this.session;
-    }
-
-    public void registerDirty() throws RepositoryException {
-        try {
-            getSession().getUnitOfWork().registerDirty(this);
-        } catch (TransactionException e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-    public void registerRemoved() throws RepositoryException {
-        try {
-            getSession().getUnitOfWork().registerRemoved(this);
-            SourceUtil.delete(getMetaSourceURI(), this.manager);
-        } catch (Exception e) {
-            throw new RepositoryException(e);
-        }
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/repository/SourceNodeFactory.java b/src/java/org/apache/lenya/cms/repository/SourceNodeFactory.java
deleted file mode 100644
index 238766d..0000000
--- a/src/java/org/apache/lenya/cms/repository/SourceNodeFactory.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.lenya.cms.repository;
-
-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.lenya.transaction.Identifiable;
-import org.apache.lenya.transaction.IdentityMap;
-
-/**
- * Factory to create source nodes.
- * 
- * @version $Id$
- */
-public class SourceNodeFactory extends AbstractLogEnabled implements NodeFactory, Serviceable,
-        ThreadSafe {
-
-    private ServiceManager manager;
-    private Session session;
-
-    /**
-     * Ctor.
-     */
-    public SourceNodeFactory() {
-    }
-    
-    /**
-     * @param session The session.
-     */
-    public void setSession(Session session) {
-        this.session = session;
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.IdentifiableFactory#build(org.apache.lenya.transaction.IdentityMap,
-     *      java.lang.String)
-     */
-    public Identifiable build(IdentityMap map, String key) throws Exception {
-        if (this.session == null) {
-            throw new RepositoryException("The session has not been set!");
-        }
-        return new SourceNode(this.session, key, this.manager, getLogger());
-    }
-
-    /**
-     * @see org.apache.lenya.transaction.IdentifiableFactory#getType()
-     */
-    public String getType() {
-        return Node.IDENTIFIABLE_TYPE;
-    }
-
-    /**
-     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-     */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-    }
-
-}
diff --git a/src/java/org/apache/lenya/cms/usecase/Usecase.java b/src/java/org/apache/lenya/cms/usecase/Usecase.java
index 66ea45d..f185b03 100644
--- a/src/java/org/apache/lenya/cms/usecase/Usecase.java
+++ b/src/java/org/apache/lenya/cms/usecase/Usecase.java
@@ -19,7 +19,7 @@
 import java.util.List;
 
 import org.apache.cocoon.servlet.multipart.Part;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.repo.Session;
 
 /**
  * Usecase interface.
diff --git a/src/java/org/apache/lenya/cms/workflow/DocumentWorkflowable.java b/src/java/org/apache/lenya/cms/workflow/DocumentWorkflowable.java
index 13c1fcb..1b2c2f2 100644
--- a/src/java/org/apache/lenya/cms/workflow/DocumentWorkflowable.java
+++ b/src/java/org/apache/lenya/cms/workflow/DocumentWorkflowable.java
@@ -29,12 +29,14 @@
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.lenya.ac.Identity;
-import org.apache.lenya.cms.metadata.LenyaMetaData;
-import org.apache.lenya.cms.metadata.MetaData;
-import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.DocumentException;
 import org.apache.lenya.cms.publication.ResourceType;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.repo.ContentNode;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.DocumentType;
+import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.metadata.MetaData;
 import org.apache.lenya.workflow.Version;
 import org.apache.lenya.workflow.Workflow;
 import org.apache.lenya.workflow.Workflowable;
@@ -49,20 +51,15 @@
     /**
      * Ctor.
      * @param manager The service manager.
-     * @param session The repository session.
      * @param document The document.
      * @param logger The logger.
      */
-    public DocumentWorkflowable(ServiceManager manager, Session session, Document document,
-            Logger logger) {
+    public DocumentWorkflowable(ServiceManager manager, Document document, Logger logger) {
         this.document = document;
-        this.session = session;
         this.manager = manager;
         ContainerUtil.enableLogging(this, logger);
     }
 
-    private Session session;
-
     private ServiceManager manager;
 
     /**
@@ -76,7 +73,15 @@
      * @return The repository session.
      */
     public Session getSession() {
-        return session;
+        try {
+            return getDocument().getContentNode()
+                    .getContent()
+                    .getArea()
+                    .getPublication()
+                    .getSession();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     private Document document;
@@ -91,9 +96,13 @@
     protected String getWorkflowSchema() {
         String workflowName = null;
         try {
-            ResourceType doctype = document.getResourceType();
+            ContentNode node = document.getContentNode();
+            DocumentType doctype = node.getDocumentType();
             if (doctype != null) {
-                workflowName = document.getPublication().getWorkflowSchema(doctype);
+                workflowName = node.getContent()
+                        .getArea()
+                        .getPublication()
+                        .getWorkflowSchema(doctype);
             }
         } catch (Exception e) {
             throw new RuntimeException(e);
@@ -109,9 +118,9 @@
     public Version[] getVersions() {
         if (this.versions == null) {
             try {
-                MetaData meta = this.document.getMetaDataManager().getLenyaMetaData();
+                MetaData meta = this.document.getMetaData("workflow");
 
-                String[] versionStrings = meta.getValues(LenyaMetaData.ELEMENT_WORKFLOW_VERSION);
+                String[] versionStrings = meta.getValues("version");
                 this.versions = new Version[versionStrings.length];
                 for (int i = 0; i < versionStrings.length; i++) {
                     String string = versionStrings[i];
@@ -123,7 +132,7 @@
                     this.versions[number] = version;
                 }
 
-            } catch (DocumentException e) {
+            } catch (RepositoryException e) {
                 throw new RuntimeException();
             }
         }
@@ -157,10 +166,9 @@
 
         String string = number + " " + encodeVersion(workflow, version);
         try {
-            MetaData meta = this.document.getMetaDataManager().getLenyaMetaData();
-            meta.addValue(LenyaMetaData.ELEMENT_WORKFLOW_VERSION, string);
-            meta.save();
-        } catch (DocumentException e) {
+            MetaData meta = this.document.getMetaData("workflow");
+            meta.addValue("version", string);
+        } catch (RepositoryException e) {
             throw new RuntimeException(e);
         }
     }
diff --git a/src/java/org/apache/lenya/cms/workflow/WorkflowUtil.java b/src/java/org/apache/lenya/cms/workflow/WorkflowUtil.java
index 53bded8..9a7b226 100644
--- a/src/java/org/apache/lenya/cms/workflow/WorkflowUtil.java
+++ b/src/java/org/apache/lenya/cms/workflow/WorkflowUtil.java
@@ -19,9 +19,9 @@
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.util.DocumentSet;
-import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.cms.repo.Document;
+import org.apache.lenya.cms.repo.Session;
 import org.apache.lenya.workflow.Workflow;
 import org.apache.lenya.workflow.WorkflowException;
 import org.apache.lenya.workflow.WorkflowManager;
diff --git a/src/modules/jackrabbit/java/src/org/apache/lenya/cms/jcr/jackrabbit/JackrabbitRepositoryFactory.java b/src/modules/jackrabbit/java/src/org/apache/lenya/cms/jcr/jackrabbit/JackrabbitRepositoryFactory.java
index 7f4a043..7d130e0 100644
--- a/src/modules/jackrabbit/java/src/org/apache/lenya/cms/jcr/jackrabbit/JackrabbitRepositoryFactory.java
+++ b/src/modules/jackrabbit/java/src/org/apache/lenya/cms/jcr/jackrabbit/JackrabbitRepositoryFactory.java
@@ -42,7 +42,7 @@
             File configFile = new File(repoDirectory, configFilePath);
             RepositoryConfig repoConfig = RepositoryConfig.create(configFile.getAbsolutePath(),
                     repoDirectory.getAbsolutePath());
-            JCRRepository repo = new JCRRepository(RepositoryImpl.create(repoConfig));
+            JCRRepository repo = new JCRRepository(RepositoryImpl.create(repoConfig), webappDirectory);
 
             return repo;
         } catch (Exception e) {
diff --git a/src/modules/jackrabbit/repository/repository/nodetypes/custom_nodetypes.xml b/src/modules/jackrabbit/repository/repository/nodetypes/custom_nodetypes.xml
index 774c74b..62503b7 100644
--- a/src/modules/jackrabbit/repository/repository/nodetypes/custom_nodetypes.xml
+++ b/src/modules/jackrabbit/repository/repository/nodetypes/custom_nodetypes.xml
@@ -185,7 +185,7 @@
       <supertype>mix:lockable</supertype>
       <supertype>lnt:mappable</supertype>
     </supertypes>
-    <propertyDefinition name="lenya:contentNode" mandatory="false" autoCreate="false" multiple="false" onParentVersion="ABORT"
+    <propertyDefinition name="lenya:document" mandatory="false" autoCreate="false" multiple="false" onParentVersion="ABORT"
       protected="false" requiredType="Reference"/>
     <childNodeDefinition name="*" defaultPrimaryType="lnt:siteNode" autoCreate="false" mandatory="false"
       onParentVersion="ABORT" protected="false" sameNameSiblings="false">
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/AreaProxy.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/AreaProxy.java
index 7ff4410..59992bb 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/AreaProxy.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/AreaProxy.java
@@ -22,6 +22,7 @@
 import org.apache.lenya.cms.jcr.mapping.PropertyPathElement;
 import org.apache.lenya.cms.repo.Area;
 import org.apache.lenya.cms.repo.Content;
+import org.apache.lenya.cms.repo.Publication;
 import org.apache.lenya.cms.repo.RepositoryException;
 import org.apache.lenya.cms.repo.Site;
 
@@ -91,4 +92,8 @@
         return getPropertyString(ID_PROPERTY);
     }
 
+    public Publication getPublication() throws RepositoryException {
+        return getRepository().getRepositorySession().getPublication(getPublicationId());
+    }
+
 }
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/ContentNodeProxy.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/ContentNodeProxy.java
index 691fcb1..b9dd280 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/ContentNodeProxy.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/ContentNodeProxy.java
@@ -20,6 +20,7 @@
 import org.apache.lenya.cms.jcr.mapping.NamePathElement;
 import org.apache.lenya.cms.jcr.mapping.Path;
 import org.apache.lenya.cms.jcr.mapping.PathElement;
+import org.apache.lenya.cms.repo.Content;
 import org.apache.lenya.cms.repo.ContentNode;
 import org.apache.lenya.cms.repo.Document;
 import org.apache.lenya.cms.repo.DocumentType;
@@ -115,4 +116,8 @@
         setProperty(DOCUMENT_TYPE_PROPERTY, documentType);
     }
 
+    public Content getContent() throws RepositoryException {
+        return (Content) getParentProxy();
+    }
+
 }
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRPublication.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRPublication.java
index 5b6d090..095a56e 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRPublication.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRPublication.java
@@ -16,14 +16,17 @@
  */
 package org.apache.lenya.cms.jcr;
 
+import java.io.File;
+
 import org.apache.lenya.cms.repo.Area;
-import org.apache.lenya.cms.repo.Publication;
 import org.apache.lenya.cms.repo.RepositoryException;
+import org.apache.lenya.cms.repo.Session;
+import org.apache.lenya.cms.repo.impl.AbstractPublication;
 
 /**
  * JCR publication.
  */
-public class JCRPublication implements Publication {
+public class JCRPublication extends AbstractPublication {
 
     private String pubId;
     private JCRSession session;
@@ -42,20 +45,44 @@
         return this.pubId;
     }
 
-    protected JCRSession getSession() {
+    public Session getSession() {
+        return this.session;
+    }
+
+    protected JCRSession getJCRSession() {
         return this.session;
     }
 
     public Area getArea(String area) throws RepositoryException {
-        return getSession().getArea(this, area);
+        return getJCRSession().getArea(this, area);
     }
 
     public Area addArea(String area) throws RepositoryException {
-        return getSession().addArea(this, area);
+        return getJCRSession().addArea(this, area);
     }
 
     public boolean existsArea(String area) throws RepositoryException {
-        return getSession().existsArea(this, area);
+        return getJCRSession().existsArea(this, area);
+    }
+
+    public Area[] getAreas() throws RepositoryException {
+        return getJCRSession().getAreas(this);
+    }
+
+    /**
+     * @return The configuration file (publication.xconf).
+     */
+    public File getConfigurationFile() {
+        JCRRepository repo;
+        try {
+            repo = (JCRRepository) getSession().getRepository();
+        } catch (RepositoryException e) {
+            throw new RuntimeException(e);
+        }
+        String pubPath = ("lenya/pubs/" + getPublicationId()).replace('/', File.separatorChar);
+        File pubDir = new File(repo.getWebappDirectory(), pubPath);
+        File configFile = new File(pubDir, CONFIGURATION_FILE);
+        return configFile;
     }
 
 }
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRRepository.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRRepository.java
index a720018..bef844a 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRRepository.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRRepository.java
@@ -16,6 +16,8 @@
  */
 package org.apache.lenya.cms.jcr;
 
+import java.io.File;
+
 import javax.jcr.Repository;
 
 import org.apache.lenya.cms.repo.DocumentTypeRegistry;
@@ -29,12 +31,16 @@
  */
 public class JCRRepository implements org.apache.lenya.cms.repo.Repository {
 
+    private File webappDirectory;
+    
     /**
      * Ctor.
      * @param repository The repository.
+     * @param webappDirectory The web application directory.
      */
-    public JCRRepository(Repository repository) {
+    public JCRRepository(Repository repository, File webappDirectory) {
         this.repository = repository;
+        this.webappDirectory = webappDirectory;
     }
 
     private Repository repository;
@@ -67,5 +73,9 @@
         }
         return this.metaDataRegistry;
     }
+    
+    protected File getWebappDirectory() {
+        return this.webappDirectory;
+    }
 
 }
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRSession.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRSession.java
index bc26b12..ffab536 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRSession.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/JCRSession.java
@@ -34,6 +34,7 @@
 import org.apache.lenya.cms.jcr.mapping.Path;
 import org.apache.lenya.cms.jcr.mapping.RepositoryFacade;
 import org.apache.lenya.cms.repo.Publication;
+import org.apache.lenya.cms.repo.Repository;
 import org.apache.lenya.cms.repo.RepositoryException;
 
 /**
@@ -51,7 +52,7 @@
 
     private JCRRepository repository;
 
-    protected JCRRepository getRepository() {
+    public Repository getRepository() {
         return this.repository;
     }
 
@@ -71,9 +72,10 @@
                     // create = true;
                 }
 
-                Session session = getRepository().getRepository()
+                Session session = ((JCRRepository) getRepository()).getRepository()
                         .login(new SimpleCredentials("john", "".toCharArray()), area);
-                facade = new RepositoryFacade(session,
+                facade = new RepositoryFacade(this,
+                        session,
                         getRepository().getDocumentTypeRegistry(),
                         getRepository().getMetaDataRegistry());
 
@@ -100,7 +102,7 @@
     protected WorkspaceImpl getDefaultWorkspace() throws LoginException, RepositoryException {
         WorkspaceImpl defaultWorkspace;
         try {
-            Session defaultWorkspaceSession = getRepository().getRepository()
+            Session defaultWorkspaceSession = ((JCRRepository) getRepository()).getRepository()
                     .login(new SimpleCredentials("john", "".toCharArray()));
             defaultWorkspace = (WorkspaceImpl) defaultWorkspaceSession.getWorkspace();
         } catch (javax.jcr.RepositoryException e) {
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteNodeProxy.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteNodeProxy.java
index 3d3c0c8..0c4735e 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteNodeProxy.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteNodeProxy.java
@@ -27,7 +27,7 @@
 import org.apache.lenya.cms.jcr.mapping.NodeProxy;
 import org.apache.lenya.cms.jcr.mapping.Path;
 import org.apache.lenya.cms.jcr.mapping.PathElement;
-import org.apache.lenya.cms.repo.ContentNode;
+import org.apache.lenya.cms.repo.Document;
 import org.apache.lenya.cms.repo.RepositoryException;
 import org.apache.lenya.cms.repo.Site;
 import org.apache.lenya.cms.repo.SiteNode;
@@ -39,7 +39,7 @@
 
     protected static final String NODE_NAME = "lenya:siteNode";
     protected static final String NODE_TYPE = "lnt:siteNode";
-    protected static final String CONTENT_NODE_PROPERTY = "lenya:contentNode";
+    protected static final String DOCUMENT_PROPERTY = "lenya:document";
 
     public SiteNode[] getChildren() throws RepositoryException {
         try {
@@ -59,12 +59,12 @@
         return (SiteNode) getRepository().getProxy(path);
     }
 
-    public SiteNode addChild(String name, ContentNode contentNode) throws RepositoryException {
+    public SiteNode addChild(String name, Document document) throws RepositoryException {
         SiteNodeProxy proxy = (SiteNodeProxy) getRepository().addByName(getAbsolutePath(),
                 SiteNodeProxy.NODE_TYPE,
                 SiteNodeProxy.class.getName(),
                 name);
-        proxy.setContentNode((ContentNodeProxy) contentNode);
+        proxy.setDocument((DocumentProxy) document);
         return proxy;
     }
 
@@ -78,18 +78,13 @@
         return site.getAbsolutePath().append(getPathElement(getName()));
     }
 
-    public ContentNode getContentNode() throws RepositoryException {
-        try {
-            Node node = getPropertyNode(CONTENT_NODE_PROPERTY);
-            String id = node.getUUID();
-            return getSite().getArea().getContent().getNode(id);
-        } catch (javax.jcr.RepositoryException e) {
-            throw new RepositoryException(e);
-        }
+    public Document getDocument() throws RepositoryException {
+        Node node = getPropertyNode(DOCUMENT_PROPERTY);
+        return (Document) getRepository().getProxy(node);
     }
 
-    protected void setContentNode(ContentNodeProxy proxy) throws RepositoryException {
-        setProperty(CONTENT_NODE_PROPERTY, proxy.getNode());
+    protected void setDocument(DocumentProxy proxy) throws RepositoryException {
+        setProperty(DOCUMENT_PROPERTY, proxy.getNode());
     }
 
     public SiteNode getParent() throws RepositoryException {
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteProxy.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteProxy.java
index cc080f7..a53add9 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteProxy.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/SiteProxy.java
@@ -20,6 +20,9 @@
 import java.util.Arrays;
 import java.util.List;
 
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
 import javax.jcr.Session;
 
 import org.apache.lenya.cms.jcr.mapping.AbstractNodeProxy;
@@ -27,7 +30,7 @@
 import org.apache.lenya.cms.jcr.mapping.Path;
 import org.apache.lenya.cms.jcr.mapping.PathElement;
 import org.apache.lenya.cms.repo.Area;
-import org.apache.lenya.cms.repo.ContentNode;
+import org.apache.lenya.cms.repo.Document;
 import org.apache.lenya.cms.repo.RepositoryException;
 import org.apache.lenya.cms.repo.Site;
 import org.apache.lenya.cms.repo.SiteNode;
@@ -54,12 +57,12 @@
         return (SiteNode[]) nodes.toArray(new SiteNode[nodes.size()]);
     }
 
-    public SiteNode addChild(String name, ContentNode contentNode) throws RepositoryException {
+    public SiteNode addChild(String name, Document document) throws RepositoryException {
         SiteNodeProxy proxy = (SiteNodeProxy) getRepository().addByName(getAbsolutePath(),
                 SiteNodeProxy.NODE_TYPE,
                 SiteNodeProxy.class.getName(),
                 name);
-        proxy.setContentNode((ContentNodeProxy) contentNode);
+        proxy.setDocument((DocumentProxy) document);
         return proxy;
     }
 
@@ -105,4 +108,34 @@
         }
     }
 
+    public SiteNode[] getReferences(Document document) throws RepositoryException {
+        List siteNodes = new ArrayList();
+        DocumentProxy proxy = (DocumentProxy) document;
+
+        try {
+            for (PropertyIterator references = proxy.getNode().getReferences(); references.hasNext();) {
+                Property property = references.nextProperty();
+                Node node = property.getParent();
+                if (node.isNodeType(SiteNodeProxy.NODE_TYPE)) {
+                    SiteNode siteNode = (SiteNode) getRepository().getProxy(node);
+                    siteNodes.add(siteNode);
+                }
+            }
+        } catch (javax.jcr.RepositoryException e) {
+            throw new RepositoryException(e);
+        }
+
+        return (SiteNode[]) siteNodes.toArray(new SiteNode[siteNodes.size()]);
+    }
+
+    public SiteNode getFirstReference(Document document) throws RepositoryException {
+        SiteNode[] nodes = getReferences(document);
+        if (nodes.length > 0) {
+            return nodes[0];
+        }
+        else {
+            return null;
+        }
+    }
+
 }
diff --git a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/mapping/RepositoryFacade.java b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/mapping/RepositoryFacade.java
index 784987a..98e7b7f 100644
--- a/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/mapping/RepositoryFacade.java
+++ b/src/modules/jcr/java/src/org/apache/lenya/cms/jcr/mapping/RepositoryFacade.java
@@ -20,6 +20,7 @@
 import javax.jcr.Session;
 import javax.jcr.query.InvalidQueryException;
 
+import org.apache.lenya.cms.jcr.JCRSession;
 import org.apache.lenya.cms.jcr.util.Assertion;
 import org.apache.lenya.cms.repo.DocumentTypeRegistry;
 import org.apache.lenya.cms.repo.RepositoryException;
@@ -32,21 +33,31 @@
 
     /**
      * Ctor.
+     * @param jcrSession The repo session.
      * @param session The JCR session.
      * @param doctypeRegistry The document type registry.
      * @param metaDataRegistry The meta data registry.
      */
-    public RepositoryFacade(Session session, DocumentTypeRegistry doctypeRegistry,
+    public RepositoryFacade(JCRSession jcrSession, Session session, DocumentTypeRegistry doctypeRegistry,
             MetaDataRegistry metaDataRegistry) {
         this.session = session;
+        this.jcrSession = jcrSession;
         this.doctypeRegistry = doctypeRegistry;
         this.metaDataRegistry = metaDataRegistry;
     }
 
+    private JCRSession jcrSession;
     private Session session;
     private DocumentTypeRegistry doctypeRegistry;
 
     protected String CLASS_PROPERTY = "lnt:className";
+    
+    /**
+     * @return The repo session.
+     */
+    public JCRSession getRepositorySession() {
+        return this.jcrSession;
+    }
 
     /**
      * @return The JCR session.
@@ -239,7 +250,12 @@
 
     }
 
-    protected NodeProxy getProxy(Node node) throws RepositoryException {
+    /**
+     * @param node A JCR node.
+     * @return The corresponding proxy.
+     * @throws RepositoryException if an error occurs.
+     */
+    public NodeProxy getProxy(Node node) throws RepositoryException {
         return createProxy(node);
     }
 
diff --git a/src/webapp/lenya/pubs/default/java/src/org/apache/lenya/defaultpub/cms/usecases/Publish.java b/src/webapp/lenya/pubs/default/java/src/org/apache/lenya/defaultpub/cms/usecases/Publish.java
index 51fb5f7..b38eb38 100644
--- a/src/webapp/lenya/pubs/default/java/src/org/apache/lenya/defaultpub/cms/usecases/Publish.java
+++ b/src/webapp/lenya/pubs/default/java/src/org/apache/lenya/defaultpub/cms/usecases/Publish.java
@@ -30,11 +30,11 @@
 import org.apache.cocoon.environment.Request;
 import org.apache.lenya.ac.Identifiable;
 import org.apache.lenya.ac.User;
+import org.apache.lenya.cms.proxy.Proxy;
 import org.apache.lenya.cms.publication.Document;
 import org.apache.lenya.cms.publication.DocumentBuildException;
 import org.apache.lenya.cms.publication.DocumentIdentityMap;
 import org.apache.lenya.cms.publication.DocumentManager;
-import org.apache.lenya.cms.publication.Proxy;
 import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.cms.publication.PublicationException;
 import org.apache.lenya.cms.publication.util.DocumentSet;