KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > nextapp > echo2 > webcontainer > ContainerInstance


1 /*
2  * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3  * Copyright (C) 2002-2005 NextApp, Inc.
4  *
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Alternatively, the contents of this file may be used under the terms of
18  * either the GNU General Public License Version 2 or later (the "GPL"), or
19  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20  * in which case the provisions of the GPL or the LGPL are applicable instead
21  * of those above. If you wish to allow use of your version of this file only
22  * under the terms of either the GPL or the LGPL, and not to allow others to
23  * use your version of this file under the terms of the MPL, indicate your
24  * decision by deleting the provisions above and replace them with the notice
25  * and other provisions required by the GPL or the LGPL. If you do not delete
26  * the provisions above, a recipient may use your version of this file under
27  * the terms of any one of the MPL, the GPL or the LGPL.
28  */

29
30 package nextapp.echo2.webcontainer;
31
32 import java.util.HashMap JavaDoc;
33 import java.util.Iterator JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.WeakHashMap JavaDoc;
36
37 import nextapp.echo2.app.ApplicationInstance;
38 import nextapp.echo2.app.Component;
39 import nextapp.echo2.app.TaskQueueHandle;
40 import nextapp.echo2.app.update.UpdateManager;
41 import nextapp.echo2.webcontainer.util.IdTable;
42 import nextapp.echo2.webrender.Connection;
43 import nextapp.echo2.webrender.UserInstance;
44
45 /**
46  * Web application container user instance.
47  */

