/*
 * 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,v 1.25 2004/03/01 16:18:16 gregor Exp $  */

package org.apache.lenya.cms.publication;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
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.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.SourceUtil;
import org.apache.lenya.cms.publication.file.FilePublication;
import org.apache.lenya.util.ServletHelper;
import org.apache.log4j.Category;

/**
 * Factory for creating publication objects.
 */
public final class PublicationFactory {

    private static Category log = Category.getInstance(PublicationFactory.class);

    /**
     * Create a new <code>PublicationFactory</code>.
     */
    private PublicationFactory() {
    }

    private static Map keyToPublication = new HashMap();

    /**
     * Creates a new publication.
     * The publication ID is resolved from the request URI.
     * The servlet context path is resolved from the context object.
    
     * @param objectModel The object model of the Cocoon component.
     * 
     * @return a <code>Publication</code>
     * 
     * @throws PublicationException if there was a problem creating the publication.
     */
    public static Publication getPublication(Map objectModel) throws PublicationException {

        assert objectModel != null;
        Request request = ObjectModelHelper.getRequest(objectModel);
        Context context = ObjectModelHelper.getContext(objectModel);
        return getPublication(request, context);
    }

    /**
     * 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
     * @param servletContextPath the servlet context path of the publication
     *
     * @return a <code>Publication</code>
     * 
     * @throws PublicationException if there was a problem creating the publication.
     */
    public static Publication getPublication(String id, String servletContextPath)
        throws PublicationException {

        assert id != null;
        assert servletContextPath != null;

        String key = generateKey(id, servletContextPath);
        Publication publication;

        if (keyToPublication.containsKey(key)) {
            publication = (Publication) keyToPublication.get(key);
        } else {
            publication = new FilePublication(id, servletContextPath);
            keyToPublication.put(key, publication);
        }

        assert publication != null;
        return publication;
    }

    /**
     * Generates a key to cache a publication.
     * The cache key is constructed using the canonical servlet context path
     * and the publication ID.
     * 
     * @param publicationId The publication ID.
     * @param servletContextPath The servlet context path.
     * @return A cache key.
     * @throws PublicationException when the servlet context does not exist.
     */
    protected static String generateKey(String publicationId, String servletContextPath)
        throws PublicationException {
        String key;
        File servletContext = new File(servletContextPath);
        String canonicalPath;
        try {
            canonicalPath = servletContext.getCanonicalPath();
        } catch (IOException e) {
            throw new PublicationException(e);
        }
        key = canonicalPath + "_" + publicationId;
        return key;
    }

    /**
     * Creates a new publication based on a request and a context.
     * 
     * @param request A request.
     * @param context A context.
     * 
     * @return A publication.
     * 
     * @throws PublicationException if there was a problem creating the publication.
     */
    public static Publication getPublication(Request request, Context context)
        throws PublicationException {

        log.debug("Creating publication from Cocoon object model");
        String webappUrl = ServletHelper.getWebappURI(request);
        String servletContextPath = context.getRealPath("");
        return getPublication(webappUrl, new File(servletContextPath));
    }

    /**
     * Creates a publication from a webapp URL and a servlet context directory.
     * @param webappUrl The URL within the web application (without context prefix)
     * @param servletContext The Lenya servlet context directory
     * @return A publication
     * @throws PublicationException when something went wrong
     */
    public static Publication getPublication(String webappUrl, File servletContext)
        throws PublicationException {
        log.debug("Creating publication from webapp URL and servlet context");

        log.debug("    Webapp URL:       [" + webappUrl + "]");
        String publicationId = new URLInformation(webappUrl).getPublicationId();
        Publication publication = getPublication(publicationId, servletContext.getAbsolutePath());
        return publication;
    }

    /**
     * Checks if a publication with a certain ID exists in a certain context.
     * @param id The publication ID.
     * @param servletContextPath The webapp context path.
     * @return <code>true</code> if the publication exists, <code>false</code> otherwise.
     */
    public static boolean existsPublication(String id, String servletContextPath) {

        if (servletContextPath.endsWith("/")) {
            servletContextPath = servletContextPath.substring(0, servletContextPath.length() - 1);
        }

        File publicationDirectory =
            new File(
                servletContextPath
                    + File.separator
                    + Publication.PUBLICATION_PREFIX
                    + File.separator
                    + id);

        boolean exists = true;
        exists = exists && publicationDirectory.isDirectory();
        exists = exists && new File(publicationDirectory, Publication.CONFIGURATION_FILE).exists();

        return exists;
    }

    /**
     * Creates a publication using a source resolver and a request.
     * @param resolver The source resolver.
     * @param request The request.
     * @return A publication.
     * @throws PublicationException when something went wrong.
     */
    public static Publication getPublication(SourceResolver resolver, Request request)
        throws PublicationException {
        log.debug("Creating publication from resolver and request");
        Publication publication;
        String webappUri = ServletHelper.getWebappURI(request);
        Source source = null;
        try {
            source = resolver.resolveURI("context:///");
            File servletContext = SourceUtil.getFile(source);
            publication = PublicationFactory.getPublication(webappUri, servletContext);
        } catch (Exception e) {
            throw new PublicationException(e);
        } finally {
            if (source != null) {
                resolver.release(source);
            }
        }
        return publication;
    }
    
}

@@ -667,36 +667,37 @@
  1.2
-5
+6
  2004/0
-3/01 16:18:16 gregor
+5/03 13:52:46 andreas
  Exp
@@ -3057,18 +3057,25 @@
 lication
+ = null
 ;%0A
-
 %0A       
@@ -3200,16 +3200,100 @@
  else %7B%0A
+            if (PublicationFactory.existsPublication(id, servletContextPath)) %7B%0A    
         
@@ -3367,16 +3367,20 @@
         
+    
 keyToPub
@@ -3411,16 +3411,30 @@
 ation);%0A
+            %7D%0A
         
@@ -3428,32 +3428,34 @@
    %7D%0A        %7D%0A%0A
+//
         assert p

return null if publication does not exist