/*****************************************************************************
 * Copyright (C) The Apache Software Foundation. All rights reserved.        *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 *****************************************************************************/
package org.apache.cocoon.reading;

import org.apache.avalon.excalibur.pool.Poolable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.parameters.Parameters;
//import org.apache.cocoon.Constants;
import org.apache.cocoon.ProcessingException;
//import org.apache.cocoon.caching.CacheValidity;
//import org.apache.cocoon.caching.Cacheable;
//import org.apache.cocoon.caching.TimeStampCacheValidity;
//import org.apache.cocoon.environment.Context;
import org.apache.cocoon.environment.http.HttpEnvironment;
//import org.apache.cocoon.environment.http.HttpResponse;
//import org.apache.cocoon.environment.http.HttpRequest;
import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.SourceResolver;

import org.apache.cocoon.components.jsp.JSPEngine;

//import org.apache.cocoon.util.HashUtil;
//import org.xml.sax.SAXException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * @author <a href="mailto:kpiroumian@flagship.ru">Konstantin Piroumian</a>
 * @version CVS $Revision: 1.0 $ $Date: 2001/08/28 12:00:00 $
 *
 * The <code>JSPReader</code> component is used to serve JSP page output data
 * in a sitemap pipeline.
 *
 */
public class JSPReader extends AbstractReader
            implements Composable, Poolable {

    private ComponentManager manager;

    public void compose (ComponentManager manager) {
        this.manager = manager;
    }

    /**
     * Generates the output from JSP page.
     */
    public void generate() throws IOException, ProcessingException {
        // ensure that we are running in a servlet environment
        HttpServletResponse httpResponse =
            (HttpServletResponse)this.objectModel.get(HttpEnvironment.HTTP_RESPONSE_OBJECT);
        HttpServletRequest httpRequest =
            (HttpServletRequest)this.objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT);
        ServletContext httpContext =
            (ServletContext)this.objectModel.get(HttpEnvironment.HTTP_SERVLET_CONTEXT);

        if (httpResponse == null || httpRequest == null || httpContext == null) {
            throw new ProcessingException("HttpServletRequest or HttpServletResponse or ServletContext object not available");
        }

        JSPEngine engine = null;
        Source src = null;
        try {
            src = this.resolver.resolve(this.source);
            String url = src.getSystemId();
            // Guarantee src parameter is a file
            getLogger().debug("Reading JSP src from path: " + url);

            if (!url.startsWith("file:")) {
                throw new IOException("Protocol not supported: " + url);
            }
//            if (url.startsWith("file:")) {
                url = url.substring(5);
//            }
            getLogger().debug("JSPReader executing JSP:" + url);

            engine = (JSPEngine)this.manager.lookup(JSPEngine.ROLE);
            byte[] bytes = engine.executeJSP(url, httpRequest, httpResponse, httpContext);

            byte[] buffer = new byte[8192];
            int length = -1;

            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            while ((length = bais.read(buffer)) > -1) {
                out.write(buffer, 0, length);
            }
            bais.close();
            bais = null;
            out.flush();
            //
        } catch (ServletException e) {
            getLogger().debug("ServletException in JSPReader.generate()", e);
            getLogger().debug("Embedded ServletException JSPReader.generate()", e.getRootCause());
            throw new ProcessingException("ServletException in JSPReader.generate()",e.getRootCause());
        } catch (IOException e) {
            getLogger().debug("IOException in JSPReader.generate()", e);
            throw new ProcessingException("IOException JSPReader.generate()",e);
        } catch (ProcessingException e) {
            throw e;
        } catch (Exception e) {
            getLogger().debug("Exception in JSPReader.generate()", e);
            throw new ProcessingException("Exception JSPReader.generate()",e);
        } finally {
            if (src != null) src.recycle();
            if (engine != null) this.manager.release(engine);
        }
    }

}