48 public class ContainerInstance extends UserInstance {
49     
50     /**
51      * Default asynchronous monitor callback interval (in milliseconds).
52      */

53     private static final int DEFAULT_CALLBACK_INTERVAL = 500;
54     
55     /**
56      * Returns the base HTML element id that should be used when rendering the
57      * specified <code>Component</code>.
58      *
59      * @param component the component
60      * @return the base HTML element id
61      */

62     public static String JavaDoc getElementId(Component component) {
63         return "c_" + component.getRenderId();
64     }
65     
66     /**
67      * Creates a new Web Application Container instance using the provided
68      * client <code>Connection</code>. The instance will automatically
69      * be stored in the relevant <code>HttpSession</code>
70      *
71      * @param conn the client/server <code>Connection</code> for which the
72      * instance is being instantiated
73      */

74     public static void newInstance(Connection conn) {
75         new ContainerInstance(conn);
76     }
77     
78     private ApplicationInstance applicationInstance;
79     private Map JavaDoc componentToRenderStateMap = new HashMap JavaDoc();
80     private transient IdTable idTable;
81     private boolean initialized = false;
82     private Map JavaDoc initialRequestParameterMap;
83     private transient Map JavaDoc taskQueueToCallbackIntervalMap;
84     
85     /**
86      * Creates a new <code>ContainerInstance</code>.
87      *
88      * @param conn the client/server <code>Connection</code> for which the
89      * instance is being instantiated
90      * @see #newInstance(nextapp.echo2.webrender.Connection)
91      */

92     private ContainerInstance(Connection conn) {
93         super(conn);
94         setServerDelayMessage(DefaultServerDelayMessage.INSTANCE);
95         initialRequestParameterMap = new HashMap JavaDoc(conn.getRequest().getParameterMap());
96     }
97     
98     /**
99      * Returns the corresponding <code>ApplicationInstance</code>
100      * for this user instance.
101      *
102      * @return the relevant <code>ApplicationInstance</code>
103      */

104     public ApplicationInstance getApplicationInstance() {
105         return applicationInstance;
106     }
107
108     //BUGBUG. current method of iterating weak-keyed map of task queues
109
// is not adequate. If the application were to for whatever reason hold on
110
// to a dead task queue, its interval setting would effect the
111
// calculation.
112
// One solution: add a getTaskQueues() method to ApplicationInstance
113
/**
114      * Determines the application-specified asynchronous monitoring
115      * service callback interval.
116      *
117      * @return the callback interval, in ms
118      */

119     public int getCallbackInterval() {
120         if (taskQueueToCallbackIntervalMap == null || taskQueueToCallbackIntervalMap.size() == 0) {
121             return DEFAULT_CALLBACK_INTERVAL;
122         }
123         Iterator JavaDoc it = taskQueueToCallbackIntervalMap.values().iterator();
124         int returnInterval = Integer.MAX_VALUE;
125         while (it.hasNext()) {
126             int interval = ((Integer JavaDoc) it.next()).intValue();
127             if (interval < returnInterval) {
128                 returnInterval = interval;
129             }
130         }
131         return returnInterval;
132     }
133     
134     /**
135      * Retrieves the <code>Component</code> with the specified element id.
136      *
137      * @param elementId the element id, e.g., "c_42323"
138      * @return the component (e.g., the component whose id is "42323")
139      */

140     public Component getComponentByElementId(String JavaDoc elementId) {
141         try {
142             return applicationInstance.getComponentByRenderId(elementId.substring(2));
143         } catch (IndexOutOfBoundsException JavaDoc ex) {
144             throw new IllegalArgumentException JavaDoc("Invalid component element id: " + elementId);
145         }
146     }
147     
148     /**
149      * Retrieves the <code>IdTable</code> used by this
150      * <code>ContainerInstance</code> to assign weakly-referenced unique
151      * identifiers to arbitrary objects.
152      *
153      * @return the <code>IdTable</code>
154      */

155     public IdTable getIdTable() {
156         if (idTable == null) {
157             idTable = new IdTable();
158         }
159         return idTable;
160     }
161     
162     /**
163      * Returns an immutable <code>Map</code> containing the HTTP form
164      * parameters sent on the initial request to the application.
165      *
166      * @return the initial request parameter map
167      */

168     public Map JavaDoc getInitialRequestParameterMap() {
169         return initialRequestParameterMap;
170     }
171     
172     /**
173      * Retrieves the <code>RenderState</code> of the specified
174      * <code>Component</code>.
175      *
176      * @param component the component
177      * @return the rendering state
178      */

179     public RenderState getRenderState(Component component) {
180         return (RenderState) componentToRenderStateMap.get(component);
181     }
182     
183     /**
184      * Convenience method to retrieve the application's
185      * <code>UpdateManager</code>, which is used to synchronize
186      * client and server states.
187      * This method is equivalent to invoking
188      * <code>getApplicationInstance().getUpdateManager()</code>.
189      *
190      * @return the <code>UpdateManager</code>
191      */

192     public UpdateManager getUpdateManager() {
193         return applicationInstance.getUpdateManager();
194     }
195     
196     /**
197      * Initializes the <code>ContainerInstance</code>, creating an instance
198      * of the target <code>ApplicationInstance</code> and initializing the state
199      * of the application.
200      *
201      * @param conn the relevant <code>Connection</code>
202      */

203     public void init(Connection conn) {
204         if (initialized) {
205             throw new IllegalStateException JavaDoc("Attempt to invoke ContainerInstance.init() on initialized instance.");
206         }
207         WebContainerServlet servlet = (WebContainerServlet) conn.getServlet();
208         applicationInstance = servlet.newApplicationInstance();
209         
210         ContainerContext containerContext = new ContainerContextImpl(this);
211         applicationInstance.setContextProperty(ContainerContext.CONTEXT_PROPERTY_NAME, containerContext);
212         
213         try {
214             ApplicationInstance.setActive(applicationInstance);
215             applicationInstance.doInit();
216         } finally {
217             ApplicationInstance.setActive(null);
218         }
219         initialized = true;
220     }
221     
222     /**
223      * Determines if the <code>ContainerInstance</code> has been initialized,
224      * i.e., whether its <code>init()</code> method has been invoked.
225      *
226      * @return true if the <code>ContainerInstance</code> is initialized
227      */

228     boolean isInitialized() {
229         return initialized;
230     }
231     
232     /**
233      * Removes the <code>RenderState</code> of the specified
234      * <code>Component</code>.
235      *
236      * @param component the component
237      */

238     public void removeRenderState(Component component) {
239         componentToRenderStateMap.remove(component);
240     }
241     
242     /**
243      * Sets the <code>RenderState</code> of the specified
244      * <code>Component</code>.
245      *
246      * @param component the component
247      * @param renderState the render state
248      */

249     public void setRenderState(Component component, RenderState renderState) {
250         componentToRenderStateMap.put(component, renderState);
251     }
252     
253     /**
254      * Sets the interval between asynchronous callbacks from the client to check
255      * for queued tasks for a given <code>TaskQueue</code>. If multiple
256      * <code>TaskQueue</code>s are active, the smallest specified interval should
257      * be used. The default interval is 500ms.
258      * Application access to this method should be accessed via the
259      * <code>ContainerContext</code>.
260      *
261      * @param taskQueue the <code>TaskQueue</code>
262      * @param ms the number of milliseconds between asynchronous client
263      * callbacks
264      * @see nextapp.echo2.webcontainer.ContainerContext#setTaskQueueCallbackInterval(nextapp.echo2.app.TaskQueueHandle, int)
265      */

266     public void setTaskQueueCallbackInterval(TaskQueueHandle taskQueue, int ms) {
267         if (taskQueueToCallbackIntervalMap == null) {
268             taskQueueToCallbackIntervalMap = new WeakHashMap JavaDoc();
269         }
270         taskQueueToCallbackIntervalMap.put(taskQueue, new Integer JavaDoc(ms));
271     }
272 }
273
Popular Tags