All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.shared_tomahawk.util.ExternalContextUtils Maven / Gradle / Ivy

Go to download

JSF components and utilities that can be used with any JSF implementation. This library is based on the JSF1.1 version of Tomahawk, but with minor source code and build changes to take advantage of JSF2.0 features. A JSF2.0 implementation is required to use this version of the Tomahawk library.

The newest version!
/*
 * 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.myfaces.shared_tomahawk.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.context.ExternalContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * This provides some functionality for determining some things about the
 * native request object that is not provided by JSF.  This class is useful
 * for use in places where Portlet API's may or may not be present and can
 * also provide access to some request-specific items which are not available on
 * the JSF ExternalContext.  If portlet API's are not present, this class simply 
 * handles the Servlet Request type.
 */
public final class ExternalContextUtils
{

    /**
     * Returns true if a particular class relating to the supplied
     * request type is available on the current classpath or false 
     * if it is not.  This class assumes that all containers have a servlet type
     * request available, but the portlet request types are all dependant on the 
     * portlet container being used.
     * 
     * @param type the RequestType to test
     * @return a boolean value of true if the container contains the
     *         request type in the classpath
     * @since 2.0
     */
    public static final boolean isRequestTypeAvailable(RequestType type)
    {
        switch (type)
        {
        case SERVLET:
            return true;

        case ACTION:
        case RENDER:
            return _PORTLET_CONTEXT_CLASS != null;

        case RESOURCE:
        case EVENT:
            return _PORTLET_RENDER_REQUEST_CLASS != null;

        default:
            return false;
        }
    }

    /**
     * Returns true if a particular request type is supported by the
     * container.  For a request type to be supported, the required objects must
     * be on the classpath AND and, in the case of Portlet RequestTypes, an 
     * appropriate bridge must be avaialble which supports those objects.  This
     * means that if the supplied RequestType is RESOURCE, the 
     * javax.portlet.ResourceRequest object must be available on the classpath AND
     * a bridge which supports the Portlet 2.0 specification would also need to be
     * available.
     * 
     * @param type the RequestType to test
     * @return a boolean value of true if the container supports the
     *         current request type
     * @since 2.0
     */
    public static final boolean isRequestTypeSupported(RequestType type)
    {
        switch (type)
        {
        case SERVLET:
            return true;

        case ACTION:
        case RENDER:
            return _PORTLET_10_SUPPORTED;

        case RESOURCE:
        case EVENT:
            return _PORTLET_20_SUPPORTED;

        default:
            return false;
        }
    }
    
    /**
     * Returns the requestType of this ExternalContext.
     * 
     * @param externalContext the current external context
     * @return the appropriate RequestType for this external context
     * @see RequestType
     */
    public static final RequestType getRequestType(ExternalContext externalContext)
    {
        //Stuff is laid out strangely in this class in order to optimize
        //performance.  We want to do as few instanceof's as possible so
        //things are laid out according to the expected frequency of the
        //various requests occurring.
        if(_PORTLET_10_SUPPORTED || _PORTLET_20_SUPPORTED)
        {
            if (_PORTLET_CONTEXT_CLASS.isInstance(externalContext.getContext()))
            {
                //We are inside of a portlet container
                Object request = externalContext.getRequest();
                
                if(_PORTLET_RENDER_REQUEST_CLASS.isInstance(request))
                {
                    return RequestType.RENDER;
                }
                
                if(_PORTLET_RESOURCE_REQUEST_CLASS != null)
                {
                    if(_PORTLET_ACTION_REQUEST_CLASS.isInstance(request))
                    {
                        return RequestType.ACTION;
                    }

                    //We are in a JSR-286 container
                    if(_PORTLET_RESOURCE_REQUEST_CLASS.isInstance(request))
                    {
                        return RequestType.RESOURCE;
                    }
                    
                    return RequestType.EVENT;
                }
                
                return RequestType.ACTION;
            }
        }
        
        return RequestType.SERVLET;
    }

