/*
 * Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (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.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.sitenode;

import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.net.*;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;

import junit.framework.*;

import org.apache.cactus.*;
import org.apache.cactus.util.*;

import org.apache.log4j.Logger;

import com.arsdigita.dispatcher.*;
import com.arsdigita.sitenode.*;
import com.arsdigita.initializer.*;

import com.arsdigita.persistence.SessionManager;
import com.arsdigita.persistence.Session;
import com.arsdigita.persistence.TransactionContext;
import com.arsdigita.domain.DataObjectNotFoundException;

import com.arsdigita.kernel.*;

/**
 * This tests the instantiation of a particular package's dispatcher
 * to make sure it instantiated once.  SDM Bug #801
 *
 * @author Anukul Kapoor
 */


public class PackageDispatcherCreationCactusTest extends ServletTestCase {

    public static final String versionId = "$Id: //core-platform/dev/test/src/com/arsdigita/sitenode/PackageDispatcherCreationCactusTest.java#9 $ by $Author: dennis $, $DateTime: 2004/04/07 16:07:11 $";
    HttpServlet s;
    RequestContext rctx;

    public PackageDispatcherCreationCactusTest(String theName) {
        super(theName);
    }


    public static class TestDispatcher implements Dispatcher {

        public static int counter = 0;

        public TestDispatcher() {
            final Logger s_cat = Logger.getLogger(getClass().getName());
            s_cat.debug("construction!");
        }

        public void dispatch(HttpServletRequest req, HttpServletResponse resp,
                             RequestContext reqCtx) {
            final Logger s_cat = Logger.getLogger(getClass().getName());
            counter = 1;
            s_cat.debug("dispatch!");
            return;
        }
    }

    public void setUp() throws Exception {

        final Logger s_cat = Logger.getLogger(getClass().getName());

        Session sm = SessionManager.getSession();
        TransactionContext txn = sm.getTransactionContext();
        txn.beginTxn();
        s_cat.debug("setup: begin txn");

        try {
            PackageType pt = new PackageType();
            pt.setKey("PackageDispatcherTester");
            pt.setPrettyName("Package Dispatcher Tester");
            pt.setPrettyPlural("Package Dispatcher Testers");
            pt.setURI("http://testing.arsdigita.com/package/dispatcher");
            pt.setDispatcherClass(TestDispatcher.class.getName());
            pt.save();

            PackageInstance pkg = pt.createInstance("testDispatch");
            pkg.save();

            SiteNode sn = new SiteNode();
            sn.setName("testDispatch");
            sn.setParent(SiteNode.getRootSiteNode());
            sn.mountPackage(pkg);
            sn.save();

            txn.commitTxn();
            s_cat.debug("commit txn");
        } catch (Exception e) {
            txn.abortTxn();
            s_cat.debug("abort txn");
            throw e;
        }
    }


    public void tearDown() throws Exception {
        Session sm = SessionManager.getSession();
        TransactionContext txn = sm.getTransactionContext();
        txn.beginTxn();

        try {
            SiteNode sn = SiteNode.getSiteNode("/testDispatch");
            sn.delete();

            PackageType pt =
                PackageType.findByKey("PackageDispatcherTester");

            PackageInstanceCollection pic = pt.getInstances();
            PackageInstance pi;

            pic.rewind();
            boolean more = pic.next();
            while (more) {
                pi = pic.getPackageInstance();
                pi.delete();
                more = pic.next();
            }

            pt.delete();
            txn.commitTxn();
        } catch (DataObjectNotFoundException d) {
            txn.abortTxn();
            throw d;
        }
        TestDispatcher.counter = 0;
    }

    public void beginDispatcherCreation(WebRequest req) {
        // host, context path, servlet path, path info, query string
        req.setURL("localhost", "", "", "/testDispatch/", "");
    }


    public void testDispatcherCreation()
        throws javax.servlet.ServletException, java.io.IOException, Throwable {
        final Logger s_cat =
            Logger.getLogger(PackageDispatcherCreationCactusTest.class.getName());

        s_cat.info("PackageDispatcherCreationCactusTest.testDispatcherCreation()");

        s = new SiteNodeDispatcher();

        s.init(config);

        try {
            s_cat.debug(request.toString());
            s_cat.debug("begin request 1");
            s.service(request, response);
            s_cat.debug("end request 1");
            s_cat.debug(request.toString());
            s_cat.debug("begin request 2");

            //      DispatcherHelper.setRequestContext(request, null);
            // FIXME: need to "reset" request and response objects
            // to test dispatcher instantiation across multiple hits

            for(Enumeration e = request.getAttributeNames();
                e.hasMoreElements() ; ) {
                request.removeAttribute((String)e.nextElement());
            }

            s.service(request, response);
            s_cat.debug("begin request 3");

        } catch (ServletException se) {
            Throwable t = se;
            Throwable rootError;
            do {
                rootError = t;
                t = ((ServletException)t).getRootCause();
            } while (t instanceof ServletException);
            if (t != null) {
                rootError = t;
            }
            throw rootError;
        }
        assertEquals(TestDispatcher.counter,1);
    }

}
