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