FileDocCategorySizeDatePackage
RegistryImpl.javaAPI DocphoneME MR2 API (J2ME)52940Wed May 02 18:00:44 BST 2007com.sun.midp.content

RegistryImpl

public final class RegistryImpl extends Object
Implementation of Content Handler registry. It maintains the set of currently registered handlers and updates to the file that holds the permanent set. The RegistryImpl class maintains an array of the current registrations that is initialized on first use.

Fields Summary
private static com.sun.midp.security.SecurityToken
classSecurityToken
This class has a different security domain than the MIDlet suite
private final Hashtable
activeInvocations
The set of active Invocations.
private static Hashtable
registries
The set of active RegistryImpls.
private static final Object
mutex
The mutex used to avoid corruption between threads.
private ResponseListenerImpl
listenerImpl
Implementation of the listener.
private ContentHandlerImpl
handlerImpl
The ContentHandlerImpl that matches the classname of this Registry.
private Registry
registry
The Registry that is delegating to this RegistryImpl.
final AppProxy
application
The AppProxy for this registry.
int
responseCalls
Count of responses received.
Constructors Summary
private RegistryImpl(String classname)
RegistryImpl constructor and insert the instance in the list of registered applications.

param
classname the application class for this instance
exception
ContentHandlerException if the classname is not registered either as a MIDlet or a content handler
exception
NullPointerException if classname is null
exception
SecurityException is thrown if the caller does not have the correct permision

        try {
            // Get the application for the class
            application = AppProxy.getCurrent().forClass(classname);
        } catch (ClassNotFoundException cnfe) {
            throw new ContentHandlerException("not an application",
                         ContentHandlerException.NO_REGISTERED_HANDLER);
        } catch (IllegalArgumentException iae) {
            throw new ContentHandlerException("not an application",
                         ContentHandlerException.NO_REGISTERED_HANDLER);
        }

        /* Remember the ContentHandlerImpl, if there is one. */
        handlerImpl = getServer(application);

        if (handlerImpl == null && (!application.isRegistered())) {
            // Classname is not a registered MIDlet or ContentHandler; fail
            throw new ContentHandlerException("not a registered MIDlet",
                         ContentHandlerException.NO_REGISTERED_HANDLER);
        }
    
Methods Summary
public voidcancelGetResponse()
Cancels a pending getResponse. This method will force a Thread blocked in a call to the getResponse method for the same application context to return early. If no Thread is blocked; this call has no effect.

        InvocationStore.cancel();
    
static ContentHandlerImplcheckConflicts(ContentHandlerImpl handler)
Check for conflicts between a proposed new handler and the existing handlers. If the handler is being replaced it will be returned. Locate and return any existing handler for the same classname.

param
handler the new content handler
return
a ContentHandlerImpl within the suite that need to be removed to register the new ContentHandler

        ContentHandlerImpl[] handlers = RegistryStore.findConflicted(handler.ID);
        ContentHandlerImpl existing = null;

        if (handlers != null) {
            switch (handlers.length) {
                case 0:
                    break;
                case 1:
                    if (handler.classname.equals(handlers[0].classname)) {
                        existing = handlers[0];
                        break;
                    }
                default:
                    throw new ContentHandlerException(
                        "ID would be ambiguous: " + handler.ID,
                        ContentHandlerException.AMBIGUOUS);
            }
        }

        if (existing == null) {
            existing = RegistryStore.getHandler(handler.storageId, handler.classname);
        }

        return existing;
    
