javacommons/utils/javasrc/com/nokia/mj/impl/rt/support/ApplicationUtils.java
branchRCL_3
changeset 19 04becd199f91
child 48 e0d6e9bd3ca7
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     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      * &lt;value of system property PACKAGE_END_PROPERTY_NAME &gt;
       
   113      * + .&lt;value of PORTCLASS member variable &gt.
       
   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 }