FileDocCategorySizeDatePackage
ContentHandlerServer.javaAPI DocphoneME MR2 API (J2ME)13227Wed May 02 18:00:44 BST 2007javax.microedition.content

ContentHandlerServer.java

/*
 *  
 *
 * 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.RegistryImpl;

/**
 *<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 cancelled 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);
}