ProxyReader.java :  » Web-Framework » cocoon » org » apache » cocoon » portal » reading » Java Open Source

Java Open Source » Web Framework » cocoon 
cocoon » org » apache » cocoon » portal » reading » ProxyReader.java
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.cocoon.portal.reading;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.Map;

import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Response;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.portal.coplet.CopletInstanceData;
import org.apache.cocoon.portal.transformation.ProxyTransformer;
import org.apache.cocoon.reading.ServiceableReader;
import org.apache.cocoon.util.NetUtils;
import org.xml.sax.SAXException;

/**
 * This reader is used to retrieve non XML content from external applications
 * routet via the portal site. Requests from external resources are marked with
 * a proxy prefix and have coplet id and portal name attached as request
 * parameters. The portal name and coplet id are used to look up necessary
 * connection data for the external request (like session id, cookies, 
 * document base, etc.) from the application coplet instance data.
 * 
 * @author <a href="mailto:gernot.koller@rizit.at">Gernot Koller</a>
 * @author <a href="mailto:friedrich.klenner@rzb.at">Friedrich Klenner</a> 
 * 
 * @version CVS $Id: ProxyReader.java 433543 2006-08-22 06:22:54Z crossley $
 */
public class ProxyReader extends ServiceableReader {

    /**
     * The coplet instance data
     */
    protected CopletInstanceData copletInstanceData;

    /**
     * The HTTP response
     */
    protected Response response;

    /**
     * The origninal HTTP request
     */
    protected Request request;

    /** The prefix */
    protected String prefix;
    
    /**
     * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(SourceResolver, Map, String, Parameters)
     */
    public void setup(SourceResolver resolver,
                      Map objectModel,
                      String src,
                      Parameters par)
    throws ProcessingException, SAXException, IOException {
        super.setup(resolver, objectModel, src, par);

        request = ObjectModelHelper.getRequest(objectModel);
        response = ObjectModelHelper.getResponse(objectModel);

        String copletID = request.getParameter(ProxyTransformer.COPLETID);
        String portalName = request.getParameter(ProxyTransformer.PORTALNAME);

        copletInstanceData =
            ProxyTransformer.getInstanceData(
                this.manager,
                copletID,
                portalName);
        this.prefix = par.getParameter("prefix", ProxyTransformer.PROXY_PREFIX);
    }

    /**
     * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
     */
    public void recycle() {
        this.response = null;
        this.request = null;
        this.copletInstanceData = null;
        super.recycle();
    }

    /**
     * Send the request to the external WebServer
     * @throws IOException on any exception that occures
     * @see org.apache.cocoon.reading.Reader#generate()
     */
    public void generate() throws IOException {
        String link = request.getRequestURI();
        link = link.substring(link.indexOf(this.prefix) + this.prefix.length());

        String documentBase =
            (String) copletInstanceData.getAttribute(
                ProxyTransformer.DOCUMENT_BASE);
        String remoteURI = null;

        remoteURI = ProxyTransformer.resolveURI(link, documentBase);

        HttpURLConnection connection = connect(request, remoteURI);
        copyHeaderFields(connection, response);
        sendData(connection.getInputStream());
    }

    /**
     * Copy the data to the original response stream
     * @param in the response from external request to read from
     * @throws IOException on any exception
     */
    protected void sendData(InputStream in) throws IOException {
        int length = -1;
        byte[] buf = new byte[4096];

        while ((length = in.read(buf)) > -1) {
            out.write(buf, 0, length);
        }
        out.flush();
        in.close();
    }

    /**
     * Establish the HttpURLConnection to the given uri.
     * @param request the original request
     * @param uri the remote uri
     * @return the established HttpURLConnection
     * @throws IOException on any exception
     */
    protected HttpURLConnection connect(Request request, String uri)
        throws IOException {
        String cookie =
            (String) copletInstanceData.getAttribute(ProxyTransformer.COOKIE);

        Enumeration enumeration = request.getParameterNames();

        boolean firstattribute = true;
        StringBuffer query = new StringBuffer();

        while (enumeration.hasMoreElements()) {
            String paramName = (String) enumeration.nextElement();

            if (!paramName.startsWith("cocoon-portal-")) {

                String[] paramValues = request.getParameterValues(paramName);

                for (int i = 0; i < paramValues.length; i++) {
                    if (firstattribute) {
                        query.append('?');
                        firstattribute = false;
                    }
                    else {
                        query.append('&');
                    }

                    query.append(NetUtils.encode(paramName, "utf-8"));
                    query.append('=');
                    query.append(NetUtils.encode(paramValues[i], "utf-8"));

                }
            }
        }

        uri = uri + query.toString();

        URL url = new URL(uri);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setInstanceFollowRedirects(true);

        if (cookie != null) {
            connection.setRequestProperty(ProxyTransformer.COOKIE, cookie);
        }

        connection.connect();

        copletInstanceData.setAttribute(
            ProxyTransformer.COOKIE,
            connection.getHeaderField(ProxyTransformer.COOKIE));

        return connection;
    }

    /**
     * Copy header fields from external response to original response.
     * @param connection the connection to the external resource
     * @param response the original HTTP response.
     */
    private void copyHeaderFields(
        HttpURLConnection connection,
        Response response) {
        String[] fieldNames =
            new String[] {
                "Content-Range",
                "Accept-Ranges",
                "Content-Length",
                "Last-Modified",
                "Content-Type",
                "Expires" };
        for (int i = 0; i < fieldNames.length; i++) {
            String value = connection.getHeaderField(fieldNames[i]);
            if (value != null) {
                response.setHeader(fieldNames[i], value);
            }

        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.