|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.mj.impl.rt.support; |
|
19 |
|
20 import com.nokia.mj.impl.utils.Uid; |
|
21 import java.util.Vector; |
|
22 import java.util.Enumeration; |
|
23 import java.security.Permission; |
|
24 import java.security.AccessControlException; |
|
25 |
|
26 /** |
|
27 * ApplicationUtils is an abstract base class for API implementations, |
|
28 * which allows them to use miscellanous utilities related to the running |
|
29 * application. |
|
30 * <p> |
|
31 * The class provides a static getter method for getting an instance of |
|
32 * the running application. In those runtimes that are always running only |
|
33 * one instance (like MIDP) returns always the same instance of the |
|
34 * ApplicationUtils. However those runtimes (like eRCP), that may run several |
|
35 * application in the same JVM instance, will return an application specific |
|
36 * instance. |
|
37 * <p> |
|
38 * The runtime implementation hides the solving of the correct application |
|
39 * when method <code>getInstace</code> is called. However it must be noted |
|
40 * that if the call is made some common thread, the <code>getInstace</code> |
|
41 * might not able to solve the correct application. |
|
42 * <p> |
|
43 * Example how to register a shutdown listener. |
|
44 * <pre> |
|
45 * package com.nokia.mj.impl.mypackage; |
|
46 * |
|
47 * import com.nokia.mj.impl.rt.support.ApplicationUtils; |
|
48 * public void myClass() |
|
49 * { |
|
50 * public void myMethod() |
|
51 * { |
|
52 * // Get the insatnce of ApplicationUtils. |
|
53 * ApplicationUtils appUtils = ApplicationUtils.getInstance(); |
|
54 * |
|
55 * // Get the name of the application. |
|
56 * appUtils.addShutdownListener(new ShutdownListener() |
|
57 * { |
|
58 * public void shuttingDown() |
|
59 * { |
|
60 * //Do cleaning... |
|
61 * } |
|
62 * |
|
63 * }); |
|
64 * |
|
65 * |
|
66 * // My implementation... |
|
67 * } |
|
68 * } |
|
69 *</pre> |
|
70 * @author Nokia Corporation |
|
71 * @version 1.0 |
|
72 */ |
|
73 |
|
74 public abstract class ApplicationUtils |
|
75 { |
|
76 |
|
77 |
|
78 /** |
|
79 * Name of the runtime specific class that extends this base class. |
|
80 */ |
|
81 private static final String PORTCLASS = ".ApplicationUtilsImpl"; |
|
82 |
|
83 /** |
|
84 * A singleton instance of runtime dependent instance of class extending |
|
85 * the ApplicationUtils base class. |
|
86 */ |
|
87 protected static ApplicationUtils sInstance = null; |
|
88 |
|
89 /** |
|
90 * A set of listeners who wants to receive notification when the |
|
91 * application is abaout to close. |
|
92 */ |
|
93 private Vector mListeners; |
|
94 |
|
95 /** |
|
96 * A lock for synchronizing the thw start up waiting feature. |
|
97 */ |
|
98 private Object mApplicationStartLock = new Object(); |
|
99 |
|
100 /** |
|
101 * Information wheteher to continue start up or cancel it. |
|
102 */ |
|
103 private Boolean mStartCmd; |
|
104 |
|
105 |
|
106 /** |
|
107 * When this class is first loaded the static initializer will create a |
|
108 * singleton instance of runtime dependent instance of class extending the |
|
109 * ApplicationUtils base class. The class is created using dynamic |
|
110 * instantiation (<code>Class.forname & Class.newInstance</code>) and |
|
111 * the name of the class is a combination of PACKAGE_PREFIX + |
|
112 * <value of system property PACKAGE_END_PROPERTY_NAME > |
|
113 * + .<value of PORTCLASS member variable >. |
|
114 */ |
|
115 static |
|
116 { |
|
117 //Get the system proptery defining the end of package. |
|
118 String packageEnd = |
|
119 System.getProperty(ApplicationInfo.PACKAGE_END_PROPERTY_NAME); |
|
120 |
|
121 if (packageEnd == null) |
|
122 { |
|
123 throw new RuntimeException |
|
124 ("Not able to load " + PORTCLASS + "class since " + |
|
125 ApplicationInfo.PACKAGE_END_PROPERTY_NAME + |
|
126 " system property is undefined"); |
|
127 } |
|
128 |
|
129 //Construct the class |
|
130 String className = ApplicationInfo.PACKAGE_PREFIX + |
|
131 packageEnd + PORTCLASS; |
|
132 try |
|
133 { |
|
134 Class clazz = Class.forName(className); |
|
135 sInstance = (ApplicationUtils)clazz.newInstance(); |
|
136 } |
|
137 catch (Exception e) |
|
138 { |
|
139 e.printStackTrace(); |
|
140 throw new RuntimeException("Not able to instantiate class " + |
|
141 className+". Reason is: " + e); |
|
142 } |
|
143 } |
|
144 |
|
145 /** |
|
146 * Returns an instace of ApplicationUtils class which provides access to |
|
147 * application related runtime services. |
|
148 * |
|
149 * @return the ApplicationUtils object, null if the construction of the |
|
150 * object has faild |
|
151 */ |
|
152 public static ApplicationUtils getInstance() |
|
153 { |
|
154 return sInstance; |
|
155 } |
|
156 |
|
157 /** |
|
158 * Notifies the runtime that an exit command has been received and the |
|
159 * application is being tried to close nicely. The runtime is responsible |
|
160 * for killing the application if it doesn't close itself nicely after |
|
161 * specified grace time. The specified grace time is runtime dependent. |
|
162 * <p> |
|
163 * This method is meant ONLY for the UI and no other API are allowed |
|
164 * to use it. The UI must use this API ONLY when the user explicitly |
|
165 * wants to close the application using some platform depedent feataure |
|
166 * (e.g. red key in S60). If the user tries to close the application |
|
167 * using the mechanism provided by the application itself, this method |
|
168 * must not be called. |
|
169 * <p> |
|
170 * This method is a problematic in such runtimes that may run more than one |
|
171 * application in same JVM instance (e.g. eRCP). If the application |
|
172 * doesn't close nicely the runtime may have to terminate |
|
173 * the whole JVM process, which leads closing all the running applications |
|
174 * and the runtime itself. |
|
175 * |
|
176 */ |
|
177 public abstract void notifyExitCmd(); |
|
178 |
|
179 /** |
|
180 * Determines whether the access request indicated by the specified |
|
181 * permission should be allowed or denied, based on the security policy |
|
182 * currently in effect. This method quietly returns if the access request |
|
183 * is permitted, or throws a suitable AccessControlException otherwise. |
|
184 * <p> |
|
185 * The design decision was that all the API implementation should use this |
|
186 * method for making security checkings and avoid using the |
|
187 * <code>checkPermission</code> method <code>AccessController</code> class, |
|
188 * which is left for application usage only. |
|
189 * <p> |
|
190 * The runtime implementation is responsible for forwarding security |
|
191 * checking to correct securty handler. In MIDP this would be Midp security |
|
192 * component while in 'main' type of application the handler would be the |
|
193 * <code>AccessController</code> class. |
|
194 * |
|
195 * @param p the requested permission. |
|
196 * @throws AccessControlException if the specified permission is not |
|
197 * permitted, based on the current security policy. |
|
198 * @throws NullPointerException if the specified permission is null. |
|
199 */ |
|
200 public abstract void checkPermission(Permission p) |
|
201 throws AccessControlException, |
|
202 NullPointerException; |
|
203 |
|
204 public abstract void checkPermission(Uid appUid,Permission p) |
|
205 throws AccessControlException, |
|
206 NullPointerException; |
|
207 |
|
208 /** |
|
209 * Adds a shutdown notifications listener to receive notifications when |
|
210 * the application is about to close. |
|
211 * <p> |
|
212 * When the runtime receives information that the application is closing |
|
213 * (either from the application itself or from the system) the runtime |
|
214 * will send a notification to all registered listeners by calling |
|
215 * {@link ShutdownListener#shuttingDown() shuttingDown} method. All the |
|
216 * calls are made in a loop in one thread, so if some listener blocks the |
|
217 * call the rest of the listeners don't get the notification. |
|
218 * <p> |
|
219 * There can be more than one listener. |
|
220 * |
|
221 * @param listener the new listener. |
|
222 */ |
|
223 public void addShutdownListener(ShutdownListener listener) |
|
224 { |
|
225 if (mListeners == null) |
|
226 { |
|
227 mListeners = new Vector(); |
|
228 } |
|
229 mListeners.addElement(listener); |
|
230 } |
|
231 |
|
232 |
|
233 /** |
|
234 * Waits (if needed) until the application to be started is known. |
|
235 * This method can be used for pre-warming features. If the runtime is in |
|
236 * pre-warmed state where the application to be launched is not yet known, |
|
237 * this method will block. It is safe to call this method if the application |
|
238 * is already known - in that case the method won't block. Once the |
|
239 * application is known all the waiters will be released. Knowing the |
|
240 * application doesn't necessarily mean that the application it self |
|
241 * has been created (might happen later). The method will provide info |
|
242 * whether to continue or cancel the start up as a return value. |
|
243 * @return true if the user should continue starting, otherwise the user |
|
244 * should do the required shut down proceures. |
|
245 */ |
|
246 public boolean waitStart() |
|
247 { |
|
248 synchronized (mApplicationStartLock) |
|
249 { |
|
250 if (mStartCmd == null) |
|
251 { |
|
252 try |
|
253 { |
|
254 mApplicationStartLock.wait(); |
|
255 } |
|
256 catch (InterruptedException ie) |
|
257 { |
|
258 } |
|
259 } |
|
260 return mStartCmd == null ? false : mStartCmd.booleanValue(); |
|
261 } |
|
262 } |
|
263 |
|
264 /** |
|
265 * Can be used to inform the runtime to pause the running application. The |
|
266 * origin could be e.g. flip close or application going to back ground. |
|
267 */ |
|
268 public void pauseApplication() |
|
269 { |
|
270 // Empty implementation as default. |
|
271 } |
|
272 |
|
273 /** |
|
274 * Can be used to inform the runtime to resume the paused application. The |
|
275 * origin could be e.g. flip open or application going to fore ground. |
|
276 */ |
|
277 public void resumeApplication() |
|
278 { |
|
279 // Empty implementation as default. |
|
280 } |
|
281 |
|
282 /** |
|
283 * Releases the start waiters. |
|
284 */ |
|
285 protected void releaseStartWaiter(boolean doStart) |
|
286 { |
|
287 if (mApplicationStartLock != null) |
|
288 { |
|
289 synchronized (mApplicationStartLock) |
|
290 { |
|
291 mStartCmd = new Boolean(doStart); |
|
292 mApplicationStartLock.notifyAll(); |
|
293 } |
|
294 } |
|
295 } |
|
296 |
|
297 /** |
|
298 * Sends shutdown notification to all the registered listeners. |
|
299 */ |
|
300 protected void doShutdown() |
|
301 { |
|
302 if (mListeners != null) |
|
303 { |
|
304 Enumeration enumer = mListeners.elements(); |
|
305 while (enumer.hasMoreElements()) |
|
306 { |
|
307 ShutdownListener listener = |
|
308 (ShutdownListener)enumer.nextElement(); |
|
309 listener.shuttingDown(); |
|
310 } |
|
311 } |
|
312 } |
|
313 } |