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

ContentHandlerImpl

public class ContentHandlerImpl extends Object implements javax.microedition.content.ContentHandler
The internal structure of a registered content handler.

Fields Summary
String
ID
The content handler ID. Lengths up to 256 characters MUST be supported. The ID may be null.
private String[]
types
The types that are supported by this content handler. If there are no types registered, the this field MUST either be null or refer to an empty array .
private String[]
suffixes
The suffixes of URLs that are supported by this content handler. If there are no suffixes, then this field MUST be null. The suffixes MUST include any and all punctuation. For example, the string ".png".
private String[]
actions
The actions that are supported by this content handler. If there are no actions, then this field MSUT be null.
javax.microedition.content.ActionNameMap[]
actionnames
The action names that are defined by this content handler.
final int
seqno
The sequence number of this instance; monotonic increasing.
private static int
nextSeqno
The next sequence number to assign.
RequestListenerImpl
listenerImpl
The RequestListenerImpl; if a listener is set.
public static final String[]
ZERO_STRINGS
Empty String array to return when needed.
private static final javax.microedition.content.ActionNameMap[]
ZERO_ACTIONNAMES
Empty ActionNameMap to return when needed.
private static final String
LOCALE_PROP
Property name for the current locale.
int
storageId
The MIDlet suite storagename that contains the MIDlet.
String
appname
The Name from parsing the Property for the MIDlet with this classname.
String
version
The Version parsed from MIDlet-Version attribute.
String
classname
The application class name that implements this content handler. Note: Only the application that registered the class will see the classname; for other applications the value will be null.
String
authority
The authority that authenticated this ContentHandler.
private String[]
accessRestricted
The accessRestrictions for this ContentHandler.
int
registrationMethod
Indicates content handler registration method: dynamic registration from the API, static registration from install or native content handler. Must be similar to enum in jsr211_registry.h
static final int
REGISTERED_STATIC
Content handler statically registered during installation
static final int
REGISTERED_DYNAMIC
Dynamically registered content handler via API
static final int
REGISTERED_NATIVE
Native platform content handler
int
requestCalls
Count of requests retrieved via {@link #getRequest}.
boolean
removed
Instance is a registration or unregistration. An unregistration needs only storageId and classname.
Constructors Summary
ContentHandlerImpl(String[] types, String[] suffixes, String[] actions, javax.microedition.content.ActionNameMap[] actionnames, String ID, String[] accessRestricted, String auth)
Construct a ContentHandlerImpl. Verifies that all strings are non-null

param
types an array of types to register; may be null
param
suffixes an array of suffixes to register; may be null
param
actions an array of actions to register; may be null
param
actionnames an array of ActionNameMaps to register; may be null
param
ID the content handler ID; may be null
param
accessRestricted the IDs of applications allowed access
param
auth application authority
exception
NullPointerException if any types, suffixes, actions, actionnames array element is null
exception
IllegalArgumentException is thrown if any of the types, suffix, or action strings have a length of zero or if the ID has a length of zero or contains any control character or space (U+0000-U+00020)


                                                                                                                                                      
       
                          
                             
        this();

        // Verify consistency between actions and ActionNameMaps
        if (actionnames != null && actionnames.length > 0) {
            if (actions == null) {
                throw new IllegalArgumentException("no actions");
            }
            int len = actions.length;
            for (int i = 0; i < actionnames.length; i++) {
                // Verify the actions are the same
                ActionNameMap map = actionnames[i];
                if (len != map.size()) {
                    throw new IllegalArgumentException("actions not identical");
                }

                for (int j = 0; j < len; j++) {
                    if (!actions[j].equals(map.getAction(j))) {
                        throw new
                            IllegalArgumentException("actions not identical");
                    }
                }

                /*
                 * Verify the locale of this ActionNameMap is not the same
                 * as any previous ActionNameMap.
                 */
                for (int j = 0; j < i; j++) {
                    if (map.getLocale().equals(actionnames[j].getLocale())) {
                        throw new IllegalArgumentException("duplicate locale");
                    }
                }
            }
        }

        // Check the ID for invalid characters (controls or space)
        if (ID != null) {
            int len = ID.length();
            if (len == 0) {
                    throw new IllegalArgumentException("invalid ID");
            }
            for (int i = 0; i < ID.length(); i++) {
                if (ID.charAt(i) <= 0x0020) {
                    throw new IllegalArgumentException("invalid ID");
                }
            }
            this.ID = ID;
        }
        this.types = copy(types);
        this.suffixes = copy(suffixes);
        this.actions = copy(actions);
        this.actionnames = copy(actionnames);
        this.accessRestricted = copy(accessRestricted);
        this.authority = auth;
    
protected ContentHandlerImpl(ContentHandlerImpl handler)
Initialize a new instance with the same information.

param
handler another ContentHandlerImpl
see
javax.microedition.content.ContentHandlerServerImpl

        this();
        types = handler.types;
        suffixes = handler.suffixes;
        ID = handler.ID;
        accessRestricted = handler.accessRestricted;
        actions = handler.actions;
        actionnames = handler.actionnames;
        listenerImpl = handler.listenerImpl;
        storageId = handler.storageId;
        classname = handler.classname;
        version = handler.version;
        registrationMethod = handler.registrationMethod;
        requestCalls = handler.requestCalls;
        authority = handler.authority;
        appname = handler.appname;
    
ContentHandlerImpl()
Constructor used to read handlers.

        seqno = nextSeqno++;
    
Methods Summary
public intaccessAllowedCount()
Gets the number of IDs allowed access by the content handler. The number of IDs must be equal to the length of the array of accessRestricted passed to {@link javax.microedition.content.Registry#register Registry.register}. If the number of IDs is zero then all applications and content handlers are allowed access.

return
the number of accessRestricteds

        return getAccessRestricted().length;
    
public voidcancelGetRequest()
Cancel a pending getRequest. This method will force a Thread blocked in a call to the getRequest method for the same application context to return early. If no Thread is blocked; this call has no effect.

        InvocationStore.cancel();
    
public static java.lang.String[]copy(java.lang.String[] strings)
Checks that all of the string references are non-null and not zero length. If either the argument is null or is an empty array the default ZERO length string array is used.

param
strings array to check for null and length == 0
return
a non-null array of strings; an empty array replaces null
exception
NullPointerException if any string ref is null
exception
IllegalArgumentException if any string has length == 0

        if (strings != null && strings.length > 0) {
            String[] copy = new String[strings.length];
            for (int i = 0; i < strings.length; i++) {
                if (strings[i].length() == 0) {
                    throw new IllegalArgumentException("string length is 0");
                }
                copy[i] = strings[i];

            }
            return strings;
        } else {
            return ZERO_STRINGS;
        }
    
private static javax.microedition.content.ActionNameMap[]copy(javax.microedition.content.ActionNameMap[] actionnames)
Checks that all of the actionname references are non-null.

param
actionnames array to check for null and length == 0
return
a non-null array of actionnames; an empty array replaces null
exception
NullPointerException if any string ref is null

        if (actionnames != null && actionnames.length > 0) {
            ActionNameMap[] copy = new ActionNameMap[actionnames.length];
            for (int i = 0; i < actionnames.length; i++) {
                // Check for null
                if (actionnames[i] == null) {
                    throw new NullPointerException();
                }
                copy[i] = actionnames[i];
            }
            return copy;
        } else {
            return ZERO_ACTIONNAMES;
        }
    
public static javax.microedition.content.ContentHandler[]copy(javax.microedition.content.ContentHandler[] handlers)
Copy an array of ContentHandlers making a new ContentHandler for each ContentHandler. Make copies of any mutiple object.

param
handlers the array of handlers duplicate
return
the new array of content handlers

        ContentHandler[] h = new ContentHandler[handlers.length];
        for (int i = 0; i < handlers.length; i++) {
            h[i] = handlers[i];
        }
        return h;
    
booleanequals(com.sun.midp.content.ContentHandlerImpl other)
Compare two ContentHandlerImpl's for equality. Classname, storageID, and seqno must match.

param
other another ContentHandlerImpl
return
true if the other handler is for the same class, storageID, and seqno.

        return seqno == other.seqno &&
            storageId == other.storageId &&
            classname.equals(other.classname);
    
protected booleanfinish(InvocationImpl invoc, int status)
Finish this Invocation and set the status for the response. The finish method may only be called when this Invocation has a status of ACTIVE or HOLD.

The content handler may modify the URL, type, action, or arguments before invoking finish. If the method {@link Invocation#getResponseRequired} returns true then the modified values MUST be returned to the invoking application.

param
invoc the Invocation to finish
param
status the new status of the Invocation. This MUST be either OK or CANCELLED.
return
true if the MIDlet suite MUST voluntarily exit before the response can be returned to the invoking application
exception
IllegalArgumentException if the new status of the Invocation is not OK or CANCELLED
exception
IllegalStateException if the current status of the Invocation is not ACTIVE or HOLD
exception
NullPointerException if the invocation is null

        int currst = invoc.getStatus();
          if (currst != Invocation.ACTIVE && currst != Invocation.HOLD) {
             throw new IllegalStateException("Status already set");
         }
        // If ACTIVE or HOLD it must be an InvocationImpl
        return invoc.finish(status);
    
private java.lang.Stringget(int index, java.lang.String[] strings)
Gets the value at index in the string array.

param
index of the value
param
strings array of strings to get from
return
string at index.
exception
IndexOutOfBounds if index is less than zero or greater than or equal length of the array.

        if (index < 0 || index >= strings.length) {
            throw new IndexOutOfBoundsException();
        }
        return strings[index];
    
public java.lang.StringgetAccessAllowed(int index)
Gets the nth ID of an application or content handler allowed access to this content handler. The ID returned for each index must be the equal to the ID at the same index in the accessAllowed array passed to {@link javax.microedition.content.Registry#register Registry.register}.

param
index the index of the ID
return
the nth ID
exception
IndexOutOfBoundsException if index is less than zero or greater than or equal to the value of the {@link #accessAllowedCount accessAllowedCount} method.

        return get(index, getAccessRestricted());
    
private java.lang.String[]getAccessRestricted()
Get accesses for the content handler.

return
array of allowed class names

        if (accessRestricted == null) {
            accessRestricted =
                RegistryStore.getArrayField(ID, RegistryStore.FIELD_ACCESSES);
        }
        return accessRestricted;
    
public java.lang.StringgetAction(int index)
Get the nth action supported by the content handler.

param
index the index into the actions
return
the nth action
exception
IndexOutOfBounds if index is less than zero or greater than or equal to the value of the {@link #getActionCount getActionCount} method.

        return get(index, getActions());
    
public intgetActionCount()
Get the number of actions supported by the content handler.

return
the number of actions

        return getActions().length;
    
public javax.microedition.content.ActionNameMapgetActionNameMap()
Get the mapping of actions to action names for the current locale supported by this content handler. The behavior is the same as invoking {@link #getActionNameMap} with the current locale.

return
an ActionNameMap; if there is no map available for the current locale, then it MUST be null

        String locale = System.getProperty(LOCALE_PROP);
        return (locale == null) ? null : getActionNameMap(locale);
    
public javax.microedition.content.ActionNameMapgetActionNameMap(java.lang.String locale)
Get the mapping of actions to action names for the requested locale supported by this content handler. The locale is matched against the available locales. If a match is found it is used. If an exact match is not found, then the locale string is shortened and retried if either of the "_" or "-" delimiters is present. The locale is shortened by retaining only the characters up to but not including the last occurence of the delimiter (either "_" or "-"). The shortening and matching is repeated as long as the string contains one of the delimiters. Effectively, this will try the full locale and then try without the variant or country code, if they were present.

param
locale for which to find an ActionNameMap; MUST NOT be null
return
an ActionNameMap; if there is no map available for the locale, then it MUST be null
exception
NullPointerException if the locale is null

        while (locale.length() > 0) {
            for (int i = 0; i < getActionNames().length; i++) {
                if (locale.equals(getActionNames()[i].getLocale())) {
                    return getActionNames()[i];
                }
            }
            int lastdash = locale.lastIndexOf('-");
            if (lastdash < 0) {
                break;
            }
            locale = locale.substring(0, lastdash);
        }
        return null;
    
public javax.microedition.content.ActionNameMapgetActionNameMap(int index)
Gets the nth ActionNameMap supported by the content handler.

param
index the index of the locale
return
the nth ActionNameMap
exception
IndexOutOfBoundsException if index is less than zero or greater than or equal to the value of the {@link #getActionNameMapCount getActionNameMapCount} method.

        if (index < 0 || index >= getActionNames().length) {
            throw new IndexOutOfBoundsException();
        }
        return getActionNames()[index];
    
public intgetActionNameMapCount()
Gets the number of action name maps supported by the content handler.

return
the number of action name maps

        return getActionNames().length;
    
private javax.microedition.content.ActionNameMap[]getActionNames()
Get actions names for the content handler.

return
array of actions names

        if (actionnames == null) {
            String [] locales =
                RegistryStore.getArrayField(ID, RegistryStore.FIELD_LOCALES);
            String [] names   =
                RegistryStore.getArrayField(ID, RegistryStore.FIELD_ACTION_MAP);

            actionnames = new ActionNameMap[locales.length];
            for (int index = 0; index < locales.length; index++) {
                String [] temp = new String[getActions().length];

                System.arraycopy(names,
                                 index * getActions().length,
                                 temp,
                                 0,
                                 getActions().length);

                actionnames[index] = new ActionNameMap(getActions(),
                                                       temp,
                                                       locales[index]);
            }
        }
        return actionnames;
    
java.lang.String[]getActions()
Get actions supported by the content handler.

return
array of actions supported

        if (actions == null) {
            actions =
                RegistryStore.getArrayField(ID, RegistryStore.FIELD_ACTIONS);
        }
        return actions;
    
public java.lang.StringgetAppName()
Returns the name used to present this content handler to a user. The value is extracted from the normal installation information about the content handler application.

return
the user-friendly name of the application; it MUST NOT be null

        loadAppData();
        return appname;
    
public java.lang.StringgetAuthority()
Gets the name of the authority that authorized this application. This value MUST be null unless the device has been able to authenticate this application. If non-null, it is the string identifiying the authority. For example, if the application was a signed MIDlet, then this is the "subject" of the certificate used to sign the application.

The format of the authority for X.509 certificates is defined by the MIDP Printable Representation of X.509 Distinguished Names as defined in class javax.microedition.pki.Certificate.

return
the authority; may be null

        loadAppData();
        return authority;
    
public java.lang.StringgetID()
Get the content handler ID. The ID uniquely identifies the application which contains the content handler. After registration and for every registered handler, the ID MUST NOT be null.

return
the ID; MUST NOT be null unless the ContentHandler is not registered.

        return ID;
    
public InvocationImplgetRequest(boolean wait, javax.microedition.content.Invocation invocation)
Gets the next Invocation request pending for this ContentHandlerServer. The method can be unblocked with a call to {@link #cancelGetRequest cancelGetRequest}. The application should process the Invocation as a request to perform the action on the content.

param
wait true if the method must wait for for an Invocation if one is not available; false if the method MUST NOT wait.
param
invocation an Invocation instance that will delegate to the result; if any
return
the next pending Invocation or null if no Invocation is available; null if cancelled with {@link #cancelGetRequest cancelGetRequest}
see
javax.microedition.content.Registry#invoke
see
javax.microedition.content.ContentHandlerServer#finish

        // Application has tried to get a request; reset cleanup flags on all
        if (requestCalls == 0) {
            InvocationStore.setCleanup(storageId, classname, false);
        }
        requestCalls++;

        InvocationImpl invoc =
            InvocationStore.getRequest(storageId, classname, wait);
        if (invoc != null) {
            // Keep track of number of requests delivered to the application
            AppProxy.requestForeground(invoc.invokingSuiteId,
                                       invoc.invokingClassname,
                                       invoc.suiteId,
                                       invoc.classname);
            invoc.invocation = invocation;
        }
        return invoc;
    
public java.lang.StringgetSuffix(int index)
Get the nth suffix supported by the content handler.

param
index the index into the suffixes
return
the nth suffix
exception
IndexOutOfBounds if index is less than zero or greater than or equal to the value of the {@link #getSuffixCount getSuffixCount} method.

        return get(index, getSuffixes());
    
public intgetSuffixCount()
Get the number of suffixes supported by the content handler.

return
the number of suffixes

        return getSuffixes().length;
    
java.lang.String[]getSuffixes()
Get suffixes supported by the content handler.

return
array of suffixes supported

        if (suffixes == null) {
            suffixes =
                RegistryStore.getArrayField(ID, RegistryStore.FIELD_SUFFIXES);
        }
        return suffixes;
    
public java.lang.StringgetType(int index)
Get the nth type supported by the content handler.

param
index the index into the types
return
the nth type
exception
IndexOutOfBounds if index is less than zero or greater than or equal to the value of the {@link #getTypeCount getTypeCount} method.

        return get(index, getTypes());
    
public intgetTypeCount()
Get the number of types supported by the content handler.

return
the number of types

        return getTypes().length;
    
java.lang.String[]getTypes()
Get types supported by the content handler.

return
array of types supported

        if (types == null) {
            types = RegistryStore.getArrayField(ID, RegistryStore.FIELD_TYPES);
        }
        return types;
    
public java.lang.StringgetVersion()
Gets the version number of this content handler. The value is extracted from the normal installation information about the content handler application.

return
the version number of the application; MAY be null

        loadAppData();
        return version;
    
private booleanhas(java.lang.String string, java.lang.String[] strings, boolean ignoreCase)
Determines if the string is in the array.

param
string to locate
param
strings array of strings to get from
param
ignoreCase true to ignore case in matching
return
true if the value is found
exception
NullPointerException if string is null

        int len = string.length(); // Throw NPE if null
        for (int i = 0; i < strings.length; i++) {
            if (strings[i].length() == len &&
                string.regionMatches(ignoreCase, 0, strings[i], 0, len)) {
                return true;
            }
        }
        return false;
    
public booleanhasAction(java.lang.String action)
Determine if a action is supported by the content handler.

param
action the action to check for
return
true if the action is supported; false otherwise
exception
NullPointerException if action is null

        return has(action, getActions(), false);
    
public booleanhasSuffix(java.lang.String suffix)
Determine if a suffix is supported by the content handler.

param
suffix the suffix to check for
return
true if the suffix is supported; false otherwise
exception
NullPointerException if suffix is null

        return has(suffix, getSuffixes(), true);
    
public booleanhasType(java.lang.String type)
Determine if a type is supported by the content handler.

param
type the type to check for
return
true if the type is supported; false otherwise
exception
NullPointerException if type is null

        return has(type, getTypes(), true);
    
public booleanisAccessAllowed(java.lang.String ID)
Determines if an ID MUST be allowed access by the content handler. Access MUST be allowed if the ID has a prefix that exactly matches any of the IDs returned by {@link #getAccessAllowed}. The prefix comparison is equivalent to java.lang.String.startsWith.

param
ID the ID for which to check access
return
true if access MUST be allowed by the content handler; false otherwise
exception
NullPointerException if accessRestricted is null

        ID.length();                // check for null
        if (getAccessRestricted().length == 0) {
            return true;
        }
        for (int i = 0; i < getAccessRestricted().length; i++) {
            if (ID.startsWith(getAccessRestricted()[i])) {
                return true;
            }
        }
        return false;
    
private voidloadAppData()
Initializes fields retrieved from AppProxy 'by-demand'.

        if (appname == null) {
            try {
                AppProxy app = 
                        AppProxy.getCurrent().forApp(storageId, classname);
                appname = app.getApplicationName();
                version = app.getVersion();
                authority = app.getAuthority();
            } catch (Throwable t) {
            }
            if (appname == null) {
                appname = "";
            }
        }
    
protected voidrequestNotify()
Notify the request listener of a pending request. Overridden by subclass.

    
public voidsetListener(javax.microedition.content.RequestListener listener)
Set the listener to be notified when a new request is available for this content handler. The request MUST be retrieved using {@link #getRequest}.

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

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

                // If the listener thread no longer needed; clear it
                if (listener == null) {
                    listenerImpl = null;
                }
            }
        }
    
public java.lang.StringtoString()
Debug routine to print the values.

return
a string with the details

        if (AppProxy.LOG_INFO) {
            StringBuffer sb = new StringBuffer(80);
            sb.append("CH:");
            sb.append(" classname: ");
            sb.append(classname);
            sb.append(", removed: ");
            sb.append(removed);
            sb.append(", flag: ");
            sb.append(registrationMethod);
            sb.append(", types: ");
            toString(sb, types);
            sb.append(", ID: ");
            sb.append(ID);
            sb.append(", suffixes: ");
            toString(sb, suffixes);
            sb.append(", actions: ");
            toString(sb, actions);
            sb.append(", access: ");
            toString(sb, accessRestricted);
            sb.append(", suiteID: ");
            sb.append(storageId);
            sb.append(", authority: ");
            sb.append(authority);
            sb.append(", appname: ");
            sb.append(appname);
            return sb.toString();
        } else {
            return super.toString();
        }
    
private voidtoString(java.lang.StringBuffer sb, java.lang.String[] strings)
Append all of the strings inthe array to the string buffer.

param
sb a StringBuffer to append to
param
strings an array of strings.

        if (strings == null) {
            sb.append("null");
            return;
        }
        for (int i = 0; i < strings.length; i++) {
            if (i > 0) {
                sb.append(':");
            }
            sb.append(strings[i]);
        }