    /**
     * This method is used when a ExternalContext object is not available,
     * like in TomahawkFacesContextFactory.
     * 
     * According to TOMAHAWK-1331, the object context could receive an
     * instance of javax.portlet.PortletContext or javax.portlet.PortletConfig,
     * so we check both cases.
     * 
     * @param context
     * @param request
     * @return
     */
    public static final RequestType getRequestType(Object context, Object request)
    {
        //Stuff is laid out strangely in this class in order to optimize
        //performance.  We want to do as few instanceof's as possible so
        //things are laid out according to the expected frequency of the
        //various requests occurring.

        if(_PORTLET_10_SUPPORTED || _PORTLET_20_SUPPORTED)
        {
            if (_PORTLET_CONFIG_CLASS.isInstance(context) ||
                _PORTLET_CONTEXT_CLASS.isInstance(context))
            {
                //We are inside of a portlet container
                
                if(_PORTLET_RENDER_REQUEST_CLASS.isInstance(request))
                {
                    return RequestType.RENDER;
                }
                
                if(_PORTLET_RESOURCE_REQUEST_CLASS != null)
                {
                    if(_PORTLET_ACTION_REQUEST_CLASS.isInstance(request))
                    {
                        return RequestType.ACTION;
                    }

                    //We are in a JSR-286 container
                    if(_PORTLET_RESOURCE_REQUEST_CLASS.isInstance(request))
                    {
                        return RequestType.RESOURCE;
                    }
                    
                    return RequestType.EVENT;
                }
                
                return RequestType.ACTION;
            }
        }
        
        return RequestType.SERVLET;
    }

    /**
     * Returns the current active session id or null if there is
     * none.  If a session is not already created, this method will create one
     * for you.
     * 
     * @param ec the current external context
     * @return a string containing the requestedSessionId
     */
    public static String getSessionId(ExternalContext ec)
    {
        return getSessionId(ec, true);
    }

    /**
     * Returns the current active session id or null if there is
     * none.
     * 
     * @param ec the current external context
     * @param create create a new session if one is not created
     * @return a string containing the requestedSessionId
     */
    public static String getSessionId(ExternalContext ec, boolean create)
    {
        Object session = ec.getSession(create);
        return (null != session) ? (String) _runMethod(session, "getId") : null;
    }

    /**
     * Returns the session ID for the client, or null if there is none.
     *
     * @param ec the current external context
     * @return a string containing the requestedSessionId
     */
    public static String getRequestedSessionId(ExternalContext ec)
    {
        return (String) _runMethod(ec.getRequest(), "getRequestedSessionId");
    }

    /**
     * Checks if the requested session ID is still valid.
     *
     * @param ec the current external context
     * @return a boolean containing true if the request session is
     *         valid or false if it is not
     */
    public static boolean isRequestedSessionIdValid(ExternalContext ec)
    {
        return (Boolean) _runMethod(ec.getRequest(),
                "isRequestedSessionIdValid");
    }

    /**
     * Returns the contextPath of the ServletContext or null for portlets
     *
     * @param ec the current external context
     * @return a String containing the servletContextPath
     */
    public static String getServletContextPath(ExternalContext ec)
    {
        if (!isPortlet(ec))
        {
            return ((ServletContext) ec.getContext()).getContextPath();
        }
        else
        {
            return null;
        }
    }

    /**
     * Returns the contextPath of the ServletRequest or null for portlet requests
     *
     * @param ec the current external context
     * @return a String containing the request context path
     * @see ExternalContext#getRequestContextPath()
     * 
     * @deprecated use ExternalContext.getRequestContextPath() as of JSF 1.2.  This method
     *             does not appropriately handle portlet environments, but the functionality
     *             is maintained to prevent needing to change the contract.
     */
    @Deprecated
    public static String getRequestContextPath(ExternalContext ec)
    {
        if (!isPortlet(ec))
        {
            return ec.getRequestContextPath();
        }
        else
        {
            return null;
        }
    }

    /**
     * Returns the requestURI of the HttpServletRequest or null for 
     * portlet requests
     *
     * @param ec the current external context
     * @return A string containing the current request uri
     */
    public static String getRequestURI(ExternalContext ec)
    {
        if (!isPortlet(ec))
        {
            return ((HttpServletRequest) ec.getRequest()).getRequestURI();
        }
        else
        {
            return null;
        }
    }

