Fields Summary |
---|
public javax.microedition.content.Invocation | invocationThe Invocation delegating to this instance.
This field is public to Invocation can set it.
This allows the implementation to pass a InvocationImpl to
back to the Invocation class and it can wrap it in an Invocation
before passing it to the application. |
String | urlThe URL of the content; may be null .
URLs of up to and including 256 characters in length MUST be
supported. A URL with a length of zero is treated as
null and is ignored.. |
String | typeThe content type; may be null . |
String | IDThe content handler ID; may be null |
String | actionThe action to perform on the content; may be null |
String[] | argumentsThe array of arguments; may be null |
int | argsLenThe length (returned by get0) of the argument array. |
byte[] | dataThe data array; may be null . |
int | dataLenThe length (returned by get0) needed for the data array. |
boolean | responseRequiredSet to true if the invoker must be notified of
completion. |
String | usernameThe username in case it is needed for authentication. |
String | passwordThe password in case it is needed for authentication. |
int | tidTransaction Identifier. |
int | suiteIdThe MIDlet suite that should handle this Invocation. |
String | classnameThe classname of the MIDlet to deliver to. |
int | statusThe status of the request; one of
{@link Invocation#ACTIVE},
{@link Invocation#WAITING},
{@link Invocation#ERROR},
{@link Invocation#OK}, or
{@link Invocation#CANCELLED}. |
String | invokingAuthorityThe authority that authenticated this Invocation. |
String | invokingIDThe ID that authenticated this Invocation. |
int | invokingSuiteIdThe MIDlet suite of the invoking application. |
String | invokingClassnameThe classname in the invoking MIDlet suite for the response. |
String | invokingAppNameThe application name of the invoking MIDlet suite. |
InvocationImpl | previousThe previous invocation, if any. |
int | previousTidThe tid of the previous Invocation, if any. |
private static final byte[] | ZERO_BYTESA zero length array of strings to re-use when needed. |
static final int | DISPOSEThe DISPOSE status is used with {@link #setStatus setStatus}
to discard the native Invocation. It must not overlap with
Status values defined in the Invocation class and must match
STATUS_DISPOSE defined in invocStore.c. |
Methods Summary |
---|
public java.lang.String | findType()Finds the type of the content in this Invocation.
If the getType method return value is
non-null , then the type is returned.
If the type is null and the URL is non-null ,
then the content type will be found by accessing the content
through the URL.
When found, the type is set as if the setType method
was called; subsequent calls to
{@link #getType getType} and {@link #findType findType}
will return the type.
If an exception is thrown, the getType method will
return null .
The calling thread blocks while the type is being determined.
If a network access is needed there may be an associated delay.
if (type != null) {
return type;
}
if (url == null) {
// No URL to examine, leave the type null
throw new ContentHandlerException(
"URL is null",
ContentHandlerException.TYPE_UNKNOWN);
}
// Open a connection to the content.
Connection conn = null;
int rc = 0;
try {
while (true) {
// Loop to enable redirects.
conn = Connector.open(url);
if (conn instanceof HttpConnection) {
HttpConnection httpc = (HttpConnection)conn;
httpc.setRequestMethod(httpc.HEAD);
// Get the response code
rc = httpc.getResponseCode();
if (rc == HttpConnection.HTTP_OK) {
type = httpc.getType();
if (type != null) {
// Check for and remove any parameters (rfc2616)
int ndx = type.indexOf(';");
if (ndx >= 0) {
type = type.substring(0, ndx);
}
type = type.trim();
}
if (type == null || type.length() == 0) {
type = null;
throw new ContentHandlerException(
"unable to determine type",
ContentHandlerException.TYPE_UNKNOWN);
}
break;
} else if (rc == HttpConnection.HTTP_TEMP_REDIRECT ||
rc == HttpConnection.HTTP_MOVED_TEMP ||
rc == HttpConnection.HTTP_MOVED_PERM) {
// Get the new location and close the connection
url = httpc.getHeaderField("location");
conn.close();
conn = null;
continue; // restart with the new url
} else {
throw new IOException("http status: " + rc);
}
} else {
// Not HTTP, this isn't going to work
// TBD: Check suffixes
throw new ContentHandlerException(
"URL scheme not supported",
ContentHandlerException.TYPE_UNKNOWN);
}
}
} finally {
if (conn != null) {
try {
conn.close();
} catch (Exception ex) {
}
}
}
return type;
|
boolean | finish(int status)Finish this Invocation and set the status for the response.
if (status != Invocation.OK &&
status != Invocation.CANCELLED &&
status != Invocation.INITIATED) {
throw new IllegalArgumentException();
}
/*
* If a response is required by the invoking application,
* the native code requeues it.
* The application mutable parameters are saved to the
* native invocation.
*/
if (getResponseRequired()) {
if (tid != 0) {
InvocationStore.setParams(this);
}
}
setStatus(status);
if (getResponseRequired()) {
// Launch the target application if necessary.
try {
AppProxy appl = AppProxy.getCurrent().
forApp(suiteId, classname);
return appl.launch(invokingAppName);
} catch (ClassNotFoundException cnfe) {
AppProxy.getCurrent().logInfo(
"Unable to launch invoking application "
+ invokingAppName + "; classname = "
+ classname + " from suite = "
+ suiteId);
}
}
return false;
|
public java.lang.String | getAction()Gets the action to be performed on the content.
return action;
|
public java.lang.String[] | getArgs()Gets the argument list as an array of Strings. These values
are passed to the content handler and are returned from
the content handler.
The array is not copied; modifications to array elements
will be visible.
return arguments;
|
public byte[] | getData()Gets the data for the Invocation. The data
is passed to the content handler.
The content handler may modify and return the data
if it returns a response.
The array is not copied; modifications to array elements
will be visible.
return data;
|
public java.lang.String | getID()Gets the content handler ID for this Invocation.
return ID;
|
public java.lang.String | getInvokingAppName()Get the user-friendly name of the application that invoked
the content handler. This information is available only if the status is
ACTIVE or HOLD .
This information has been authenticated only if
getInvokingAuthority is non-null.
if (status != Invocation.ACTIVE &&
status != Invocation.HOLD) {
return null;
}
return invokingAppName;
|
public java.lang.String | getInvokingAuthority()Gets the authority, if any, used to authenticate the
application that invoked this request.
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 .
if (status != Invocation.ACTIVE &&
status != Invocation.HOLD) {
return null;
}
return invokingAuthority;
|
public java.lang.String | getInvokingID()Gets the ID of the application that invoked the content
handler. This information is available only if the status is
ACTIVE or HOLD .
This information has been authenticated only if
getInvokingAuthority is non-null.
if (status != Invocation.ACTIVE &&
status != Invocation.HOLD) {
return null;
}
return invokingID;
|
public com.sun.midp.content.InvocationImpl | getPrevious()Returns the previous Invocation linked to this
Invocation by this application's previous call to
{@link Registry#invoke(Invocation invoc, Invocation previous)}.
return previous;
|
public boolean | getResponseRequired()Gets the responseRequired mode for
this Invocation.
If true , then the invoking application requires a
response to the Invocation.
return responseRequired;
|
public int | getStatus()Returns the status of this Invocation, which can be
INIT , WAITING , HOLD ,
ACTIVE , OK ,
CANCELLED , or ERROR .
The application uses the status to determine how
to process an Invocation returned from
getInvocation .
return status;
|
public java.lang.String | getType()Gets the content type for the Invocation.
return type;
|
public java.lang.String | getURL()Gets the URL for the invocation.
The URL must be equal to the value set with {@link #setURL setURL}.
return url;
|
boolean | invoke(com.sun.midp.content.InvocationImpl previous, ContentHandlerImpl handler)Checks this Invocation and uses the ID, type, URL, and action
find a matching ContentHandler and queue this request to it.
The actual launching of the application is done in the Registry.
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 Registry#findHandler Registry.findHandler}.
If any handlers are
found, one is arbitrarily selected for this Invocation.
The status of this Invocation is set to WAITING .
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.
/*
* Check all of the arguments for validity.
*/
for (int i = 0; i < arguments.length; i++) {
if (arguments[i] == null) {
throw new IllegalArgumentException("argument is null");
}
}
if (previous != null) {
this.previous = previous;
this.previousTid = previous.tid;
}
// Fill information about the target content handler.
setStatus(Invocation.INIT);
setID(handler.ID);
suiteId = handler.storageId;
classname = handler.classname;
// Queue this Invocation
InvocationStore.put(this);
// Launch the target application if necessary.
boolean shouldExit = false;
try {
if (handler.registrationMethod ==
ContentHandlerImpl.REGISTERED_NATIVE) {
shouldExit = RegistryStore.launch(handler);
finish(Invocation.INITIATED);
} else {
try {
AppProxy appl = AppProxy.getCurrent().
forApp(suiteId, classname);
shouldExit = appl.launch(handler.getAppName());
// Set the status of this Invocation to WAITING
status = Invocation.WAITING;
} catch (ClassNotFoundException cnfe) {
throw new ContentHandlerException(
"Invoked handler has been removed",
ContentHandlerException.NO_REGISTERED_HANDLER);
}
}
} catch (ContentHandlerException che) {
// remove this invocation from the queue before throwing
setStatus(DISPOSE);
throw che;
}
// Set the status of the previous invocation
if (previous != null) {
previous.setStatus(Invocation.HOLD);
}
return shouldExit;
|
static void | invokeNext()Execute the User Environment Policy to select the next
application to run.
Check for and select the next MIDlet suite to run
based on the contents of the Invocation queue.
From the most recently queued Invocation that is an Invocation
in INIT.
If none, find the most recently queued Invocation that is
a response.
InvocationImpl invoc = null;
int tid;
// Look for a recently queued Invocation to launch
tid = 0;
while ((invoc = InvocationStore.getByTid(tid, -1)) != null) {
if (invoc.status == Invocation.INIT) {
AppProxy.getCurrent().logInfo("invokeNext has request: " +
invoc);
if (invoc.suiteId != MIDletSuite.UNUSED_SUITE_ID &&
invoc.classname != null) {
try {
AppProxy appl = AppProxy.getCurrent().
forApp(invoc.suiteId, invoc.classname);
appl.launch("Application");
return;
} catch (ClassNotFoundException cnfe) {
// Ignore
}
} else if (invoc.ID != null) {
// check if it is native handler
ContentHandlerImpl handler = RegistryStore.getHandler(null,
invoc.ID, RegistryStore.SEARCH_EXACT);
if (handler != null &&
handler.registrationMethod ==
ContentHandlerImpl.REGISTERED_NATIVE) {
try {
RegistryStore.launch(handler);
invoc.finish(Invocation.INITIATED);
continue;
} catch (ContentHandlerException che) {
// Ignore
}
}
}
// can't process this invocation - remove it
invoc.setStatus(DISPOSE);
} else if (invoc.status == Invocation.ERROR) {
AppProxy.getCurrent().logInfo("invokeNext has response: " +
invoc);
if (invoc.suiteId != MIDletSuite.UNUSED_SUITE_ID &&
invoc.classname != null) {
try {
AppProxy appl = AppProxy.getCurrent().
forApp(invoc.suiteId, invoc.classname);
appl.launch("Application");
return;
} catch (ClassNotFoundException cnfe) {
// Ignore
}
}
// can't process this invocation - remove it
invoc.setStatus(DISPOSE);
}
tid = invoc.tid;
}
|
public javax.microedition.io.Connection | open(boolean timeouts)Creates and opens a Connection to the content accessable by
using the URL. This method is
equivalent to
{@link javax.microedition.io.Connector#open Connector.open}
with the URL provided.
The application should use this method to access the
content of the URL
so that any type or content information cached by the
implementation can be fully utilized. The content is opened
in read only mode.
Connection conn = Connector.open(getURL(), Connector.READ, timeouts);
return conn;
|
public void | setAction(java.lang.String action)Sets the action to be performed on the content.
this.action = action;
|
public void | setArgs(java.lang.String[] args)Sets the argument list to a new array of Strings. The arguments
are used by the application to communicate to the content
handler and return results from the content handler.
The values of the arguments are not checked when they are set.
Instead, they are checked during
{@link Registry#invoke Registry.invoke} to
check that none of the values are null .
this.arguments =
(args == null) ? ContentHandlerImpl.ZERO_STRINGS : args;
|
public void | setCredentials(java.lang.String username, char[] password)Provide the credentials needed to access the content.
this.username = username;
this.password = (password == null) ? null : new String(password);
|
public void | setData(byte[] data)Sets the data used for the Invocation. The data
is used by the application to communicate to the content
handler and return data from the content handler.
this.data = (data == null) ? ZERO_BYTES : data;
|
public void | setID(java.lang.String ID)Sets the ID of the content handler for this Invocation.
this.ID = ID;
|
public void | setResponseRequired(boolean responseRequired)Sets the responseRequired mode for
this Invocation.
If true , then the invoking application requires a
response to the Invocation.
The value in the request can be changed only if the status is
INIT .
if (getStatus() != Invocation.INIT) {
throw new IllegalStateException();
}
this.responseRequired = responseRequired;
|
void | setStatus(int status)Set the status of this InvocationImpl.
If the invocation is still active in the native code
set the status in native also.
this.status = status;
if (tid != 0) {
InvocationStore.setStatus(this);
}
|
public void | setType(java.lang.String type)Sets the type for the Invocation.
this.type = type;
|
public void | setURL(java.lang.String url)Sets the URL for the invocation.
this.url = url;
|
public java.lang.String | toString()Return a printable form of InvocationImpl.
Disabled if not logging
if (AppProxy.LOG_INFO) {
StringBuffer sb = new StringBuffer(200);
sb.append("tid: "); sb.append(tid);
sb.append(" status: "); sb.append(status);
// sb.append(" suiteId: "); sb.append(suiteId);
sb.append(", type: "); sb.append(getType());
sb.append(", url: "); sb.append(getURL());
sb.append(", respReq: "); sb.append(getResponseRequired());
// sb.append(", args: "); sb.append(getArgs());
// sb.append(", prevTid: "); sb.append(previousTid);
// sb.append(", previous: ");
// sb.append((previous == null) ? "null" : "non-null");
// sb.append("_suiteId: "); sb.append(invokingSuiteId);
sb.append("\n invokee: "); sb.append(classname);
sb.append(", invoker: "); sb.append(invokingClassname);
// sb.append(", _authority: "); sb.append(invokingAuthority);
// sb.append(", _ID: "); sb.append(invokingID);
return sb.toString();
} else {
return super.toString();
}
|