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;
    20
    21  import java.io.IOException;
    22
    23  import org.apache.myfaces.orchestra.conversation.ConversationMessager;
    24
    25  /**
    26   * An interface that provides access to all the data necessary for Orchestra to work while isolating Orchestra
    27   * from the actual UI presentation framework being used.
    28   * <p>
    29   * A different concrete subclass of this type is then provided for each UI framework that Orchestra supports
    30   * (and additional subtypes can be defined by users if required). This allows Orchestra to support multiple
    31   * presentation frameworks, such as JSF and plain JSP. Method getCurrentInstance is used by Orchestra code
    32   * to locate the appropriate adapter instance when needed.
    33   * <p>
    34   * The method setCurrentInstance must be called at the start of each request in order to set the
    35   * appropriate adapter instance for whatever UI framework will be handing that request.
    36   */
    37  public abstract class FrameworkAdapter
    38  {
    39      private final static ThreadLocal instanceThreadLocal = new ThreadLocal();
    40
    41      private ConversationMessager conversationMessager;
    42      private boolean prepared = false;
    43
    44      /**
    45       * Expected to be called only by a servlet filter at the start and end of each request.
    46       * <p>
    47       * The prepare method of the provided frameworkAdapter is called if it has not already
    48       * been done. This ensures that the object is valid before the request begins. An
    49       * unchecked exception may therefore be thrown if the instance is misconfigured.
    50       */
    51      public static void setCurrentInstance(FrameworkAdapter frameworkAdapter)
    52      {
    53          if (frameworkAdapter == null)
    54          {
    55              instanceThreadLocal.remove();
    56              return;
    57          }
    58
    59          synchronized(frameworkAdapter)
    60          {
    61              if (!frameworkAdapter.prepared)
    62              {
    63                  frameworkAdapter.prepare();
    64              }
    65          }
    66
    67          instanceThreadLocal.set(frameworkAdapter);
    68      }
    69
    70      /**
    71       * Return an object that implements the non-static methods of this abstract
    72       * class in a manner appropriate for whatever UI framework is handling the
    73       * current request.
    74       */
    75      public static FrameworkAdapter getCurrentInstance()
    76      {
    77          return (FrameworkAdapter) instanceThreadLocal.get();
    78      }
    79
    80      /**
    81       * Constructor.
    82       * <p>
    83       * This constructor deliberately takes no parameters, as this class may be extended
    84       * in future releases, adding new framework-specific properties if more are needed.
    85       * Changing the constructor would not be elegant, so instead this class uses
    86       * "setter" methods to set the properties of this object, and the prepare() method
    87       * to ensure object integrity.
    88       */
    89      public FrameworkAdapter()
    90      {
    91      }
    92
    93      /**
    94       * Ensure this object is valid, and perform any once-only initialisation required.
    95       * <p>
    96       * This method must be called before any call to any method on this class
    97       * other than setters. Multiple calls to this method are safe; all except the first
    98       * one will be ignored. The setCurrentInstance method calls this method
    99       * automatically.
    100      * <p>
    101      * This method may be overridden by subclasses to perform once-only initialisation.
    102      * If this is done, call super.prepare at the end of the subclass implementation.
    103      * <p>
    104      * This method can throw unchecked exceptions if there is a problem with the
    105      * configuration of this object.
    106      */
    107     public void prepare()
    108     {
    109         if (conversationMessager == null)
    110         {
    111             // Not set via an explicit call to the setter, and not set
    112             // from a child class implementation of this method, so
    113             // try to do it here.
    114             conversationMessager = createConversationMessager();
    115         }
    116
    117         synchronized(this)
    118         {
    119             prepared = true;
    120         }
    121     }
    122
    123     /**
    124      * If this method is not overridden by a subclass, then method setConversationMessager
    125      * must be used to explicitly provide an instance.
    126      */
    127     protected ConversationMessager createConversationMessager()
    128     {
    129         throw new IllegalStateException("conversation messager configuration missing"); // NON-NLS
    130     }
    131
    132     /**
    133      * Return an object that can report internal application problems to the user associated
    134      * with the current request.
    135      * <p>
    136      * If setConversationManager was called explicitly when this object was set up, then the
    137      * provided instance is returned. Otherwise what is returned is determined by the
    138      * concrete subclass. See the appropriate subclass documentation for details.
    139      */
    140     public ConversationMessager getConversationMessager()
    141     {
    142         return conversationMessager;
    143     }
    144
    145     /**
    146      * Set the object that can report internal application problems to the user associated
    147      * with a request. This method is only ever expected to be called once, during
    148      * configuration of a FrameworkAdapter instance.
    149      */
    150     public void setConversationMessager(ConversationMessager conversationMessager)
    151     {
    152         this.conversationMessager = conversationMessager;
    153     }
    154
    155     /**
    156      * Return the global init parameter with the specified name.
    157      * In most cases this is expected to return data from the ServletContext.
    158      */
    159     public abstract String getInitParameter(String key);
    160
    161     /**
    162      * Get a value from the set of input parameters sent by the user as part
    163      * of the request.
    164      */
    165     public abstract Object getRequestParameterAttribute(String key);
    166
    167     public abstract boolean containsRequestParameterAttribute(String key);
    168
    169     /**
    170      * Get a request-scope variable.
    171      */
    172     public abstract Object getRequestAttribute(String key);
    173
    174     public abstract void setRequestAttribute(String key, Object value);
    175
    176     public abstract boolean containsRequestAttribute(String key);
    177
    178     /**
    179      * Get a variable from the session-scope of the current user.
    180      */
    181     public abstract Object getSessionAttribute(String key);
    182
    183     public abstract void setSessionAttribute(String key, Object value);
    184
    185     public abstract boolean containsSessionAttribute(String key);
    186
    187     /**
    188      * Instruct the remote browser to fetch the specified URL.
    189      */
    190     public abstract void redirect(String url) throws IOException;
    191
    192     /**
    193      * Return the variable with the specified name, or null if no such bean exists.
    194      * <p>
    195      * In frameworks that support "managed beans", ie creation of objects on demand then
    196      * this may trigger the creation of the specified object. In frameworks that do not
    197      * support this, then the lookup may just return null if no object with the specified
    198      * name currently exists.
    199      * <p>
    200      * Note that no "property traversal" is required or expected; a name of "a.b.c"
    201      * is NOT evaluated as "property c of property b of bean a", but as the bean
    202      * with name 'a.b.c'.
    203      */
    204     public abstract Object getBean(String name);
    205
    206     /**
    207      * Navigate to the specified logical destination.
    208      * <p>
    209      * For frameworks that have a built-in navigation system, that system should be
    210      * invoked.
    211      * <p>
    212      * For frameworks with no logical navigation system, the navigationName is treated
    213      * as a plain URL. Whether a FORWARD or a REDIRECT to this URL is perfomed is
    214      * determined by the subclass.
    215      */
    216     public abstract void invokeNavigation(String navigationName) throws IOException;
    217
    218     /**
    219      * Return a string that identifies what view (logical application page) the user is
    220      * currently working with.
    221      * <p>
    222      * The primary use of this is to pass it to the "view controller manager" to obtain
    223      * the "view controller" bean that holds the lifecycle methods needed for the current
    224      * view.
    225      * <p>
    226      * For frameworks like JSF, this is the "view id".
    227      * <p>
    228      * By default a fixed value is returned, which allows frameworks that do not have
    229      * a concept of a "current logical page" to automatically support a single
    230      * "view controller" bean for the whole application.
    231      */
    232     public String getCurrentViewId()
    233     {
    234         return "defaultView";
    235     }
    236 }