    /**
     * Returns the character encoding or null if there isn't any
     *
     * @param ec the current external context
     * @return a string containing the request's character encoding
     * @see ExternalContext#getRequestCharacterEncoding()
     * 
     * @deprecated replaced by an API in JSF.  Use ExternalContext.getRequestCharacterEncoding()
     */
    @Deprecated
    public static String getCharacterEncoding(ExternalContext ec)
    {
        return ec.getRequestCharacterEncoding();
    }

    /**
     * Returns the name of the underlying context or null if something
     * went wrong in trying to retrieve the context.
     * 
     * @param ec the current external context
     * @return a String containing the context name
     */
    public static String getContextName(ExternalContext ec)
    {
        try
        {
            if (isPortlet(ec))
            {
                return (String) _runMethod(ec.getContext(),
                        "getPortletContextName");
            }
            else
            {
                return ((ServletContext) ec.getContext())
                        .getServletContextName();
            }
        }
        catch (final ClassCastException e)
        {
            _LOG.severe(e.getMessage());
        }
        return null;
    }

    /**
     * Returns the name and version of the underlying servlet container or null if something
     * went wrong in trying to retrieve the context.
     *
     * @param ec the current external context
     * @return a String containing the name and version of the underlying servlet container
     */
    public static String getServerInfo(ExternalContext ec)
    {
        try
        {
            if (isPortlet(ec))
            {
                return (String) _runMethod(ec.getContext(), "getServerInfo");
            }
            else
            {
                return ((ServletContext) ec.getContext()).getServerInfo();
            }
        }
        catch (final ClassCastException e)
        {
            _LOG.severe(e.getMessage());
        }
        return null;
    }

    /**
     * Returns the content length or -1 if the unknown.
     *
     * @param ec the current external context
     * @return the length or -1 if the length is unknown
     */
    public static int getContentLength(ExternalContext ec)
    {
        if (isRequestFromClient(ec))
        {
            return (Integer) _runMethod(ec.getRequest(), "getContentLength");
        }

        return -1;
    }

    /**
     * Returns the content type from the current externalContext or
     * null if unknown.
     *
     * @param ec the current external context
     * @return a String contining the the content type or null
     * @see ExternalContext#getRequestContentType()
     *
     * @deprecated use ExternalContext.getRequestContentType()
     */
    @Deprecated
    public static String getContentType(ExternalContext ec)
    {
        return ec.getRequestContentType();
    }

    /**
     * Returns the request input stream if one is available
     *
     * @param ec the current external context
     * @return the request's input stream
     * @throws IOException if there was a problem getting the input stream
     */
    public static InputStream getRequestInputStream(ExternalContext ec)
            throws IOException
    {
        RequestType type = getRequestType(ec);
        if (type.isRequestFromClient())
        {
            Object req = ec.getRequest();
            if (type.isPortlet())
            {
                return (InputStream) _runMethod(req, "getPortletInputStream");
            }
            else
            {
                return ((ServletRequest) ec.getRequest()).getInputStream();
            }
        }

        return null;
    }

    /**
     * Returns true if this externalContext represents an "action". 
     * An action request is any ServletRequest or a portlet ActionRequest or 
     * ResourceRequest.
     *
     * @param ec the current external context
     * @return a boolean of true if this request is an action-type
     *         request.
     * @see #isRequestFromClient(ExternalContext)
     *         
     * @deprecated replaced with {@link #isRequestFromClient(ExternalContext)}
     */
    @Deprecated
    public static boolean isAction(ExternalContext ec)
    {
        return isRequestFromClient(ec);
    }

    /**
     * Returns the value of {@link RequestType#isPortlet()} for the current
     * RequestType. This is a convenience function designed to perform a quick
     * check of the current request. If more capabilities need to be tested for
     * the given request, then it is more efficient to pull this information from
     * the RequestType itself.
     * 
     * @param ec the current external context
     * @return a boolean value of true if the current RequestType
     *         is a portlet request.
     * 
     * @see RequestType#isPortlet()
     * @see #getRequestType(ExternalContext)
     */
    public static boolean isPortlet(ExternalContext ec)
    {
        return getRequestType(ec).isPortlet();
    }

