View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing,
    13   * software distributed under the License is distributed on an
    14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   * KIND, either express or implied.  See the License for the
    16   * specific language governing permissions and limitations
    17   * under the License.
    18   */
    19  package org.apache.myfaces.orchestra.frameworkAdapter.basic;
    20
    21  import org.apache.commons.logging.Log;
    22  import org.apache.commons.logging.LogFactory;
    23  import org.apache.myfaces.orchestra.conversation.ConversationMessager;
    24  import org.apache.myfaces.orchestra.conversation.basic.LogConversationMessager;
    25  import org.apache.myfaces.orchestra.frameworkAdapter.FrameworkAdapter;
    26  import org.apache.myfaces.orchestra.lib._ClassUtils;
    27
    28  import javax.servlet.ServletContext;
    29  import javax.servlet.ServletRequest;
    30  import javax.servlet.ServletResponse;
    31  import javax.servlet.http.HttpServletRequest;
    32  import javax.servlet.http.HttpServletResponse;
    33  import java.io.IOException;
    34
    35  /**
    36   * An implementation of the FrameworkAdapter for plain servlet environments.
    37   * <p>
    38   * This class requires the BasicFrameworkAdapterFilter to be configured to run
    39   * for every request.
    40   *
    41   * <h2>Configuring the ConversationMessager</h2>
    42   *
    43   * This class allows the concrete ConversationMessager instance returned
    44   * by the getConversationMessager method to be configured
    45   * in a number of ways:
    46   * <ul>
    47   * <li>By calling an explicit setter, passing an instance.</li>
    48   * <li>By specifying a conversationMessagerName parameter to the constructor
    49   * of this method which matches a bean name defined in the dependency injection
    50   * framework.</li>
    51   * <li>By specifying a conversationMessagerName that is the fully-qualified
    52   * name of a ConversationMessager class to be instantiated</li>
    53   * <li>Otherwise, method createDefaultConversationMessager is called which
    54   * returns a LogConversationMessager instance (unless overridden in a subclass).</li>
    55   * </ul>
    56   *
    57   * See also the BasicFrameworkAdapterFilter class.
    58   */
    59  public class BasicFrameworkAdapter extends FrameworkAdapter
    60  {
    61      private final static String ISE_MESSAGE="No request/response data available"; // NON-NLS
    62
    63      private final static ThreadLocal httpServletRequestThreadLocal = new ThreadLocal();
    64      private final static ThreadLocal httpServletResponseThreadLocal = new ThreadLocal();
    65
    66      private final Log log = LogFactory.getLog(BasicFrameworkAdapter.class);
    67
    68      private final ServletContext servletContext;
    69      private final String conversationMessagerClass;
    70
    71      public BasicFrameworkAdapter(ServletContext context, String conversationMessagerClass)
    72      {
    73          servletContext = context;
    74          this.conversationMessagerClass = conversationMessagerClass;
    75      }
    76
    77      protected ConversationMessager createConversationMessager()
    78      {
    79          if (conversationMessagerClass == null)
    80          {
    81              return createDefaultConversationMessager();
    82          }
    83
    84          // First try to find a bean of that name in the dependency-injection
    85          // framework.
    86          Object instance = getBean(conversationMessagerClass);
    87          if (instance instanceof ConversationMessager)
    88          {
    89              return (ConversationMessager) instance;
    90          }
    91
    92          // Now resort to trying the value as a classname.
    93          return (ConversationMessager) _ClassUtils.newInstance(conversationMessagerClass);
    94      }
    95
    96      protected ConversationMessager createDefaultConversationMessager()
    97      {
    98          return new LogConversationMessager();
    99      }
    100
    101     private HttpServletRequest getRequest()
    102     {
    103         return (HttpServletRequest) httpServletRequestThreadLocal.get();
    104     }
    105
    106     private HttpServletResponse getResponse()
    107     {
    108         return (HttpServletResponse) httpServletResponseThreadLocal.get();
    109     }
    110
    111     public void beginRequest(ServletRequest req, ServletResponse rsp)
    112     {
    113         log.debug("Beginning request");
    114         if (req instanceof HttpServletRequest)
    115         {
    116             httpServletRequestThreadLocal.set(req);
    117         }
    118         if (rsp instanceof HttpServletResponse)
    119         {
    120             httpServletResponseThreadLocal.set(rsp);
    121         }
    122
    123         FrameworkAdapter.setCurrentInstance(this);
    124     }
    125
    126     public void endRequest()
    127     {
    128         log.debug("Ending request");
    129         FrameworkAdapter.setCurrentInstance(null);
    130         httpServletRequestThreadLocal.set(null);
    131         httpServletResponseThreadLocal.set(null);
    132     }
    133
    134     public String getInitParameter(String key)
    135     {
    136         return servletContext.getInitParameter(key);
    137     }
    138
    139     public Object getRequestParameterAttribute(String key)
    140     {
    141         HttpServletRequest request = getRequest();
    142         if (request != null)
    143         {
    144             return request.getParameter(key);
    145         }
    146
    147         throw new IllegalStateException(ISE_MESSAGE);
    148     }
    149
    150     public boolean containsRequestParameterAttribute(String key)
    151     {
    152         HttpServletRequest request = getRequest();
    153         if (request != null)
    154         {
    155             return request.getParameter(key) != null;
    156         }
    157
    158         throw new IllegalStateException(ISE_MESSAGE);
    159     }
    160
    161     public Object getRequestAttribute(String key)
    162     {
    163         HttpServletRequest request = getRequest();
    164         if (request != null)
    165         {
    166             return request.getAttribute(key);
    167         }
    168
    169         throw new IllegalStateException(ISE_MESSAGE);
    170     }
    171
    172     public void setRequestAttribute(String key, Object value)
    173     {
    174         HttpServletRequest request = getRequest();
    175         if (request != null)
    176         {
    177             request.setAttribute(key, value);
    178             return;
    179         }
    180
    181         throw new IllegalStateException(ISE_MESSAGE);
    182     }
    183
    184     public boolean containsRequestAttribute(String key)
    185     {
    186         HttpServletRequest request = getRequest();
    187         if (request != null)
    188         {
    189             return request.getAttribute(key) != null;
    190         }
    191
    192         throw new IllegalStateException(ISE_MESSAGE);
    193     }
    194
    195     public Object getSessionAttribute(String key)
    196     {
    197         HttpServletRequest request = getRequest();
    198         if (request != null && request.getSession(true) != null)
    199         {
    200             return request.getSession(true).getAttribute(key);
    201         }
    202
    203         throw new IllegalStateException(ISE_MESSAGE);
    204     }
    205
    206     public void setSessionAttribute(String key, Object value)
    207     {
    208         HttpServletRequest request = getRequest();
    209         if (request != null && request.getSession(true) != null)
    210         {
    211             request.getSession(true).setAttribute(key, value);
    212             return;
    213         }
    214
    215     }
    216
    217     public boolean containsSessionAttribute(String key)
    218     {
    219         HttpServletRequest request = getRequest();
    220         if (request != null && request.getSession(true) != null)
    221         {
    222             return request.getSession(true).getAttribute(key) != null;
    223         }
    224
    225         throw new IllegalStateException(ISE_MESSAGE);
    226     }
    227
    228     protected String getRequestContextPath()
    229     {
    230         HttpServletRequest request = getRequest();
    231         if (request != null)
    232         {
    233             return request.getContextPath();
    234         }
    235
    236         throw new IllegalStateException(ISE_MESSAGE);
    237     }
    238
    239     public void redirect(String url) throws IOException
    240     {
    241         StringBuffer redir = new StringBuffer();
    242         if (url.startsWith("/"))
    243         {
    244             redir.append(getRequestContextPath());
    245         }
    246         redir.append(url);
    247
    248         HttpServletResponse rsp = getResponse();
    249         String dstUrl = rsp.encodeRedirectURL(redir.toString());
    250         rsp.sendRedirect(dstUrl);
    251     }
    252
    253     /**
    254      * Look in the request and session scopes for an entry
    255      * with the specified name.
    256      * <p>
    257      * This basic adapter class does not support invoking the JSP expression
    258      * evaluator; no "variable resolver" will ever be used to look up the
    259      * specified name.
    260      * <p>
    261      * TODO: also look in the application scope.
    262      * <p>
    263      * TODO: investigate invoking the jsp.ExpressionFactory class to look up
    264      * the variable. Possibly that could be done in a different JspFrameworkAdapter
    265      * class.
    266      */
    267     public Object getBean(String name)
    268     {
    269         Object obj;
    270
    271         obj = getRequestAttribute(name);
    272         if (obj != null)
    273         {
    274             return obj;
    275         }
    276
    277         obj = getSessionAttribute(name);
    278         if (obj != null)
    279         {
    280             return obj;
    281         }
    282
    283         // TODO: look up application-scoped objects.
    284
    285         return null;
    286     }
    287
    288     /**
    289      * Perform a redirect to the specified url.
    290      * <p>
    291      * A redirect is done rather than a forward so that the remote browser has its
    292      * current url updated appropriately. Note that a redirect does cause any
    293      * request-scoped variables to be discarded.
    294      */
    295     public void invokeNavigation(String navigationName) throws IOException
    296     {
    297         redirect(navigationName);
    298     }
    299 }