/*
*
*
* Copyright 1990-2009 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;
/**
*<tt>ContentHandlerServer</tt> provides methods
* to get new Invocation requests, to finish the processing
* of requests and to get the access control information.
* This server interface extends {@link ContentHandler}
* to make available the registration information for types,
* suffixes, actions, ID, etc.
* Instances are thread safe.
*
* <h3>Responding to an Invocation</h3>
* <p>Content handler applications process requests using
* either blocking calls to {@link #getRequest getRequest} or can be
* notified of
* new requests with the {@link #setListener setListener} method.
* A content handler receives an Invocation by calling
* {@link #getRequest getRequest}.
* The content handler should use the
* {@link Invocation#getAction Invocation.getAction}
* method to determine the requested action and act on the content
* appropriately.
* The content handler will typically call the
* {@link Invocation#open Invocation.open} method to read the content.
* The <code>open</code> method returns a Connection from the Generic
* Connection framework that provides access to the content.
* When the content handler is finished processing the Invocation,
* it must call the
* {@link #finish finish} method to report the status.
* If a response was required the status and parameters are returned
* to the invoking application.
*
* <h3>Required Response to the Invoking Application</h3>
* <p>
* The invoking application decides whether it needs a response and
* sets the request state before calling
* {@link Registry#invoke Registry.invoke}.
* When an Invocation is completed either by using the
* {@link #finish finish}
* method or when the AMS is handling an error condition,
* the {@link Invocation#getResponseRequired Invocation.getResponseRequired}
* method is checked.
* If it is <code>true</code>, then the values from the Invocation are
* queued to the invoking application with the status set
* by the ContentHandler or AMS.
* When a response is queued, it will be dispatched to the invoking
* application.
* If a response is not required, it is not delivered to the invoking
* application and the invoking application is not started.
*
* <H3>Chaining Content Handlers</H3>
* <p> Content handlers link Invocations that are part of
* a user-driven task and depend on each other as part of a transaction.
* Suppose an application <i>A</i> creates an invocation
* <i>a</i>. When invoked, it is dispatched to content
* handler <i>B</i> which in-turn creates an invocation <i>b</i>
* and it is dispatched to content handler <i>C</i>. C displays the
* content and returns a response <i>b'</i> to B, B in turn
* completes processing and returns a response <i>a'</i> to A.</p>
* <p>
* The implementation MUST have the capacity and mechanisms to support
* the chaining of requests required for an application to invoke a
* content handler, and the content handler invoking another content
* handler, and for each content handler to return a response.
* This chain length of two active invocations is the minimum
* requirement. The implementation should not artificially
* limit the number of invocations and responses that are supported
* except as constrained by the resources of the device.</p>
*
* <p> To maintain continuity across the applications,
* chained invocations are part of the same transaction.
* Invoking an Invocation places it in a transaction.
* The transaction maintains the sequence of invocations
* across all of the applications involved.
* The transaction maintains the invocations regardless of whether
* a single application can run at a time or the applications
* execute in parallel in different runtime environments. The
* transaction is used to record and manage the steps in processing and
* dispatching to applications. </p>
*
* <p> For simple non-chaining use cases that involve only two
* applications with a single invocation and response,
* only the methods
* {@link #getRequest getRequest}, {@link #finish finish},
* {@link Registry#invoke Registry.invoke}, and
* {@link Registry#getResponse Registry.getResponse} are needed.</p>
* <p>
* For chained use cases, the methods {@link Registry#invoke Registry.invoke}
* and {@link Invocation#getPrevious Invocation.getPrevious}
* are used to establish
* the sequence and to retrieve the previous Invocation.
* The {@link Registry#invoke Registry.invoke} method places the new
* Invocation in the same transaction as a previous Invocation.
* The previous Invocation will be held in the transaction until
* the new Invocation is completed. When the response to the new
* Invocation is returned, the previously active Invocation can be
* retrieved with {@link Invocation#getPrevious Invocation.getPrevious}
* so the content handler can complete its processing.</p>
*
* <p>
* An Invocation can be delegated to another handler with the
* {@link Registry#reinvoke Registry.reinvoke} method.
* Responses to the reinvocation will be queued to the original invoking
* application. </p>
*
* <H3>Handling Faults</H3>
* If the content handler cannot or does not correctly handle the
* Invocation, then the AMS MUST handle it correctly.
* These actions prevent an incorrectly written content
* handler from being unresponsive or being run repeatedly but never
* processing queued invocations.
* <ul>
* <li>
* If an Invocation with a status of <code>ACTIVE</code> is dequeued by
* the content handler, but the handler does not call
* {@link #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.
* This ensures that the invoking application
* will always get a response, if required, for each invocation
* regardless of whether the content handler correctly handles it.
* </li>
* <li>
* 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 or can not be started,
* then Invocations that were in the queue for the content handler
* before it was started MUST be handled as follows:
* <ul>
* <li>Invocation requests with a status of <code>ACTIVE</code>
* are completed with the <code>ERROR</code> status.</li>
* <li>Invocation responses are discarded.</li>
* <li>Invocations queued after the content handler was started are
* retained and will require it to be restarted.</li>
* </ul>
* This serialization of queued requests and starting the content
* handler
* addresses a race condition. This condition may occur when the
* content handler is active but exits before processing Invocations that
* were queued after it was started or it last called
* {@link #getRequest getRequest} or
* {@link Registry#getResponse Registry.getResponse}.
* </li>
* </ul>
* <p>
* Invocations and invocation state MUST NOT be preserved
* across soft and hard restarts of the device software including
* unexpected power interruptions.</p>
*
*
*/
public interface ContentHandlerServer extends ContentHandler {
/**
* 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 <code>action</code> on the content.
*
* @param wait <code>true</code> if the method must wait
* for an Invocation if one is not available;
* <code>false</code> if the method MUST NOT wait.
*
* @return the next pending Invocation or <code>null</code>
* if no Invocation is available; <code>null</code>
* if canceled with {@link #cancelGetRequest cancelGetRequest}
* @see Registry#invoke
* @see #finish
*/
public Invocation getRequest(boolean wait);
/**
* Cancels a pending <code>getRequest</code>.
* This method will force all threads blocked in a call to the
* <code>getRequest</code> method for this ContentHandlerServer
* to return.
* If no threads are blocked; this call has no effect.
*/
public void cancelGetRequest();
/**
* Finishes the Invocation and sets the status for the response.
* The <code>finish</code> method can only be called when the
* Invocation
* has a status of <code>ACTIVE</code> or <code>HOLD</code>.
* <p>
* The content handler may modify the URL, type, action, or
* arguments before invoking <code>finish</code>.
* If the method
* {@link Invocation#getResponseRequired Invocation.getResponseRequired}
* returns <code>true</code>, then the modified
* values MUST be returned to the invoking application.
*
* @param invocation the Invocation to finish
* @param status the new status of the Invocation;
* MUST be either <code>OK</code>, <code>CANCELLED</code>
* or <code>INITIATED</code>
*
* @return <code>true</code> if the application MUST
* voluntarily exit to allow pending responses or requests
* to be handled;
* <code>false</code> otherwise
*
* @exception IllegalArgumentException if the new
* <code>status</code> of the Invocation
* is not <code>OK</code>, <code>CANCELLED</code>,
* or <code>INITIATED</code>
* @exception IllegalStateException if the current
* <code>status</code> of the
* Invocation is not <code>ACTIVE</code> or <code>HOLD</code>
* @exception NullPointerException if the invocation is <code>null</code>
*/
public boolean finish(Invocation invocation, int status);
/**
* Sets the listener to be notified when a new request is
* available for this content handler. The request is
* retrieved using {@link #getRequest getRequest}.
* If the listener is <code>non-null</code> and a request is
* available, the listener MUST be notified.
*
* @param listener the listener to register;
* <code>null</code> to remove the listener.
*/
public void setListener(RequestListener listener);
/**
* Gets the ID at the specified index 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 <tt>accessAllowed</tt> array passed to
* {@link Registry#register Registry.register}.
*
* @param index the index of the ID
* @return the ID at the specified index
* @exception IndexOutOfBoundsException if index is less than zero or
* greater than or equal to the value of the
* {@link #accessAllowedCount accessAllowedCount} method.
*/
public String getAccessAllowed(int index);
/**
* 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 <code>accessAllowed</code> passed to
* {@link Registry#register Registry.register}.
* If the number of IDs is zero then all applications and
* content handlers are allowed access.
*
* @return the number of IDs allowed access
*/
public int accessAllowedCount();
/**
* 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
* <code>java.lang.String.startsWith</code>.
*
* @param ID the ID for which to check access
* @return <code>true</code> if access MUST be allowed by the
* content handler;
* <code>false</code> otherwise
* @exception NullPointerException if <code>ID</code>
* is <code>null</code>
*/
public boolean isAccessAllowed(String ID);
}