org.apache.cocoon.servletservice.util.ServletServiceRequest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.cocoon.servletservice.util.ServletServiceRequest.java

Source

/*
 * 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.servletservice.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.Principal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

import org.apache.cocoon.callstack.CallFrame;
import org.apache.cocoon.callstack.CallStack;
import org.apache.cocoon.callstack.environment.CallFrameHelper;
import org.apache.cocoon.servletservice.ServletServiceContext;
import org.apache.commons.collections.iterators.IteratorEnumeration;

/**
 * <p>
 * Create a {@link HttpServletRequest} from an URL, that is used while calling e.g. a
 * servlet service. The current implementation forwards headers, attributes and
 * parameters.
 * </p>
 *
 * @version $Id: BlockCallHttpServletRequest.java 577519 2007-09-20 03:05:26Z
 *          vgritsenko $
 * @since 1.0.0
 */
public class ServletServiceRequest implements HttpServletRequest {

    /**
     * Protocol of block call requests.
     */
    private static final String PROTOCOL = "HTTP/1.1";

    /**
     * Date header format definied by RFC 822, see
     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3
     */
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z",
            Locale.US);

    /**
     * The <code>parentRequest</code> holds reference to the request object
     * that makes a servlet call.
     */
    private HttpServletRequest parentRequest;

    /**
     * Block call request URI
     */
    private final URI uri;

    /**
     * Request method. If not set via {@link #setMethod(String)}, defaults to
     * <code>GET</code>.
     */
    private String method;

    /**
     * Request headers map
     */
    private final Headers headers;

    /**
     * Request character encoding.
     */
    private String encoding;

    /**
     * Length of the request body.
     */
    private int contentLength;

    /**
     * Request body.
     */
    private ServletInputStream content;

    /**
     * Request attributes map.
     */
    private final Attributes attributes;

    private Parameters parameters;

    private ServletServiceContext context;

    /**
     * @param uri
     *            points to the called servlet
     * @param parentRequest
     *            reference to the request object that makes a servlet call
     */
    public ServletServiceRequest(URI uri, HttpServletRequest parentRequest) {
        this.parentRequest = parentRequest;
        this.uri = uri;
        this.headers = new Headers();
        this.method = "GET";
        this.contentLength = -1;
        this.content = NullServletInputStream.INSTANCE;
        this.attributes = new Attributes();
        this.parameters = new Parameters();
    }

    public String getProtocol() {
        return PROTOCOL;
    }

    public String getMethod() {
        return this.method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    //
    // Request URI parts
    //

    public String getScheme() {
        return this.uri.getScheme();
    }

    public String getServerName() {
        return this.parentRequest.getServerName();
    }

    public int getServerPort() {
        return this.parentRequest.getServerPort();
    }

    public String getContextPath() {
        return this.parentRequest.getContextPath();
    }

    public String getServletPath() {
        // TODO Is this right?
        return "";
    }

    public String getPathInfo() {
        return this.uri.getPath();
    }

    public String getPathTranslated() {
        // TODO This is legal but more info might be possible
        return null;
    }

    public String getQueryString() {
        return this.uri.getQuery();
    }

    public String getRequestURI() {
        // TODO Is this right?
        return this.getContextPath() + this.getServletPath() + this.getPathInfo();
    }

    public StringBuffer getRequestURL() {
        return new StringBuffer(this.getScheme()).append(':').append(this.getRequestURI());
    }

    //
    // Request headers
    //

    public String getHeader(String name) {
        return (String) this.headers.getValue(name);
    }

    public Enumeration getHeaders(String name) {
        return this.headers.getNames();
    }

    public void setHeader(String name, String value) {
        this.headers.setValue(name, value);
    }

    public long getDateHeader(String name) {
        String header = this.getHeader(name);
        if (header == null) {
            return -1;
        }

        try {
            return this.dateFormat.parse(header).getTime();
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public void setDateHeader(String name, long date) {
        this.setHeader(name, this.dateFormat.format(new Date(date)));
    }

    public int getIntHeader(String name) {
        String header = this.getHeader(name);
        if (header == null) {
            return -1;
        }

        return Integer.parseInt(header);
    }

    public void setIntHeader(String name, int value) {
        this.setHeader(name, String.valueOf(value));
    }

    public Enumeration getHeaderNames() {
        return this.headers.getNames();
    }

    //
    // Request parameters
    //

    public String getParameter(String name) {
        return (String) this.parameters.getValue(name);
    }

    public String[] getParameterValues(String name) {
        return this.parameters.getValues(name);
    }

    public Enumeration getParameterNames() {
        return this.parameters.getNames();
    }

    public Map getParameterMap() {
        return this.parameters.getValues();
    }

    //
    // Request body
    //

    public String getCharacterEncoding() {
        return this.encoding;
    }

    public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException {
        this.encoding = encoding;
    }

    public int getContentLength() {
        return this.contentLength;
    }

    public void setContentLength(int contentLength) {
        this.contentLength = contentLength;
    }

    /*
     * TODO Doesn't handle input streams yet
     */
    public String getContentType() {
        return null;
    }

    public ServletInputStream getInputStream() throws IOException {
        return this.content;
    }

    public void setInputStream(final InputStream inputStream) {
        try {
            this.contentLength = inputStream.available();
        } catch (IOException e) {
            this.contentLength = -1;
        }

        this.content = new ServletInputStream() {
            public int read() throws IOException {
                return inputStream.read();
            }
        };
    }

    public BufferedReader getReader() throws IOException {
        Reader reader;
        String encoding = this.getCharacterEncoding();
        if (encoding == null) {
            reader = new InputStreamReader(this.getInputStream());
        } else {
            reader = new InputStreamReader(this.getInputStream(), encoding);
        }

        return new BufferedReader(reader);
    }

    //
    // Request attributes
    //

    public Object getAttribute(String name) {
        return this.attributes.getValue(name);
    }

    public Enumeration getAttributeNames() {
        return this.attributes.getNames();
    }

    public void setAttribute(String name, Object value) {
        if (value != null) {
            this.attributes.setValue(name, value);
        } else {
            this.removeAttribute(name);
        }
    }

    public void removeAttribute(String name) {
        this.attributes.remove(name);
    }

    public String getAuthType() {
        return null;
    }

    public Cookie[] getCookies() {
        return this.parentRequest.getCookies();
    }

    public Locale getLocale() {
        return this.parentRequest.getLocale();
    }

    public Enumeration getLocales() {
        return this.parentRequest.getLocales();
    }

    /**
     * @deprecated
     * @see javax.servlet.ServletRequest#getRealPath(String)
     */
    public String getRealPath(String path) {
        return null;
    }

    public String getRemoteAddr() {
        return this.parentRequest.getRemoteAddr();
    }

    public String getRemoteHost() {
        return this.parentRequest.getRemoteHost();
    }

    public String getRemoteUser() {
        return this.parentRequest.getRemoteUser();
    }

    public RequestDispatcher getRequestDispatcher(String path) {
        return this.context.getRequestDispatcher(path);
    }

    public String getRequestedSessionId() {
        return this.parentRequest.getRequestedSessionId();
    }

    public HttpSession getSession() {
        Session session = (Session) this.getSession(true);
        session.setRequest(this);
        return session;
    }

    public HttpSession getSession(boolean create) {

        HttpServletRequest request = this.parentRequest;
        while (request != null) {
            if (request instanceof ServletServiceRequest) {
                request = ((ServletServiceRequest) request).parentRequest;
            } else {
                break;
            }
        }
        HttpSession outestSession = request.getSession();
        Session session = null;
        // each block's session object is stored in the outest session as an
        // attribute
        if (this != request) {
            session = (Session) outestSession.getAttribute(HttpSession.class + "_" + this.context.getMountPath());
        } else {
            session = (Session) outestSession;
        }

        if (session == null && create) {
            session = new Session(this.context);
            outestSession.setAttribute(HttpSession.class + "_" + this.context.getMountPath(), session);
        }

        if (session != null) {
            session.setRequest(this);
        }

        return session;
    }

    public void setContext(ServletContext context) {
        this.context = (ServletServiceContext) context;
    }

    public Principal getUserPrincipal() {
        return this.parentRequest.getUserPrincipal();
    }

    public boolean isRequestedSessionIdFromCookie() {
        return this.parentRequest.isRequestedSessionIdFromCookie();
    }

    public boolean isRequestedSessionIdFromUrl() {
        return this.isRequestedSessionIdFromURL();
    }

    public boolean isRequestedSessionIdFromURL() {
        return this.parentRequest.isRequestedSessionIdFromURL();
    }

    public boolean isRequestedSessionIdValid() {
        return this.parentRequest.isRequestedSessionIdValid();
    }

    public boolean isSecure() {
        return this.parentRequest.isSecure();
    }

    public boolean isUserInRole(String role) {
        return this.parentRequest.isUserInRole(role);
    }

    public String getLocalAddr() {
        return this.parentRequest.getLocalAddr();
    }

    public String getLocalName() {
        return this.parentRequest.getLocalName();
    }

    public int getLocalPort() {
        return this.parentRequest.getLocalPort();
    }

    public int getRemotePort() {
        return this.parentRequest.getRemotePort();
    }

    private abstract static class Values implements Serializable {

        /** The parameter names are the keys and the value is a List object */
        Map values = new HashMap();

        public Values() {
        }

        protected void setValue(String name, Object value) {
            List list;
            if (this.values.containsKey(name)) {
                list = (List) this.values.get(name);
            } else {
                list = new ArrayList();
                this.values.put(name, list);
            }
            list.add(value);
        }

        public Object getValue(String name) {
            if (this.values.containsKey(name)) {
                return ((List) this.values.get(name)).get(0);
            }

            return this.getValueOfCaller(name);
        }

        protected abstract Object getValueOfCaller(String name);

        protected abstract Enumeration namesOf(HttpServletRequest request);

        public Enumeration getNames() {
            Set names = new HashSet();
            for (int i = 0; i < CallStack.size(); i++) {
                CallFrame frame = CallStack.frameAt(i);
                HttpServletRequest request = (HttpServletRequest) frame
                        .getAttribute(CallFrameHelper.REQUEST_OBJECT);
                if (request instanceof ServletServiceRequest) {
                    names.addAll(this.values.keySet());
                } else {
                    for (Enumeration enumeration = this.namesOf(request); enumeration.hasMoreElements();) {
                        names.add(enumeration.nextElement());
                    }
                }
                if (request.equals(this.getRequest())) {
                    break;
                }
            }

            return new EnumerationFromIterator(names.iterator());
        }

        protected abstract ServletServiceRequest getRequest();

        final class EnumerationFromIterator implements Enumeration {

            private Iterator iterator;

            EnumerationFromIterator(Iterator iter) {
                this.iterator = iter;
            }

            public boolean hasMoreElements() {
                return this.iterator.hasNext();
            }

            public Object nextElement() {
                return this.iterator.next();
            }
        }

    }

    private class Parameters extends Values {

        public Parameters() {
            if (this.getRequest().uri.getQuery() != null) {
                StringTokenizer st = new StringTokenizer(this.getRequest().uri.getQuery(), "&");
                while (st.hasMoreTokens()) {
                    String pair = st.nextToken();
                    int pos = pair.indexOf('=');
                    if (pos != -1) {
                        this.setValue(this.parseName(pair.substring(0, pos)),
                                this.parseName(pair.substring(pos + 1, pair.length())));
                    }
                }
            }
        }

        private String parseName(String s) {
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                switch (c) {
                case '+':
                    sb.append(' ');
                    break;
                case '%':
                    try {
                        if (s.charAt(i + 1) == 'u') {
                            // working with multi-byte symbols in format %uXXXX
                            sb.append((char) Integer.parseInt(s.substring(i + 2, i + 6), 16));
                            i += 5; // 4 digits and 1 symbol u
                        } else {
                            // working with single-byte symbols in format %YY
                            sb.append((char) Integer.parseInt(s.substring(i + 1, i + 3), 16));
                            i += 2;
                        }
                    } catch (NumberFormatException e) {
                        IllegalArgumentException iae = new IllegalArgumentException();
                        iae.initCause(e);
                        throw iae;
                    } catch (StringIndexOutOfBoundsException e) {
                        String rest = s.substring(i);
                        sb.append(rest);
                        if (rest.length() == 2) {
                            i++;
                        }
                    }

                    break;
                default:
                    sb.append(c);
                    break;
                }
            }
            return sb.toString();
        }

        public Map getValues() {
            Map result = new HashMap();
            for (int i = 0; i < CallStack.size(); i++) {
                CallFrame frame = CallStack.frameAt(i);
                HttpServletRequest request = (HttpServletRequest) frame
                        .getAttribute(CallFrameHelper.REQUEST_OBJECT);
                if (request instanceof ServletServiceRequest) {
                    result.putAll(this.values);
                } else {
                    result.putAll(request.getParameterMap());
                }
                if (request.equals(this.getRequest())) {
                    break;
                }
            }

            return result;
        }

        public String[] getValues(String name) {
            List list = (List) this.values.get(name);
            if (list == null) {
                return null;
            }

            String[] result = new String[list.size()];
            for (int i = 0; i < list.size(); i++) {
                result[i] = (String) list.get(i);
            }
            return result;
        }

        protected ServletServiceRequest getRequest() {
            return ServletServiceRequest.this;
        }

        protected Object getValueOfCaller(String name) {
            return this.getRequest().parentRequest.getParameter(name);
        }

        protected Enumeration namesOf(HttpServletRequest request) {
            return request.getParameterNames();
        }

    }

    private class Headers extends Values {

        public Object getValueOfCaller(String name) {
            return this.getRequest().parentRequest.getHeader(name);
        }

        public Enumeration getValues(String name) {
            List list = (List) this.values.get(name);
            if (list == null) {
                return new Enumeration() {

                    public boolean hasMoreElements() {
                        return false;
                    }

                    public Object nextElement() {
                        throw new NoSuchElementException();
                    }

                };
            }

            return new IteratorEnumeration(list.iterator());
        }

        protected ServletServiceRequest getRequest() {
            return ServletServiceRequest.this;
        }

        protected Enumeration namesOf(HttpServletRequest request) {
            return request.getHeaderNames();
        }
    }

    private class Attributes extends Values {

        public Object getValue(String name) {
            if (this.values.containsKey(name)) {
                return this.values.get(name);
            }

            return this.getValueOfCaller(name);
        }

        public Object getValueOfCaller(String name) {
            return this.getRequest().parentRequest.getAttribute(name);
        }

        protected void setValue(String name, Object value) {
            this.values.put(name, value);
        }

        public void remove(String name) {
            if (this.values.containsKey(name)) {
                this.values.remove(name);
            } else {
                this.getRequest().parentRequest.removeAttribute(name);
            }
        }

        protected ServletServiceRequest getRequest() {
            return ServletServiceRequest.this;
        }

        protected Enumeration namesOf(HttpServletRequest request) {
            return request.getAttributeNames();
        }

    }

    private static class Session extends Values implements HttpSession {

        private ServletServiceContext context;

        private transient ServletServiceRequest request;

        public Session(ServletServiceContext context) {
            this.context = context;
        }

        protected Object getValueOfCaller(String name) {
            return this.getRequest().parentRequest.getSession().getAttribute(name);
        }

        protected Enumeration namesOf(HttpServletRequest request) {
            return this.getRequest().parentRequest.getSession().getAttributeNames();
        }

        protected ServletServiceRequest getRequest() {
            return this.request;
        }

        private void setRequest(ServletServiceRequest request) {
            this.request = request;
        }

        public Object getAttribute(String name) {
            if (this.values.containsKey(name)) {
                return this.values.get(name);
            }

            return this.getValueOfCaller(name);
        }

        public Enumeration getAttributeNames() {
            return this.getNames();
        }

        public long getCreationTime() {
            return this.getRequest().parentRequest.getSession().getCreationTime();
        }

        public String getId() {
            return this.getRequest().parentRequest.getSession().getId();
        }

        public long getLastAccessedTime() {
            return this.getRequest().parentRequest.getSession().getLastAccessedTime();
        }

        public int getMaxInactiveInterval() {
            return this.getRequest().parentRequest.getSession().getMaxInactiveInterval();
        }

        public ServletContext getServletContext() {
            return this.context;
        }

        public HttpSessionContext getSessionContext() {
            throw new UnsupportedOperationException();
        }

        public String[] getValueNames() {
            throw new UnsupportedOperationException();
        }

        public void invalidate() {
            this.getRequest().parentRequest.getSession().invalidate();
        }

        public boolean isNew() {
            return this.getRequest().parentRequest.getSession().isNew();
        }

        public void putValue(String name, Object value) {
            this.setValue(name, value);
        }

        public void removeAttribute(String name) {
            this.removeValue(name);
        }

        public void removeValue(String name) {
            this.removeAttribute(name);
        }

        public void setAttribute(String name, Object value) {
            this.setValue(name, value);
        }

        public void setMaxInactiveInterval(int interval) {
            this.getRequest().parentRequest.getSession().setMaxInactiveInterval(interval);
        }

        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // Override the setValue and getValue methods because session attributes
        // are not arrays
        protected void setValue(String name, Object value) {
            this.values.put(name, value);
        }

        public Object getValue(String name) {
            return this.values.get(name);
        }

    }

}