    /**
     * Returns the value of {@link RequestType#isResponseWritable()} for the
     * current RequestType. This is a convenience function designed to perform a
     * quick check of the current request. If more capabilities need to be tested
     * for the given request, then it is more efficient to pull this information
     * from the RequestType itself.
     * 
     * @param ec the current external context
     * @return a boolean value of true if the current RequestType
     *         is a "render" type response.
     * 
     * @see RequestType#isResponseWritable()
     * @see #getRequestType(ExternalContext)
     * @since 2.0
     */
    public static final boolean isResponseWritable(ExternalContext ec)
    {
        return getRequestType(ec).isResponseWritable();
    }

    /**
     * Returns the value of {@link RequestType#isRequestFromClient()} for the
     * current RequestType. This is a convenience function designed to perform a
     * quick check of the current request. If more capabilities need to be tested
     * for the given request, then it is more efficient to pull this information
     * from the RequestType itself.
     * 
     * @param ec the current external context
     * @return a boolean value of true if the current RequestType
     *         represents a request from the client.
     * 
     * @see RequestType#isResponseWritable()
     * @see #getRequestType(ExternalContext)
     * @since 2.0
     */
    public static final boolean isRequestFromClient(ExternalContext ec)
    {
        return getRequestType(ec).isRequestFromClient();
    }

    /**
     * Returns wherther of not this external context represents a true HttpServletRequest or
     * not.  Some portal containers implement the PortletRequest/Response objects as 
     * HttpServletRequestWrappers, and those objects should not be treated as an
     * HttpServlerRequest.  As such, this method first tests to see if the request is
     * a portlet request and, if not, then tests to see if the request is an instanceof
     * HttpServletRequest.
     * 
     * @param ec the current external context
     * @return a boolean value of true if the current request is an
     *         HttpServletRequest
     * @since 1.1
     */
    public static boolean isHttpServletRequest(ExternalContext ec)
    {
        return (!isPortlet(ec) && (ec.getRequest() instanceof HttpServletRequest));
    }

    /**
     * Returns an HttpServletResponse if one exists on the externalContext or null
     * if it does not.  Please note that some portal environments implement the
     * PortletRequest and Response objects as HttpServletRequest/Response objects.
     * This method handles these types of requests properly and will therefore
     * return null in portal environments.
     * 
     * @param response
     * @return an HttpServletResponse if we have one or null if we do not
     * @since 4.0
     */
    public static HttpServletResponse getHttpServletResponse(ExternalContext ec)
    {
        if (isHttpServletRequest(ec))
        {
            return (HttpServletResponse) ec.getResponse();
        }

        return null;
    }

    /**
     * Runs a method on an object and returns the result
     * 
     * @param obj the object to run the method on
     * @param methodName the name of the method
     * @return the results of the method run
     */
    private static Object _runMethod(Object obj, String methodName)
    {
        try
        {
            Method sessionIdMethod = obj.getClass().getMethod(methodName);
            return sessionIdMethod.invoke(obj);
        }
        catch (Exception e)
        {
            return null;
        }

    }

    // prevent this from being instantiated
    private ExternalContextUtils()
    {
    }

    private static final Logger _LOG = Logger
            .getLogger(ExternalContextUtils.class.getName());

    // =-= Scott O'Bryan =-=
    // Performance enhancement. These will be needed anyway, let's not get them every time.
    private static final Class _PORTLET_ACTION_REQUEST_CLASS;
    private static final Class _PORTLET_RENDER_REQUEST_CLASS;
    private static final Class _PORTLET_RESOURCE_REQUEST_CLASS;
    private static final Class _PORTLET_CONTEXT_CLASS;
    private static final boolean _PORTLET_10_SUPPORTED;
    private static final boolean _PORTLET_20_SUPPORTED;
    private static final Class _PORTLET_CONFIG_CLASS;

