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.custom.conversation;
20  
21  import org.apache.myfaces.custom.redirectTracker.RedirectTrackerManager;
22  
23  import javax.faces.context.FacesContext;
24  import javax.faces.el.ValueBinding;
25  import java.io.IOException;
26  
27  /**
28   * <p>
29   * Ensures a named conversation is running
30   * </p>
31   * <p>
32   * check if a conversation is active.
33   * </p>
34   * <p>
35   * The way this is done here is sub-optimal, once we are on jsf 1.2 it should be possible to
36   * check this before ANY rendering - and maybe to invoke a navigation then
37   * </p>
38   *   
39   * @JSFJspProperty name="action" longDesc = "the action which should be called in case of a not running conversation"
40   *   
41   * @author imario@apache.org
42   */
43  public class UIEnsureConversation extends AbstractConversationComponent
44  {
45      public static final String COMPONENT_TYPE = "org.apache.myfaces.EnsureConversation";
46  
47      private String redirectTo;
48      private Boolean preCheck;
49  
50      public void encodeBegin(FacesContext context) throws IOException
51      {
52          super.encodeBegin(context);
53  
54          checkConversation(context, getName());
55      }
56  
57      public void decode(FacesContext context)
58      {
59          super.decode(context);
60  
61          try
62          {
63              checkConversation(context, getName());
64          }
65          catch (IOException e)
66          {
67              throw new RuntimeException(e);
68          }
69      }
70  
71      public void restoreState(FacesContext context, Object state)
72      {
73          Object[] states = (Object[]) state;
74  
75          super.restoreState(context, states[0]);
76          redirectTo = (String) states[1];
77          preCheck = (Boolean) states[2];
78      }
79  
80      public Object saveState(FacesContext context)
81      {
82          return new Object[]
83              {
84                  super.saveState(context),
85                  redirectTo,
86                  preCheck
87              };
88      }
89  
90      protected void checkConversation(FacesContext context, String name) throws IOException
91      {
92          ConversationManager conversationManager = ConversationManager.getInstance();
93  
94          if (Boolean.TRUE.equals(preCheck))
95          {
96              String actionResult = (String) getAction().invoke(context, null);
97              if (actionResult == null)
98              {
99                  // no further action, maybe the user started a conversation
100                 return;
101             }
102 
103             conversationManager.getMessager().setConversationNotActive(context, getName());
104             return;
105         }
106         else if (!conversationManager.hasConversation(name))
107         {
108             if (getAction() != null)
109             {
110                 String actionResult = (String) getAction().invoke(context, null);
111                 if (actionResult == null)
112                 {
113                     // no further action, maybe the user started a conversation
114                     return;
115                 }
116                 conversationManager.getMessager().setConversationNotActive(context, getName());
117 
118                 // hopefully the user configured the navigation as redirect ...
119                 context.getApplication().getNavigationHandler().handleNavigation(context, null, actionResult);
120             }
121             else
122             {
123                 conversationManager.getMessager().setConversationNotActive(context, getName());
124 
125                 String actionUrl = context.getApplication().getViewHandler().getActionURL(
126                             context, getRedirectTo());
127                 String encodedActionUrl = context.getExternalContext().encodeActionURL(actionUrl);
128 
129                 // XXX: figure out a way to avoid this ==>
130                 RedirectTrackerManager manager = RedirectTrackerManager.getInstance(context);
131                 if (manager != null)
132                 {
133                     encodedActionUrl = manager.trackRedirect(context, encodedActionUrl);
134                 }
135                 // XXX: figure out a way to avoid this <==
136 
137                 context.getExternalContext().redirect(encodedActionUrl);
138             }
139 
140             return;
141         }
142     }
143 
144     /**
145      * redirect to the given view if the conversation is not running
146      * 
147      * @JSFProperty
148      * @return
149      */
150     public String getRedirectTo()
151     {
152         if (redirectTo != null)
153         {
154             return redirectTo;
155         }
156         ValueBinding vb = getValueBinding("redirectTo");
157         if (vb == null)
158         {
159             return null;
160         }
161         return (String) vb.getValue(getFacesContext());
162     }
163 
164     public void setRedirectTo(String redirectTo)
165     {
166         this.redirectTo = redirectTo;
167     }
168     
169     /**
170      * Delegate the check to the action method at all. The user has to check if 
171      * a conversation is running. A action method is mandatory.
172      * 
173      * @JSFProperty
174      * @return
175      */
176     public Boolean getPreCheck()
177     {
178         if (preCheck != null)
179         {
180             return preCheck;
181         }
182         ValueBinding vb = getValueBinding("preCheck");
183         if (vb == null)
184         {
185             return null;
186         }
187         return (Boolean) vb.getValue(getFacesContext());
188     }
189 
190     public void setPreCheck(Boolean preCheck)
191     {
192         this.preCheck = preCheck;
193     }
194 
195 }