/*
*
*
* Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package javax.microedition.content;
import com.sun.midp.content.InvocationImpl;
import java.io.IOException;
import javax.microedition.io.Connection;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
/**
* An <tt>Invocation</tt> contains the parameters that
* are passed from an invoking application to a content handler and
* the results that are returned to the application.
* The parameters are the type, URL, action,
* content handler ID, and responseRequired.
* The string and data arguments can be set using
* {@link #setArgs setArgs} and {@link #setData setData} methods.
* All of the parameters are provided to the content handler and
* are returned with the handlers response, if any.
* Invocation instances are not thread safe, the application
* must handle any synchronization necessary. </p>
* <p>
* The values of content handler ID, type, URL, and action are used to
* identify the content handler when invoked by
* {@link Registry#invoke Registry.invoke}.
* If an Invocation contains an ID then it is used to identify the
* content handler to be invoked. The other parameters are input to
* the content handler.
* <p>If a type is present, it is used to find handlers that support
* that type. The application should supply the type if it is known.
* If the type is not set, then calling the
* {@link #findType findType} will find the type using the URL to the
* content.
*
* <h3>Invocation Status</h3>
* <P>
* The status value indicates the next processing step of
* the invocation by the content handler.
* The status of an Invocation can be any of the following:
* <ul>
* <li>{@link #INIT}indicates the Invocation is still being
* initialized</li>
* <li>{@link #WAITING}indicates that this Invocation is waiting
* to complete </li>
* <li>{@link #ACTIVE}indicates the Invocation is currently
* being processed </li>
* <li>{@link #HOLD}indicates the Invocation is currently
* waiting for a chained Invocation to complete </li>
* <li>{@link #ERROR}, {@link #OK}, {@link #CANCELLED}
* indicate that the Invocation is complete</li>
* <LI>{@link #INITIATED}
* indicate that the Invocation has been initiated but the content
* handler cannot provide a response when it is finished.
* </ul>
*
* <p>All status transitions occur only during method calls that involve
* the Invocation instance. The transitions that occur are specified
* in the methods that make the change visible.
* For example, when an invoking application creates a new Invocation, the
* status is {@link #INIT INIT}.
* When the application calls
* {@link Registry#invoke Registry.invoke}
* the status changes to {@link #WAITING WAITING}.
* When the <code>Registry.getResponse</code> method is invoked, the
* status will be updated to the appropriate {@link #OK OK},
* {@link #CANCELLED CANCELLED},
* {@link #INITIATED INITIATED}, or {@link #ERROR ERROR} status from
* the content handler.
*
* <p>
* A content handler calls
* {@link ContentHandlerServer#getRequest ContentHandlerServer.getRequest}
* to get the next request.
* The request always has the {@link #ACTIVE ACTIVE} status.
* When the handler is finished acting on the content, the status
* is set to either {@link #OK OK}, {@link #CANCELLED CANCELLED}, or
* {@link #INITIATED INITIATED} by
* the {@link ContentHandlerServer#finish ContentHandlerServer.finish} method.
* <p>
* If the handler is chaining, then the new Invocation follows the status
* transitions of <code>invoke</code> as described above. The status of the
* previous invocation being chained from is set to {@link #HOLD HOLD}
* by the <code>Registry.invoke</code> method. The status of the previous
* Invocation is restored to {@link #ACTIVE ACTIVE} by the
* {@link Registry#getResponse Registry.getResponse}
* method that returns the status for the new Invocation.
* <p>
* If the content handler application causes faults because it
* does not properly dequeue and respond to invocations as described
* in the {@link ContentHandler} class, then the
* status is set to {@link #ERROR ERROR} in the response queued back
* to the invoking application.
*
* <H3>Access to Content</H3>
* <P>
* The implementation of the invocation mechanism may save or cache
* information about the request, the URL, the content type, or content
* during the invocation. The information may be
* utilized when the application accesses the content with the
* {@link #open open} method.
* The {@link #getURL} method MUST return the original URL unmodified
* by any implementation specific information.
*/
public final class Invocation {
/** The InvocationImpl to delegate to. */
private InvocationImpl invocImpl;
/**
* This Invocation was just constructed and is being initialized.
*/
public static final int INIT = 1;
/**
* This Invocation is a new request and is being handled
* by the content handler.
*/
public static final int ACTIVE = 2;
/**
* This Invocation has been invoked and is waiting to be
* complete.
* @see Registry#invoke
*/
public static final int WAITING = 3;
/**
* This Invocation is on hold until a chained
* Invocation is completed.
* @see Registry#invoke
*/
public static final int HOLD = 4;
/**
* The content handler successfully completed processing
* the Invocation.
* Invocations queued with
* {@link ContentHandlerServer#finish ContentHandlerServer.finish}
* will have this status.
*/
public static final int OK = 5;
/**
* The processing of the Invocation was cancelled by
* the ContentHandler.
* Invocations queued with
* {@link ContentHandlerServer#finish ContentHandlerServer.finish}
* will have this status.
*/
public static final int CANCELLED = 6;
/**
* The content handler failed to correctly process the Invocation
* request.
*/
public static final int ERROR = 7;
/**
* The processing of the Invocation has been initiated and will
* continue. This status is only appropriate when the content
* handler can not provide a response when it is finished.
*/
public static final int INITIATED = 8;
/**
* Creates a new Invocation.
* The status of the new Invocation object is <code>INIT</code>.
* The URL, type, ID, action, arguments, and data are set to
* empty arrays, and initialized to require a response.
*/
public Invocation() {
invocImpl = new InvocationImpl(this);
}
/**
* Convenient alternative constructor with URL, type, and ID.
* The behavior is identical to
* <code>new Invocation(url, type, ID, true, null)</code>.
*
* @param url the URL of the content to be dispatched;
* may be <code>null</code>
* @param type the content type; may be <code>null</code>
* @param ID the ID of the content handler; may be <code>null</code>
*/
public Invocation(String url, String type, String ID) {
this(url, type, ID, true, null);
}
/**
* Convenient alternative constructor with URL and type.
* The behavior is identical to
* <code>new Invocation(url, type, null, true, null)</code>.
*
* @param url the URL of the content to be dispatched;
* may be <code>null</code>
* @param type the content type; may be <code>null</code>
*/
public Invocation(String url, String type) {
this(url, type, null, true, null);
}
/**
* Convenient alternative constructor with a URL.
* The behavior is identical to
* <code>new Invocation(url, null, null, true, null)</code>.
*
* @param url the URL of the content to be dispatched;
* may be <code>null</code>
*/
public Invocation(String url) {
this(url, null, null, true, null);
}
/**
* Creates a new instance and initializes it from the
* specified parameters.
* The status of the new Invocation is <code>INIT</code>.
* None of the values are checked until the
* {@link Registry#invoke Registry.invoke}
* method is called.
* String arguments or data can be set with
* {@link #setArgs setArgs} or {@link #setData setData}.
*
* @param url the URL of the content to be dispatched;
* may be <code>null</code>
* @param type the content type; may be <code>null</code>
* @param ID the ID of the content handler; may be <code>null</code>
* @param responseRequired <code>true</code> if a response is
* required; <code>false</code> otherwise
* @param action the action that the content handler should perform on the
* content; may be <code>null</code>
*/
public Invocation(String url, String type, String ID,
boolean responseRequired, String action)
{
this();
invocImpl.setURL(url);
invocImpl.setType(type);
invocImpl.setID(ID);
invocImpl.setResponseRequired(responseRequired);
invocImpl.setAction(action);
}
/**
* Creates a new Invocation to refer to an InvocationImpl.
* And makes the InvocationImpl refer to the new Invocation.
* @param impl and InvocationImpl to be associated with this Invocation
*/
Invocation(InvocationImpl impl) {
invocImpl = impl;
if (impl != null) {
impl.invocation = this;
}
}
/**
* 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 <code>null</code>.
* @param args the String array; may be <code>null</code>.
* A <code>null</code>
* argument is treated the same as a zero-length array
* @see #getArgs
*/
public void setArgs(String[] args) {
invocImpl.setArgs(args);
}
/**
* 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 the arguments array, which MUST NOT be <code>null</code>
* @see #setArgs
*/
public String[] getArgs() {
return invocImpl.getArgs();
}
/**
* 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.
* The array is not copied until the Invocation is <code>invoked</code>
* or <code>finish</code>ed;
* modifications to array elements will otherwise be visible.
*
* @param data the byte data array; may be <code>null</code>.
* A <code>null</code> is treated the same as a zero-length array
* @see #getData
*/
public void setData(byte[] data) {
invocImpl.setData(data);
}
/**
* 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.
*
* @return the data array, which MUST NOT be <code>null</code>
* @see #setData
*/
public byte[] getData() {
return invocImpl.getData();
}
/**
* Gets the URL for the invocation.
* The URL must be equal to the value set with {@link #setURL setURL}.
* @return the URL or <code>null</code> if it has not been set
* @see #setURL
*/
public String getURL() {
return invocImpl.getURL();
}
/**
* Sets the URL for the invocation.
* @param url the URL to be set; may be <code>null</code>
* @see #getURL
*/
public void setURL(String url) {
invocImpl.setURL(url);
}
/**
* Gets the content type for the Invocation.
* The type for this Invocation may be set by the application using
* {@link #setType setType}.
* The {@link #findType findType} method can be used by an application
* to find the type by accessing the content via the URL.
* When found, <code>findType</code> sets the type returned
* by <code>getType</code>.
*
* @return the content type or <code>null</code> if it has not been set
* @see #setType
* @see #findType
*/
public String getType() {
return invocImpl.getType();
}
/**
* Sets the type for the Invocation.
* @param type the type to be set for the content; may be <code>null</code>
* @see #getType
* @see #findType
*/
public void setType(String type) {
invocImpl.setType(type);
}
/**
* Gets the action to be performed on the content.
* @return the content action or <code>null</code> if it has not been set
* @see #setAction
*/
public String getAction() {
return invocImpl.getAction();
}
/**
* Sets the action to be performed on the content.
* @param action the action to be performed on the content;
* may be <code>null</code>
* @see #getAction
*/
public void setAction(String action) {
invocImpl.setAction(action);
}
/**
* Gets the <code>responseRequired</code> mode for
* this Invocation.
* If <code>true</code>, then the invoking application requires a
* response to the Invocation.
* @return the current value of the <code>responseRequired</code>
* mode. If
* <code>true</code>, then a response must be returned to the
* invoking application.
* @see #setResponseRequired
*/
public boolean getResponseRequired() {
return invocImpl.getResponseRequired();
}
/**
* Sets the <code>responseRequired</code> mode for
* this Invocation.
* If <code>true</code>, then the invoking application requires a
* response to the Invocation.
* The value in the request can be changed only if the status is
* <code>INIT</code>.
* @param responseRequired
* <code>true</code> to require a response,
* <code>false</code> otherwise
* @exception IllegalStateException is thrown if the status is not
* <code>INIT</code>
* @see #getResponseRequired
*/
public void setResponseRequired(boolean responseRequired) {
invocImpl.setResponseRequired(responseRequired);
}
/**
* Gets the status of this Invocation, which can be
* <code>INIT</code>, <code>WAITING</code>, <code>HOLD</code>,
* <code>ACTIVE</code>, <code>OK</code>,
* <code>CANCELLED</code>,
* <code>INITIATED</code>, or <code>ERROR</code>.
*
* @return the status of this Invocation
*
* @see Registry#invoke
* @see Registry#getResponse
* @see ContentHandlerServer#getRequest
* @see ContentHandlerServer#finish
*/
public int getStatus() {
// Delegated to the implementation class
return invocImpl.getStatus();
}
/**
* Gets the content handler ID for this Invocation.
*
* @return the ID of the ContentHandler; may be
* <code>null</code>
* @see Registry#forID
* @see #setID
*/
public String getID() {
// Delegated to the implementation class
return invocImpl.getID();
}
/**
* Sets the ID of the content handler for this Invocation.
* @param ID of the content handler; may be <code>null</code>
* @see #getID
*/
public void setID(String ID) {
// Delegated to the implementation class
invocImpl.setID(ID);
}
/**
* Gets the previous Invocation saved in this
* Invocation by
* {@link Registry#invoke Registry.invoke} or
* {@link Registry#getResponse Registry.getResponse}.
* Invocations returned by
* {@link ContentHandlerServer#getRequest ContentHandlerServer.getRequest}
* MUST return <code>null</code>.
*
* @return the previous Invocation, if any, saved when this
* Invocation was invoked or returned as a response;
* may be <code>null</code>
*
* @see Registry#invoke
* @see Registry#getResponse
*/
public Invocation getPrevious() {
InvocationImpl prev = invocImpl.getPrevious();
if (prev != null) {
if (prev.invocation == null) {
/*
* An InvocationImpl created by the implementation needs
* a Invocation to return to the application.
*/
prev.invocation = new Invocation(prev);
}
return prev.invocation;
} else {
return null;
}
}
/**
* Gets the authority, if any, used to authenticate the
* application that invoked this request.
* This value MUST be <code>null</code> unless the device has been
* able to authenticate this application.
* If <code>non-null</code>, it is the string identifying the
* authority.
*
* @return the authority used to authenticate this application
* and if the status is either <code>ACTIVE</code> or <code>HOLD</code>;
* otherwise it is <code>null</code>,
* the application has not been authenticated
*
* @see ContentHandler#getAuthority
*/
public String getInvokingAuthority() {
// Delegated to the implementation class
return invocImpl.getInvokingAuthority();
}
/**
* Gets the ID of the application that invoked the content
* handler. This information is available only if the status is
* <code>ACTIVE</code> or <code>HOLD</code>.
*
* This information has been authenticated only if
* <code>getInvokingAuthority</code> is non-null.
*
* @return the invoking application's ID if the Invocation status
* is <code>ACTIVE</code>
* or <code>HOLD</code>; <code>null</code> otherwise
*
* @see Registry#getID
*/
public String getInvokingID() {
// Delegated to the implementation class
return invocImpl.getInvokingID();
}
/**
* Get the user-friendly name of the application that invoked
* the content handler. This information is available only if the status is
* <code>ACTIVE</code> or <code>HOLD</code>.
*
* This information has been authenticated only if
* <code>getInvokingAuthority</code> is non-null.
*
* @return the application's name if status is <code>ACTIVE</code>
* or <code>HOLD</code>; <code>null</code> otherwise
*
* @see ContentHandler#getID
*/
public String getInvokingAppName() {
// Delegated to the implementation class
return invocImpl.getInvokingAppName();
}
/**
* Finds the type of the content in this Invocation.
* If the <tt>getType</tt> method return value is
* <code>non-null</code>, then the type is returned.
* <p>
* If the type is <code>null</code> and the URL is non-<code>null</code>,
* then the content type will be found by accessing the content
* through the URL.
* When found, the type is set as if the <code>setType</code> method
* was called; subsequent calls to
* {@link #getType getType} and {@link #findType findType}
* will return the type.
* If an exception is thrown, the <code>getType</code> method will
* return <code>null</code>.
* <p>
* The calling thread blocks while the type is being determined.
* If a network access is needed there may be an associated delay.
*
* @return the <code>non-null</code> content type
* @exception IOException if access to the content fails
*
* @exception ContentHandlerException is thrown with a reason of
* {@link ContentHandlerException#TYPE_UNKNOWN}
* if the type is <code>null</code> and cannot be found from the
* content either because the URL is <code>null</code> or the type is
* not available from the content
* @exception IllegalArgumentException if the content is accessed via
* the URL and the URL is invalid
* @exception SecurityException is thrown if access to the content
* is required and is not permitted
*
* @see Invocation#setType
* @see Invocation#getType
*/
public String findType()
throws IOException, ContentHandlerException, SecurityException
{
// Delegated to the implementation class
return invocImpl.findType();
}
/**
* Creates and opens a Connection to the content addressed by
* the URL in {@link #getURL getURL}. This method is
* similar to <code>Connector.open(getURL(), READ, timeouts)</code>
* but may deliver the content from a cache.
* 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 utilized. The content is opened
* in read only mode.
* Regardless of whether or not the content is cached, the
* application or content handler must have permission to access
* the content via the URL.
*
* @param timeouts a flag to indicate that the caller
* wants timeout exceptions
* @return a Connection object
*
* @exception ConnectionNotFoundException is thrown if:
* <ul>
* <li>the target URL can not be found, or</li>
* <li>the requested protocol type is not supported</li>
* </ul>
* @exception NullPointerException if the URL is null
* @exception IllegalArgumentException if a parameter is invalid.
* @exception IOException if some other kind of I/O error occurs
* @exception SecurityException is thrown if access to the
* protocol handler is prohibited
*/
public Connection open(boolean timeouts)
throws IOException, SecurityException
{
String url = getURL();
url.length(); // Throw NPE if null
Connection conn = Connector.open(url, Connector.READ, timeouts);
return conn;
}
/**
* Provide the credentials needed to access the content.
* Use of the credential is protocol specific.
* @param username the username; may be <code>null</code>
* @param password the password for the username;
* may be <code>null</code>
*/
public void setCredentials(String username, char[] password) {
invocImpl.setCredentials(username, password);
}
/**
* Gets the InvocationImpl for this Invocation.
* @return the InvocationImpl delgate.
*/
InvocationImpl getInvocImpl() {
return invocImpl;
}
/**
* Sets the InvocationImpl for this Invocation.
* @param invocImpl the InvocationImpl delgate.
*/
void setInvocImpl(InvocationImpl invocImpl) {
this.invocImpl = invocImpl;
}
}
|