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(); + } + } + } +}