javacommons/utils/javasrc/com/nokia/mj/impl/rt/support/ApplicationUtils.java
changeset 21 2a9601315dfc
child 48 e0d6e9bd3ca7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/utils/javasrc/com/nokia/mj/impl/rt/support/ApplicationUtils.java	Mon May 03 12:27:20 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.
+ * <p>
+ * 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.
+ * <p>
+ * The runtime implementation hides the solving of the correct application
+ * when method <code>getInstace</code> is called. However it must be noted
+ * that if the call is made some common thread, the <code>getInstace</code>
+ * might not able to solve the correct application.
+ * <p>
+ * Example how to register a shutdown listener.
+ * <pre>
+ * 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...
+ *          }
+ *      }
+ *</pre>
+ * @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 (<code>Class.forname & Class.newInstance</code>) and
+     * the name of the class is a combination of PACKAGE_PREFIX +
+     * &lt;value of system property PACKAGE_END_PROPERTY_NAME &gt;
+     * + .&lt;value of PORTCLASS member variable &gt.
+     */
+    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.
+     * <p>
+     * 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.
+     * <p>
+     * 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.
+     * <p>
+     * The design decision was that all the API implementation should use this
+     * method for making security checkings and avoid using the
+     * <code>checkPermission</code> method <code>AccessController</code> class,
+     * which is left for application usage only.
+     * <p>
+     * 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
+     * <code>AccessController</code> 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.
+     * <p>
+     * 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.
+     * <p>
+     * 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();
+            }
+        }
+    }
+}