static voidcleanup(int suiteId, java.lang.String classname)
Cleanup as necessary for this classname, both for ContentHandlerServer and the registry. Cleanup is required by the fault handling descriptions in {@link javax.microedition.content.ContentHandlerServer}.
  • If an Invocation with a status of ACTIVE is dequeued by the content handler, but the handler does not call {@link javax.microedition.content.ContentHandlerServer#finish finish} or make a request to chain a new Invocation to the ACTIVE invocation before the content handler exits, then the AMS MUST complete the request with an ERROR status.
  • If the content handler is not running, or exits before processing all queued requests or responses, then it MUST be started. The content handler is expected to dequeue at least one invocation that was queued before it was started. If it does not dequeue any pending Invocations, then Invocations that were in the queue for the content handler before it was started MUST be handled as follows:
    • Invocation requests with a status of ACTIVE are completed with the ERROR status.
    • Invocation responses are discarded.
    • Invocations queued after the content handler was started are retained and will require it to be restarted.

param
suiteId the MIDletSuite to cleanup after
param
classname the application class to cleanup

        InvocationImpl invoc = null;
        while ((invoc =
                InvocationStore.getCleanup(suiteId, classname)) != null) {
            invoc.setStatus(Invocation.ERROR);
        }
    
public ContentHandler[]findHandler(InvocationImpl invoc)
Gets the registered content handlers that could be used for this Invocation. Only handlers accessible to the application are considered. The values for ID, type, URL, and action are used in the following order:
  • If the ID is non-null, then the set of candidate handlers is determined from the {@link #forID forID} method with the parameter exact set to false. If there is an exact match it MUST be returned as the first handler. The type and URL are ignored. If there are no handlers that match the requested ID then a ContentHandlerException is thrown.
  • If the ID and type are null and the URL is non-null and If the protocol supports typing of content, then the type is determined as described in {@link Invocation#findType}. If the type cannot be determined from the content, the type is set to null.
  • If the ID is null and type is non-null, then the set of candidate handlers is determined from the {@link #forType forType} method. If there are no handlers that match the requested type then a ContentHandlerException is thrown.
  • If both the ID and type are null and the URL is non-null and if the protocol does not support typing of content or the type was not available from the content, then the set of candidate handlers includes any handler with a suffix that matches the end of the path component of the URL. If there are no handlers that match a registered suffix then a ContentHandlerException is thrown.
  • If the ID, type, and URL are all null, the set of candidate handlers includes all of the accessible handlers.
  • If the action is non-null, the set of candidate handlers is reduced to contain only handlers that support the action.
  • If the set of candidate handlers is empty then a ContentHandlerException is thrown.

The calling thread blocks while the ID and type are being determined. If a network access is needed there may be an associated delay.

param
invoc the ID, type, action, and URL that are needed to identify one or more content handlers; must not be null
return
an array of the ContentHandler(s) that could be used for this Invocation; MUST NOT be null;
exception
IOException is thrown if access to the content fails
exception
ContentHandlerException is thrown with a reason of NO_REGISTERED_HANDLER if there is no registered content handler that matches the requested ID, type, URL, and action
exception
IllegalArgumentException is thrown if ID, type, URL, and action are all null or if the content is accessed via the URL and the URL is invalid
exception
NullPointerException is thrown if the invocation is null
exception
SecurityException is thrown if access to the content is not permitted

        ContentHandler[] handlers = null;
        if (invoc.getID() != null) {
            ContentHandler handler = forID(invoc.getID(), false);
            if (handler != null) {
                handlers = new ContentHandler[1];
                handlers[0] = handler;
            }
        } else {
            String action = invoc.getAction();

            // ID is null
            synchronized (mutex) {
                // Inhibit types change while doing lookups
                if (invoc.getType() == null &&
                    invoc.getURL() != null) {
                    try {
                        invoc.findType();
                    } catch (ContentHandlerException che) {
                        // Type is null
                    }
                }
                if (invoc.getType() != null) {
                    // The type is known; lookup the handlers
                    handlers = forType(invoc.getType());
                } else if (invoc.getURL() != null) {
                    /**
                     * Call platform specific function for
                     * getting handler by URL
                     */
                    ContentHandler suitable =
                        RegistryStore.getByURL(getID(), invoc.getURL(), action);

                    if (suitable != null) {
                        handlers = new ContentHandler[1];
                        handlers[0] = suitable;
                    }
                } else if (action != null) {
                    handlers = forAction(action);
                    action = null;
                } else {
                    throw new IllegalArgumentException(
                                "not ID, type, URL, or action");
                }

                // Set of candidate handlers; check for matching action
                if (handlers != null && action != null) {
                    int rem = 0;    // number of handlers to remove
                    for (int i = 0; i < handlers.length; i++) {
                        if (!handlers[i].hasAction(action)) {
                            handlers[i] = null;
                            rem++;
                        }
                    }
                    if (rem > 0) {
                        int newsz = handlers.length - rem;
                        if (newsz > 0) {
                            ContentHandler[] newhand =
                                                new ContentHandler[newsz];
                            int j;
                            int k;
                            for (j = k = 0; j < newsz; j++) {
                                while (handlers[k] == null) {
                                    k++;
                                }
                                newhand[j] = handlers[k++];
                            }
                            handlers = newhand;
                        } else {
                            handlers = null;
                        }
                    }
                }
            }
        }


        if (handlers == null || handlers.length == 0) {
            throw new ContentHandlerException("no registered handler",
                            ContentHandlerException.NO_REGISTERED_HANDLER);
        }
        return handlers;
    
public ContentHandler[]forAction(java.lang.String action)
Gets the registered content handlers that support the action.

Only content handlers that are visible and accessible to this application are returned.

param
action content handlers for which the action is supported
return
an array of the ContentHandlers registered for the action; MUST NOT be null; an empty array is returned if no ContentHandlers are accessible to this application
exception
NullPointerException if action is null

        return RegistryStore.findHandler(getID(), RegistryStore.FIELD_ACTIONS,
                                                                    action);
    
public ContentHandlerforID(java.lang.String ID, boolean exact)
Gets the registered content handler for the ID. The query can be for an exact match or for the handler matching the prefix of the requested ID.

Only a content handler which is visible to and accessible to this application will be returned.

param
ID the content handler application ID of the content handler requested
param
exact true to require an exact match; false to allow a registered content handler ID to match a prefix of the requested ID
return
the content handler that matches the ID, otherwise null
exception
NullPointerException if ID is null

        return RegistryStore.getHandler(getID(), ID, 
                exact? RegistryStore.SEARCH_EXACT: RegistryStore.SEARCH_PREFIX);
    
public ContentHandler[]forSuffix(java.lang.String suffix)
Gets all of the content handlers for the suffix. Only content handlers that are visible and accessible to this application are returned.

param
suffix the suffix to be used to get the associated content handlers
return
an array of the ContentHandlers registered for the suffix; MUST NOT be null. An empty array is returned if there are none accessible to this application
exception
NullPointerException if suffix is null

        return RegistryStore.findHandler(getID(), RegistryStore.FIELD_SUFFIXES,
                                                                    suffix);
    
public ContentHandler[]forType(java.lang.String type)
Gets the registered content handlers for the content type.

Only content handlers that are visible and accessible to this application are returned.

param
type the type of the requested content handlers
return
an array of the ContentHandlers registered for the type; MUST NOT be null. An empty array is returned if there are no ContentHandlers accessible to this application.
exception
NullPointerException if type is null

        return RegistryStore.findHandler(getID(), RegistryStore.FIELD_TYPES,
                                                                        type);
    
public java.lang.String[]getActions()
Gets all of the actions of the registered content handlers. After a successful registration the content handler's action(s), if any, will appear in this list.

Only content handlers that this application is allowed to access will be included.

return
an array of content handler actions; MUST NOT be null

        return RegistryStore.getValues(getID(), RegistryStore.FIELD_ACTIONS);
    
public java.lang.StringgetID()
Gets the content handler ID for the current application. The ID uniquely identifies the application which contains the content handler. The application ID is assigned when the application is installed. If the application is a content handler then the ID must be the content handler ID.

return
the ID; MUST NOT be null

        return (handlerImpl != null) ?
            handlerImpl.getID() : application.getApplicationID();
    
public java.lang.String[]getIDs()
Gets all of the IDs of the registered content handlers.

Only content handlers that this application is allowed to access will be included.

return
an array of content handler IDs; MUST NOT be null

        return RegistryStore.getValues(getID(), RegistryStore.FIELD_ID);
    
public RegistrygetRegistry()
Gets the Registry that is delegating to this RegistryImpl.

return
a Registry instance
see
#setRegistry

        return registry;
    
public static com.sun.midp.content.RegistryImplgetRegistryImpl(java.lang.String classname, java.lang.Object token)
Gets the RegistryImpl for the application class. The SecurityToken is needed to call from the public API package. The application is identified by the classname that implements the lifecycle of the Java runtime environment. The classname must be the name of a registered application class or a registered content handler.

For a MIDP implementation, application classes must be registered with the MIDlet-<n> attribute; content handlers are registered with the MicroEdition-Handler-<n> attribute or the {@link #register register} method.

When the RegistryImpl is created (the first time) all of the existing Invocations are marked. They will be subject to {@link #cleanup} when the MIDlet exits.

param
classname the application class
param
token the security token needed to control access to the impl
return
a RegistryImpl instance providing access to content handler registrations and invocations; MUST NOT be null
exception
ContentHandlerException is thrown with a reason of NO_REGISTERED_HANDLER if there is no content handler registered for the classname in the current application
exception
NullPointerException if classname is null


                                                                                                                                                                                           
        
                            
     
    
    AppProxy.checkAPIPermission(token);
        return getRegistryImpl(classname);
    
static com.sun.midp.content.RegistryImplgetRegistryImpl(java.lang.String classname)
Gets the RegistryImpl for the application class. The application is identified by the classname that implements the lifecycle of the Java runtime environment. The classname must be the name of a registered application class or a registered content handler.

For a MIDP implementation, application classes must be registered with the MIDlet-<n> attribute; content handlers are registered with the MicroEdition-Handler-<n> attribute or the {@link #register register} method.

When the RegistryImpl is created (the first time) all of the existing Invocations are marked. They will be subject to {@link #cleanup} when the MIDlet exits.

param
classname the application class
return
a RegistryImpl instance providing access to content handler registrations and invocations; MUST NOT be null
exception
ContentHandlerException is thrown with a reason of NO_REGISTERED_HANDLER if there is no content handler registered for the classname in the current application
exception
NullPointerException if classname is null

        // Synchronize between competing operations
        RegistryImpl curr = null;
        synchronized (mutex) {
            // Check if class already has a RegistryImpl
            curr = (RegistryImpl)registries.get(classname);
            if (curr != null) {
                // Check that it is still a CH or MIDlet
                if (curr.handlerImpl == null &&
                    (!curr.application.isRegistered())) {
                    // Classname is not a registered MIDlet or ContentHandler
                    throw new
                        ContentHandlerException("not a registered MIDlet",
                            ContentHandlerException.NO_REGISTERED_HANDLER);
                }
                return curr;
            }

            // Create a new instance and insert it into the list
            curr = new RegistryImpl(classname);
            registries.put(classname, curr);
        }

        /*
         * Unsynchronized, a new RegistryImpl has been created.
         * Mark any existing Invocations so that at cleanup the pre-existing
         * Invocations can be handled properly.
         */
        InvocationStore.setCleanup(curr.application.getStorageId(),
                                   classname, true);
        return curr;
    
public InvocationgetResponse(boolean wait, InvocationImpl resp)
Gets the next Invocation response pending for this application. The method blocks until an Invocation response is available, but not for longer than the timeout period. The method can be unblocked with a call to {@link #cancelGetResponse}. The application can process the Invocation based on its status. The status is one of OK, CANCELLED, or ERROR.

If the Invocation was invoked with {@link #invoke(InvocationImpl invocation, InvocationImpl previous)}, the getPrevious method MUST return the previous Invocation. If the status of the previous Invocation is HOLD then its status is restored to ACTIVE.

If the original Invocation instance is reachable, then it MUST be updated with the values from the response and be returned to the application. If it is not reachable, then a new instance is returned from getResponse with the response values.

param
wait true if the method MUST wait for an Invocation if one is not currently available; otherwise false
param
resp an InvocationImpl to fill in with the response
exception
IllegalArgumentException if the context is not valid
return
the next pending response Invocation or null if the timeout expires and no Invocation is available or if cancelled with {@link #cancelGetResponse}
see
#invoke
see
#cancelGetResponse

        // Application has tried to get a response; reset cleanup flags on all
        if (responseCalls == 0) {
            InvocationStore.setCleanup(application.getStorageId(),
                                       application.getClassname(), false);
        }
        responseCalls++;

        // Find a response for this application and context
        InvocationImpl invoc =
            InvocationStore.getResponse(resp, application.getStorageId(),
                                        application.getClassname(), wait);
        if (invoc != null) {
            // Keep track of how many responses have been recevied;

            /*
             * If there was a previous Request/Tid
             * find or create the previous Invocation
             * and update its state.
             */
            InvocationImpl existing = removeActive(invoc);
            if (existing != null) {
                /*
                 * Copy mutable fields to the existing Invocation
                 * Continue with the pre-existing Invocation
                 */
                existing.ID = invoc.ID;
                existing.arguments = invoc.arguments;
                existing.data = invoc.data;
                existing.url = invoc.url;
                existing.type = invoc.type;
                existing.action = invoc.action;
                existing.status = invoc.status;
                invoc = existing;
            } else {
                // If there is a previousTid then restore the previous
                if (invoc.previousTid != 0) {
                    /*
                     * There will be a previous Invocation unless the app has
                     * already finished it. It will have a HOLD status.
                     */
                    invoc.previous =
                        InvocationStore.getByTid(invoc.previousTid, 0);
                }
            }
            if (invoc.previous != null &&
                invoc.previous.status == Invocation.HOLD) {
                // Restore ACTIVE status to a previously HELD Invocation
                invoc.previous.setStatus(Invocation.ACTIVE);
            }

            // Make an attempt to gain the foreground
            if (invoc.invokingSuiteId != MIDletSuite.UNUSED_SUITE_ID &&
                invoc.invokingClassname != null) {

                // Strong FG transition requested
                application.requestForeground(invoc.invokingSuiteId,
                                              invoc.invokingClassname);
            }

            return invoc.invocation;
        }
        return null;
    
public ContentHandlerImplgetServer()
Gets the registered content handler for the application class of this RegistryImpl.

return
the content handler for the registered classname if it was registered by this application. Otherwise, it returns null.
exception
NullPointerException if classname is null

        return handlerImpl;
    
ContentHandlerImplgetServer(AppProxy appl)
Gets the content handler for the specified application class. The classname must be a class in the current application.

param
appl the application to look up a server fro
return
the content handler information for the registered classname if the classname was registered by this application, otherwise return null
exception
NullPointerException if classname is null

        synchronized (mutex) {

            String classname = appl.getClassname();
            int storageId = appl.getStorageId();

            ContentHandlerImpl handler = RegistryStore.getHandler(storageId, classname);

            if (handler != null) {
                handler.appname = appl.getApplicationName();
                handler.version = appl.getVersion();
                handler.authority = appl.getAuthority();
            }

            return handler;
        }
    
public java.lang.String[]getSuffixes()
Gets all of the suffixes of the registered content handlers. After a successful registration the content handler's suffix(es), if any, will appear in this list.

Only content handlers that this application is allowed to access will be included.

return
an array of content handler suffixes; MUST NOT be null

        return RegistryStore.getValues(getID(), RegistryStore.FIELD_SUFFIXES);
    
public java.lang.String[]getTypes()
Gets all of the content types for which there are registered handlers. After a successful registration, the content handler's type(s), if any, will appear in this list.

Only content handlers that this application is allowed to access will be included.

return
an array of types; MUST NOT be null

        return RegistryStore.getValues(getID(), RegistryStore.FIELD_TYPES);
    
private voidinsertActive(InvocationImpl invoc)
Insert an Invocation to the set of active Invocations.

param
invoc an Invocation to add

        Integer tid = new Integer(invoc.tid);
        activeInvocations.put(tid, invoc);
    
public booleaninvoke(InvocationImpl invocation, InvocationImpl previous)
Checks the Invocation and uses the ID, type, URL, and action, if present, to find a matching ContentHandler and queues this request to it.

If the previous Invocation is null, then a new transaction is created; otherwise, this Invocation will use the same transaction as the previous Invocation.

The status of this Invocation MUST be INIT. If there is a previous Invocation, that Invocation MUST have a status of ACTIVE.

Candidate content handlers are found as described in {@link #findHandler findHandler}. If any handlers are found, one is selected for this Invocation. The choice of content handler is implemention dependent.

If there is a non-null previous Invocation, its status is set to HOLD. A copy of the Invocation is made, the status is set to ACTIVE and then queued to the target content handler. If the invoked content handler is not running, it MUST be started as described in Invocation Processing.

The calling thread blocks while the content handler is being determined. If a network access is needed, there may be an associated delay.

param
invocation the Invocation containing the target ID, type, actions, arguments, and responseRequired parameters; MUST NOT be null
param
previous a previous Invocation for this Invocation; may be null
return
true if the application MUST first voluntarily exit before the content handler can be started; false otherwise
exception
IllegalArgumentException is thrown if:
  • the ID, type, URL, and action are all null, or
  • the argument array contains any null references
exception
IOException is thrown if access to the content fails
exception
ContentHandlerException is thrown with a reason of:
  • TYPE_UNKNOWN if the type is not set and cannot be determined from the URL, or
  • NO_REGISTERED_HANDLER if there is no registered content handler that matches the requested ID, type, url or actions.
exception
IllegalStateException is thrown if the status of this Invocation is not INIT or if the status of the previous Invocation, if any, is not ACTIVE
exception
NullPointerException is thrown if the invocation is null
exception
SecurityException if an invoke operation is not permitted

        synchronized (mutex) {
            // Locate the content handler for this Invocation.
            ContentHandlerImpl handler =
                        (ContentHandlerImpl)findHandler(invocation)[0];

            // Fill in information about the invoking application
            invocation.invokingID = getID();
            invocation.invokingSuiteId = application.getStorageId();
            invocation.invokingClassname = application.getClassname();
            invocation.invokingAuthority = application.getAuthority();
            invocation.invokingAppName = application.getApplicationName();

            boolean shouldExit = invocation.invoke(previous, handler);
            // Remember the invoked invocation for getResponse
            insertActive(invocation);

            return shouldExit;
        }
    
static ContentHandlerImplnewHandler(java.lang.String classname, java.lang.String[] types, java.lang.String[] suffixes, java.lang.String[] actions, ActionNameMap[] actionnames, java.lang.String id, java.lang.String[] accessRestricted, AppProxy appl)
Create and initialize a new ContentHandler server with type(s), suffix(es), and action(s), action name(s), access restrictions and content handler ID. Compute the application name, ID, and version

param
classname the application class name that implements this content handler. The value MUST NOT be null and MUST implement the lifecycle of the Java runtime
param
types an array of types to register; if null it is treated the same as an empty array
param
suffixes an array of suffixes to register; if null it is treated the same as an empty array
param
actions an array of actions to register; if null it is treated the same as an empty array
param
actionnames an array of ActionNameMaps to register; if null it is treated the same as an empty array
param
id the content handler ID; if null a non-null value MUST be provided by the implementation
param
accessRestricted the IDs of applications and content handlers that are allowed visibility and access to this content handler; if null then all applications and content handlers are allowed access; if non-null, then ONLY applications and content handlers with matching IDs are allowed access.
param
appl the AppProxy registering the handler
return
the registered ContentHandler; MUST NOT be null
exception
NullPointerException if any of the following items is null:
  • classname
  • any types, suffixes, actions, actionnames, or accessRestricted array element
  • ,
  • msuite
exception
IllegalArgumentException can be thrown:
  • if any of the types, suffix, actions, or accessRestricted strings have a length of zero, or
  • if the classname does not implement the valid lifecycle for the Java Runtime,
  • if the sequence of actions in each ActionNameMap is not the same as the sequence of actions, or
  • if the locales of the ActionNameMaps are not unique, or.
  • if the length of the accessRestricted array is zero.
  • .

        // Default the ID if not supplied
        if (id == null) {
            // Generate a unique ID based on the MIDlet suite
            id = appl.getDefaultID();
        }

        // Create a new ContentHandler instance
        ContentHandlerImpl handler =
                new ContentHandlerImpl(types, suffixes, actions,
                                       actionnames, id, accessRestricted,
                                       appl.getAuthority());
        handler.classname = classname;
        handler.storageId = appl.getStorageId();
        handler.appname = appl.getApplicationName();
        handler.version = appl.getVersion();
        return handler;
    
public ContentHandlerImplregister(java.lang.String classname, java.lang.String[] types, java.lang.String[] suffixes, java.lang.String[] actions, ActionNameMap[] actionnames, java.lang.String id, java.lang.String[] accessRestricted)
Registers the application class using content type(s), suffix(es), and action(s), action name(s), access restrictions and content handler ID.

An application can use this method to replace or update its own registrations that have the same classname with new information. The update occurs atomically; the update to the registry either occurs or it does not.

The content handler may request to the following items:

  • zero or more content types
  • zero or more suffixes
  • zero or more actions
  • zero or more mappings from actions to action names
  • zero or more access restrictions
  • a optional application ID

If no exceptions are thrown, then the type(s), suffix(s), action(s), action names, and access restrictions, and ID will be registered for the application class.

If an exception is thrown, then the previous registration, if any, will not be removed or modified.

param
classname the application class name that implements this content handler. The value MUST NOT be null and MUST implement the lifecycle of the Java runtime
param
types an array of types to register; if null it is treated the same as an empty array
param
suffixes an array of suffixes to register; if null it is treated the same as an empty array
param
actions an array of actions to register; if null it is treated the same as an empty array
param
actionnames an array of ActionNameMaps to register; if null it is treated the same as an empty array
param
id the content handler ID; if null a non-null value MUST be provided by the implementation
param
accessRestricted the IDs of applications and content handlers that are allowed visibility and access to this content handler; if null then all applications and content handlers are allowed access; if non-null, then ONLY applications and content handlers with matching IDs are allowed access.
return
the registered ContentHandler; MUST NOT be null
exception
NullPointerException if any of the following items is null:
  • classname
  • any types, suffixes, actions, actionnames, or accessRestricted array element
exception
IllegalArgumentException can be thrown:
  • if any of the types, suffix, actions, or accessRestricted strings have a length of zero, or
  • if the classname does not implement the valid lifecycle for the Java Runtime,
  • if the sequence of actions in each ActionNameMap is not the same as the sequence of actions, or
  • if the locales of the ActionNameMaps are not unique, or.
  • if the length of the accessRestricted array is zero.
  • .
exception
ClassNotFoundException if the classname is not present
exception
ContentHandlerException with a error code of {@link ContentHandlerException#AMBIGUOUS} if id is a prefix of any registered handler or if any registered handler ID is a prefix of this ID
exception
SecurityException if registration is not permitted

        application.checkRegisterPermission("register");

        // May throw ClassNotFoundException or IllegalArgumentException
        AppProxy appl = application.forClass(classname);

        synchronized (mutex) {
            // Create a new ContentHandler instance
            ContentHandlerImpl handler =
                newHandler(classname, types, suffixes, actions,
                           actionnames, id, accessRestricted, appl);
            handler.registrationMethod = ContentHandlerImpl.REGISTERED_DYNAMIC;

            ContentHandlerImpl conflict = checkConflicts(handler);
            if (conflict != null) {
                unregister(classname);
            }

            RegistryStore.register(handler);
            setServer(handler);

            if (AppProxy.LOG_INFO) {
                appl.logInfo("Register: " + classname +
                             ", id: " + handler.getID());
            }

            return handler;
        }
    
public booleanreinvoke(InvocationImpl invocation)
Reinvokes the Invocation and uses the ID, type, URL, and action to find a matching ContentHandler and re-queues this request to it. Reinvocation is used to delegate the handling of an active Invocation to another content handler. The processing of the Invocation instance is complete and the status is set to OK. Responses to the reinvocation will be queued to the original invoking application, if a response is required.

Candidate content handlers are found as described in {@link #findHandler findHandler}. If any handlers are found, one is selected for this Invocation. The choice of content handler is implementation dependent.

The status of this Invocation is set to OK. A copy of the Invocation is made, the status is set to ACTIVE, and then queued to the target content handler. If the invoked content handler application is not running, it MUST be started as described in Invocation Processing.

The calling thread blocks while the content handler is being determined. If a network access is needed there may be an associated delay.

param
invocation an Invocation containing the target ID, type, action, arguments, and responseRequired parameters; MUST NOT be null
return
true if the application MUST first voluntarily exit before the content handler can be started; false otherwise
exception
IllegalArgumentException is thrown if:
  • the ID, type, and URL are all null, or
  • the argument array contains any null references
exception
IOException is thrown if access to the content fails
exception
ContentHandlerException is thrown with a reason of: NO_REGISTERED_HANDLER if there is no registered content handler that matches the requested ID, type, URL, and action
exception
NullPointerException is thrown if the invocation is null
exception
SecurityException if an invoke operation is not permitted or if access to the content is not permitted

        synchronized (mutex) {
            // Locate the content handler for this Invocation.
            ContentHandlerImpl handler =
                                (ContentHandlerImpl)findHandler(invocation)[0];

            // Save the TID in case the invoke fails
            int tid = invocation.tid;

            // The information about the invoking application is already set
            boolean shouldExit = invocation.invoke(null, handler);

            /*
             * Only if the invoke succeeds can the original Invocation be
             * discarded.
             * Restore the tid so the correct native invoc is disposed.
             */
            invocation.tid = tid;
            invocation.setStatus(InvocationImpl.DISPOSE);
            invocation.setStatus(Invocation.OK);

            return shouldExit;
        }
    
private InvocationImplremoveActive(InvocationImpl invoc)
Remove an Invocation from the set of active Invocations.

param
invoc an Invocation to remvoe
return
the active Invocation or null if not found

        Integer tid = new Integer(invoc.tid);
        return (InvocationImpl)activeInvocations.remove(tid);
    
public voidsetListener(ResponseListener listener)
Sets the listener to be notified when a new response is available for the application context. The request must be retrieved using {@link #getResponse getResponse}.

param
listener the listener to register; null to remove the listener.


        // Create or update the listener implementation
        synchronized (this) {
            if (listener != null || listenerImpl != null) {
                // Create or update the active listener thread
                if (listenerImpl == null) {
                    listenerImpl =
                        new ResponseListenerImpl(this, listener);
                } else {
                    listenerImpl.setListener(listener);
                }

                // If the listener thread no longer needed; clear it
                if (listener == null) {
                    listenerImpl = null;
                }
            }
        }
    
public voidsetRegistry(Registry newRegistry)
Sets the Registry that is delegating to this instance. Settable only once. Synchronization is performed in {@link javax.microedition.content.Registry#register}.

param
newRegistry the Registry delegating to this
see
#getRegistry

        if (registry == null) {
            registry = newRegistry;
        }
    
public voidsetServer(ContentHandlerImpl server)
Sets the ContentHandlerImpl; update any active RegistryImpl. Replaces the entry in RegisteredTypes list as well.

param
server the ContentHandlerImpl for this RegistryImpl
see
javax.microedition.content.ContentHandlerServerImpl

        synchronized (mutex) {
            // Update the RegistryImpl, if any, this is a server for
            RegistryImpl impl = (RegistryImpl)registries.get(server.classname);
            if (impl != null) {
                impl.handlerImpl = server;
            }
        }
    
public booleanunregister(java.lang.String classname)
Removes the content handler registration for the application class and any bindings to the content handler name, content type(s), suffix(es), action(s), and access restrictions.

param
classname the name of the content handler class
return
if the content handler was successfully removed true is returned, false otherwise
exception
NullPointerException if classname is null

        if (classname == null) {
            throw new NullPointerException(
                               "classname argument can not be null");
        }

        synchronized (mutex) {

            ContentHandlerImpl curr = null;
            RegistryImpl reg = (RegistryImpl)registries.get(classname);

            if (reg != null) {
                curr = reg.getServer();
            } else {
                try {
                    curr = RegistryStore.getHandler(application.getStorageId(), classname);
                } catch (IllegalArgumentException iae) {
                    // Empty class name falls down without further processing.
                }
            }

            if (curr != null) {
                RegistryStore.unregister(curr.getID());
                int suiteId = application.getStorageId();
                if (reg != null && classname.equals(curr.classname) &&
                        suiteId == curr.storageId) {
                    reg.handlerImpl = null;
                }
                return true;
            }
        }

        return false;