    static
    {
        Class context;
        Class config;
        Class actionRequest;
        Class renderRequest;
        Class resourceRequest;
        boolean portlet20Supported = false;
        boolean portlet10Supported = false;

        try
        {
            context = ClassLoaderUtils
                    .loadClass("javax.portlet.PortletContext");
            config = ClassLoaderUtils.loadClass("javax.portlet.PortletConfig");
            actionRequest = ClassLoaderUtils
                    .loadClass("javax.portlet.ActionRequest");
            renderRequest = ClassLoaderUtils
                    .loadClass("javax.portlet.RenderRequest");

            try
            {
                resourceRequest = ClassLoaderUtils
                        .loadClass("javax.portlet.ResourceRequest");
            }
            catch (ClassNotFoundException e)
            {
                _LOG.fine("Portlet 2.0 API is not available on classpath.  Portlet 2.0 functionality is disabled");
                resourceRequest = null;
            }
        }
        catch (final ClassNotFoundException e)
        {
            _LOG.fine("Portlet API is not available on the classpath.  Portlet configurations are disabled.");
            context = null;
            config = null;
            actionRequest = null;
            renderRequest = null;
            resourceRequest = null;
        }

        //Find bridge to tell if portal is supported
        if (context != null)
        {
            // Portlet 1.0 API found. In this case we have to consider that exists alternate
            // bridge implementations like in WebSphere and others.
            portlet10Supported = true;

            try
            {
                Class bridge = ClassLoaderUtils
                        .loadClass("javax.portlet.faces.Bridge");

                if (bridge != null)
                {
                    //Standard bridge defines a spec name which can be used to 
                    //determine Portlet 2.0 Support.
                    String specName = bridge.getPackage()
                            .getSpecificationTitle();
                    _LOG.fine("Found Bridge: " + specName);
                    if (specName != null && specName.startsWith("Portlet 2"))
                    {
                        portlet20Supported = true;
                    }

                    if (_LOG.isLoggable(Level.INFO))
                    {
                        String ver = (portlet20Supported) ? "2.0" : "1.0";
                        _LOG.info("Portlet Environment Detected: " + ver);
                    }
                }
            }
            catch (ClassNotFoundException e)
            {
                _LOG.fine("Portlet API is present but Standard Apache Portlet Bridge is not. "
                        + " This could happen if you are using an alternate Portlet Bridge solution.");

                if (resourceRequest != null)
                {
                    portlet20Supported = true;
                }
            }
        }

        _PORTLET_CONTEXT_CLASS = context;
        _PORTLET_CONFIG_CLASS = config;
        _PORTLET_ACTION_REQUEST_CLASS = actionRequest;
        _PORTLET_RENDER_REQUEST_CLASS = renderRequest;
        _PORTLET_RESOURCE_REQUEST_CLASS = resourceRequest;
        _PORTLET_10_SUPPORTED = portlet10Supported;
        _PORTLET_20_SUPPORTED = portlet20Supported;
    }

    /**
     * Trys to obtain a HttpServletResponse from the Response.
     * Note that this method also trys to unwrap any ServletResponseWrapper
     * in order to retrieve a valid HttpServletResponse.
     * @param response
     * @return if found, the HttpServletResponse, null otherwise
     */
    public static HttpServletResponse getHttpServletResponse(Object response)
    {
        // unwrap the response until we find a HttpServletResponse
        while (response != null)
        {
            if (response instanceof HttpServletResponse)
            {
                // found
                return (HttpServletResponse) response;
            }
            if (response instanceof ServletResponseWrapper)
            {
                // unwrap
                response = ((ServletResponseWrapper) response).getResponse();
            }
            // no more possibilities to find a HttpServletResponse
            break;
        }
        return null; // not found
    }

    /**
     * Trys to obtain a ResponseSwitch from the Response.
     * @param response
     * @return if found, the ResponseSwitch, null otherwise
     */
    /*
    public static ResponseSwitch getResponseSwitch(Object response)
    {
        // unwrap the response until we find a ResponseSwitch
        while (response != null)
        {
            if (response instanceof ResponseSwitch)
            {
                // found
                return (ResponseSwitch) response;
            }
            if (response instanceof ServletResponseWrapper)
            {
                // unwrap
                response = ((ServletResponseWrapper) response).getResponse();
            }
            // no more possibilities to find a ResponseSwitch
            break; 
        }
        return null; // not found
    }*/

    /**
     * Try to create a ResponseSwitch for this response.
     * @param response
     * @return the created ResponseSwitch, if there is a ResponseSwitch 
     *         implementation for the given response, null otherwise
     */
    /*
    public static ResponseSwitch createResponseSwitch(Object response)
    {
        if (response instanceof HttpServletResponse)
        {
            return new HttpServletResponseSwitch((HttpServletResponse) response);
        }
        else if (response instanceof ServletResponse)
        {
            return new ServletResponseSwitch((ServletResponse) response);
        }
        return null;
    }*/

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy