diff -r f5050f1da672 -r 04becd199f91 javacommons/utils/javasrc/com/nokia/mj/impl/rt/support/ApplicationUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javacommons/utils/javasrc/com/nokia/mj/impl/rt/support/ApplicationUtils.java Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,313 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +package com.nokia.mj.impl.rt.support; + +import com.nokia.mj.impl.utils.Uid; +import java.util.Vector; +import java.util.Enumeration; +import java.security.Permission; +import java.security.AccessControlException; + +/** + * ApplicationUtils is an abstract base class for API implementations, + * which allows them to use miscellanous utilities related to the running + * application. + *
+ * The class provides a static getter method for getting an instance of + * the running application. In those runtimes that are always running only + * one instance (like MIDP) returns always the same instance of the + * ApplicationUtils. However those runtimes (like eRCP), that may run several + * application in the same JVM instance, will return an application specific + * instance. + *
+ * The runtime implementation hides the solving of the correct application
+ * when method getInstace
is called. However it must be noted
+ * that if the call is made some common thread, the getInstace
+ * might not able to solve the correct application.
+ *
+ * Example how to register a shutdown listener. + *
+ * package com.nokia.mj.impl.mypackage; + * + * import com.nokia.mj.impl.rt.support.ApplicationUtils; + * public void myClass() + * { + * public void myMethod() + * { + * // Get the insatnce of ApplicationUtils. + * ApplicationUtils appUtils = ApplicationUtils.getInstance(); + * + * // Get the name of the application. + * appUtils.addShutdownListener(new ShutdownListener() + * { + * public void shuttingDown() + * { + * //Do cleaning... + * } + * + * }); + * + * + * // My implementation... + * } + * } + *+ * @author Nokia Corporation + * @version 1.0 + */ + +public abstract class ApplicationUtils +{ + + + /** + * Name of the runtime specific class that extends this base class. + */ + private static final String PORTCLASS = ".ApplicationUtilsImpl"; + + /** + * A singleton instance of runtime dependent instance of class extending + * the ApplicationUtils base class. + */ + protected static ApplicationUtils sInstance = null; + + /** + * A set of listeners who wants to receive notification when the + * application is abaout to close. + */ + private Vector mListeners; + + /** + * A lock for synchronizing the thw start up waiting feature. + */ + private Object mApplicationStartLock = new Object(); + + /** + * Information wheteher to continue start up or cancel it. + */ + private Boolean mStartCmd; + + + /** + * When this class is first loaded the static initializer will create a + * singleton instance of runtime dependent instance of class extending the + * ApplicationUtils base class. The class is created using dynamic + * instantiation (
Class.forname & Class.newInstance
) and
+ * the name of the class is a combination of PACKAGE_PREFIX +
+ * <value of system property PACKAGE_END_PROPERTY_NAME >
+ * + .<value of PORTCLASS member variable >.
+ */
+ static
+ {
+ //Get the system proptery defining the end of package.
+ String packageEnd =
+ System.getProperty(ApplicationInfo.PACKAGE_END_PROPERTY_NAME);
+
+ if (packageEnd == null)
+ {
+ throw new RuntimeException
+ ("Not able to load " + PORTCLASS + "class since " +
+ ApplicationInfo.PACKAGE_END_PROPERTY_NAME +
+ " system property is undefined");
+ }
+
+ //Construct the class
+ String className = ApplicationInfo.PACKAGE_PREFIX +
+ packageEnd + PORTCLASS;
+ try
+ {
+ Class clazz = Class.forName(className);
+ sInstance = (ApplicationUtils)clazz.newInstance();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new RuntimeException("Not able to instantiate class " +
+ className+". Reason is: " + e);
+ }
+ }
+
+ /**
+ * Returns an instace of ApplicationUtils class which provides access to
+ * application related runtime services.
+ *
+ * @return the ApplicationUtils object, null if the construction of the
+ * object has faild
+ */
+ public static ApplicationUtils getInstance()
+ {
+ return sInstance;
+ }
+
+ /**
+ * Notifies the runtime that an exit command has been received and the
+ * application is being tried to close nicely. The runtime is responsible
+ * for killing the application if it doesn't close itself nicely after
+ * specified grace time. The specified grace time is runtime dependent.
+ * + * This method is meant ONLY for the UI and no other API are allowed + * to use it. The UI must use this API ONLY when the user explicitly + * wants to close the application using some platform depedent feataure + * (e.g. red key in S60). If the user tries to close the application + * using the mechanism provided by the application itself, this method + * must not be called. + *
+ * This method is a problematic in such runtimes that may run more than one + * application in same JVM instance (e.g. eRCP). If the application + * doesn't close nicely the runtime may have to terminate + * the whole JVM process, which leads closing all the running applications + * and the runtime itself. + * + */ + public abstract void notifyExitCmd(); + + /** + * Determines whether the access request indicated by the specified + * permission should be allowed or denied, based on the security policy + * currently in effect. This method quietly returns if the access request + * is permitted, or throws a suitable AccessControlException otherwise. + *
+ * The design decision was that all the API implementation should use this
+ * method for making security checkings and avoid using the
+ * checkPermission
method AccessController
class,
+ * which is left for application usage only.
+ *
+ * The runtime implementation is responsible for forwarding security
+ * checking to correct securty handler. In MIDP this would be Midp security
+ * component while in 'main' type of application the handler would be the
+ * AccessController
class.
+ *
+ * @param p the requested permission.
+ * @throws AccessControlException if the specified permission is not
+ * permitted, based on the current security policy.
+ * @throws NullPointerException if the specified permission is null.
+ */
+ public abstract void checkPermission(Permission p)
+ throws AccessControlException,
+ NullPointerException;
+
+ public abstract void checkPermission(Uid appUid,Permission p)
+ throws AccessControlException,
+ NullPointerException;
+
+ /**
+ * Adds a shutdown notifications listener to receive notifications when
+ * the application is about to close.
+ *
+ * When the runtime receives information that the application is closing + * (either from the application itself or from the system) the runtime + * will send a notification to all registered listeners by calling + * {@link ShutdownListener#shuttingDown() shuttingDown} method. All the + * calls are made in a loop in one thread, so if some listener blocks the + * call the rest of the listeners don't get the notification. + *
+ * There can be more than one listener. + * + * @param listener the new listener. + */ + public void addShutdownListener(ShutdownListener listener) +{ + if (mListeners == null) + { + mListeners = new Vector(); + } + mListeners.addElement(listener); + } + + + /** + * Waits (if needed) until the application to be started is known. + * This method can be used for pre-warming features. If the runtime is in + * pre-warmed state where the application to be launched is not yet known, + * this method will block. It is safe to call this method if the application + * is already known - in that case the method won't block. Once the + * application is known all the waiters will be released. Knowing the + * application doesn't necessarily mean that the application it self + * has been created (might happen later). The method will provide info + * whether to continue or cancel the start up as a return value. + * @return true if the user should continue starting, otherwise the user + * should do the required shut down proceures. + */ + public boolean waitStart() + { + synchronized (mApplicationStartLock) + { + if (mStartCmd == null) + { + try + { + mApplicationStartLock.wait(); + } + catch (InterruptedException ie) + { + } + } + return mStartCmd == null ? false : mStartCmd.booleanValue(); + } + } + + /** + * Can be used to inform the runtime to pause the running application. The + * origin could be e.g. flip close or application going to back ground. + */ + public void pauseApplication() + { + // Empty implementation as default. + } + + /** + * Can be used to inform the runtime to resume the paused application. The + * origin could be e.g. flip open or application going to fore ground. + */ + public void resumeApplication() + { + // Empty implementation as default. + } + + /** + * Releases the start waiters. + */ + protected void releaseStartWaiter(boolean doStart) + { + if (mApplicationStartLock != null) + { + synchronized (mApplicationStartLock) + { + mStartCmd = new Boolean(doStart); + mApplicationStartLock.notifyAll(); + } + } + } + + /** + * Sends shutdown notification to all the registered listeners. + */ + protected void doShutdown() + { + if (mListeners != null) + { + Enumeration enumer = mListeners.elements(); + while (enumer.hasMoreElements()) + { + ShutdownListener listener = + (ShutdownListener)enumer.nextElement(); + listener.shuttingDown(); + } + } + } +}