001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package javax.microedition.content;
028:
029: import com.sun.midp.content.InvocationImpl;
030:
031: import java.io.IOException;
032: import javax.microedition.io.Connection;
033: import javax.microedition.io.Connector;
034: import javax.microedition.io.HttpConnection;
035:
036: /**
037: * An <tt>Invocation</tt> contains the parameters that
038: * are passed from an invoking application to a content handler and
039: * the results that are returned to the application.
040: * The parameters are the type, URL, action,
041: * content handler ID, and responseRequired.
042: * The string and data arguments can be set using
043: * {@link #setArgs setArgs} and {@link #setData setData} methods.
044: * All of the parameters are provided to the content handler and
045: * are returned with the handlers response, if any.
046: * Invocation instances are not thread safe, the application
047: * must handle any synchronization necessary. </p>
048: * <p>
049: * The values of content handler ID, type, URL, and action are used to
050: * identify the content handler when invoked by
051: * {@link Registry#invoke Registry.invoke}.
052: * If an Invocation contains an ID then it is used to identify the
053: * content handler to be invoked. The other parameters are input to
054: * the content handler.
055: * <p>If a type is present, it is used to find handlers that support
056: * that type. The application should supply the type if it is known.
057: * If the type is not set, then calling the
058: * {@link #findType findType} will find the type using the URL to the
059: * content.
060: *
061: * <h3>Invocation Status</h3>
062: * <P>
063: * The status value indicates the next processing step of
064: * the invocation by the content handler.
065: * The status of an Invocation can be any of the following:
066: * <ul>
067: * <li>{@link #INIT}—indicates the Invocation is still being
068: * initialized</li>
069: * <li>{@link #WAITING}—indicates that this Invocation is waiting
070: * to complete </li>
071: * <li>{@link #ACTIVE}—indicates the Invocation is currently
072: * being processed </li>
073: * <li>{@link #HOLD}—indicates the Invocation is currently
074: * waiting for a chained Invocation to complete </li>
075: * <li>{@link #ERROR}, {@link #OK}, {@link #CANCELLED}—
076: * indicate that the Invocation is complete</li>
077: * <LI>{@link #INITIATED}—
078: * indicate that the Invocation has been initiated but the content
079: * handler cannot provide a response when it is finished.
080: * </ul>
081: *
082: * <p>All status transitions occur only during method calls that involve
083: * the Invocation instance. The transitions that occur are specified
084: * in the methods that make the change visible.
085: * For example, when an invoking application creates a new Invocation, the
086: * status is {@link #INIT INIT}.
087: * When the application calls
088: * {@link Registry#invoke Registry.invoke}
089: * the status changes to {@link #WAITING WAITING}.
090: * When the <code>Registry.getResponse</code> method is invoked, the
091: * status will be updated to the appropriate {@link #OK OK},
092: * {@link #CANCELLED CANCELLED},
093: * {@link #INITIATED INITIATED}, or {@link #ERROR ERROR} status from
094: * the content handler.
095: *
096: * <p>
097: * A content handler calls
098: * {@link ContentHandlerServer#getRequest ContentHandlerServer.getRequest}
099: * to get the next request.
100: * The request always has the {@link #ACTIVE ACTIVE} status.
101: * When the handler is finished acting on the content, the status
102: * is set to either {@link #OK OK}, {@link #CANCELLED CANCELLED}, or
103: * {@link #INITIATED INITIATED} by
104: * the {@link ContentHandlerServer#finish ContentHandlerServer.finish} method.
105: * <p>
106: * If the handler is chaining, then the new Invocation follows the status
107: * transitions of <code>invoke</code> as described above. The status of the
108: * previous invocation being chained from is set to {@link #HOLD HOLD}
109: * by the <code>Registry.invoke</code> method. The status of the previous
110: * Invocation is restored to {@link #ACTIVE ACTIVE} by the
111: * {@link Registry#getResponse Registry.getResponse}
112: * method that returns the status for the new Invocation.
113: * <p>
114: * If the content handler application causes faults because it
115: * does not properly dequeue and respond to invocations as described
116: * in the {@link ContentHandler} class, then the
117: * status is set to {@link #ERROR ERROR} in the response queued back
118: * to the invoking application.
119: *
120: * <H3>Access to Content</H3>
121: * <P>
122: * The implementation of the invocation mechanism may save or cache
123: * information about the request, the URL, the content type, or content
124: * during the invocation. The information may be
125: * utilized when the application accesses the content with the
126: * {@link #open open} method.
127: * The {@link #getURL} method MUST return the original URL unmodified
128: * by any implementation specific information.
129: */
130: public final class Invocation {
131: /** The InvocationImpl to delegate to. */
132: private InvocationImpl invocImpl;
133:
134: /**
135: * This Invocation was just constructed and is being initialized.
136: */
137: public static final int INIT = 1;
138:
139: /**
140: * This Invocation is a new request and is being handled
141: * by the content handler.
142: */
143: public static final int ACTIVE = 2;
144:
145: /**
146: * This Invocation has been invoked and is waiting to be
147: * complete.
148: * @see Registry#invoke
149: */
150: public static final int WAITING = 3;
151:
152: /**
153: * This Invocation is on hold until a chained
154: * Invocation is completed.
155: * @see Registry#invoke
156: */
157: public static final int HOLD = 4;
158:
159: /**
160: * The content handler successfully completed processing
161: * the Invocation.
162: * Invocations queued with
163: * {@link ContentHandlerServer#finish ContentHandlerServer.finish}
164: * will have this status.
165: */
166: public static final int OK = 5;
167:
168: /**
169: * The processing of the Invocation was cancelled by
170: * the ContentHandler.
171: * Invocations queued with
172: * {@link ContentHandlerServer#finish ContentHandlerServer.finish}
173: * will have this status.
174: */
175: public static final int CANCELLED = 6;
176:
177: /**
178: * The content handler failed to correctly process the Invocation
179: * request.
180: */
181: public static final int ERROR = 7;
182:
183: /**
184: * The processing of the Invocation has been initiated and will
185: * continue. This status is only appropriate when the content
186: * handler can not provide a response when it is finished.
187: */
188: public static final int INITIATED = 8;
189:
190: /**
191: * Creates a new Invocation.
192: * The status of the new Invocation object is <code>INIT</code>.
193: * The URL, type, ID, action, arguments, and data are set to
194: * empty arrays, and initialized to require a response.
195: */
196: public Invocation() {
197: invocImpl = new InvocationImpl(this );
198: }
199:
200: /**
201: * Convenient alternative constructor with URL, type, and ID.
202: * The behavior is identical to
203: * <code>new Invocation(url, type, ID, true, null)</code>.
204: *
205: * @param url the URL of the content to be dispatched;
206: * may be <code>null</code>
207: * @param type the content type; may be <code>null</code>
208: * @param ID the ID of the content handler; may be <code>null</code>
209: */
210: public Invocation(String url, String type, String ID) {
211: this (url, type, ID, true, null);
212: }
213:
214: /**
215: * Convenient alternative constructor with URL and type.
216: * The behavior is identical to
217: * <code>new Invocation(url, type, null, true, null)</code>.
218: *
219: * @param url the URL of the content to be dispatched;
220: * may be <code>null</code>
221: * @param type the content type; may be <code>null</code>
222: */
223: public Invocation(String url, String type) {
224: this (url, type, null, true, null);
225: }
226:
227: /**
228: * Convenient alternative constructor with a URL.
229: * The behavior is identical to
230: * <code>new Invocation(url, null, null, true, null)</code>.
231: *
232: * @param url the URL of the content to be dispatched;
233: * may be <code>null</code>
234: */
235: public Invocation(String url) {
236: this (url, null, null, true, null);
237: }
238:
239: /**
240: * Creates a new instance and initializes it from the
241: * specified parameters.
242: * The status of the new Invocation is <code>INIT</code>.
243: * None of the values are checked until the
244: * {@link Registry#invoke Registry.invoke}
245: * method is called.
246: * String arguments or data can be set with
247: * {@link #setArgs setArgs} or {@link #setData setData}.
248: *
249: * @param url the URL of the content to be dispatched;
250: * may be <code>null</code>
251: * @param type the content type; may be <code>null</code>
252: * @param ID the ID of the content handler; may be <code>null</code>
253: * @param responseRequired <code>true</code> if a response is
254: * required; <code>false</code> otherwise
255: * @param action the action that the content handler should perform on the
256: * content; may be <code>null</code>
257: */
258: public Invocation(String url, String type, String ID,
259: boolean responseRequired, String action) {
260: this ();
261: invocImpl.setURL(url);
262: invocImpl.setType(type);
263: invocImpl.setID(ID);
264: invocImpl.setResponseRequired(responseRequired);
265: invocImpl.setAction(action);
266: }
267:
268: /**
269: * Creates a new Invocation to refer to an InvocationImpl.
270: * And makes the InvocationImpl refer to the new Invocation.
271: * @param impl and InvocationImpl to be associated with this Invocation
272: */
273: Invocation(InvocationImpl impl) {
274: invocImpl = impl;
275: if (impl != null) {
276: impl.invocation = this ;
277: }
278: }
279:
280: /**
281: * Sets the argument list to a new array of Strings. The arguments
282: * are used by the application to communicate to the content
283: * handler and return results from the content handler.
284: * The values of the arguments are not checked when they are set.
285: * Instead, they are checked during
286: * {@link Registry#invoke Registry.invoke} to
287: * check that none of the values are <code>null</code>.
288: * @param args the String array; may be <code>null</code>.
289: * A <code>null</code>
290: * argument is treated the same as a zero-length array
291: * @see #getArgs
292: */
293: public void setArgs(String[] args) {
294: invocImpl.setArgs(args);
295: }
296:
297: /**
298: * Gets the argument list as an array of Strings. These values
299: * are passed to the content handler and are returned from
300: * the content handler.
301: * The array is not copied; modifications to array elements
302: * will be visible.
303: * @return the arguments array, which MUST NOT be <code>null</code>
304: * @see #setArgs
305: */
306: public String[] getArgs() {
307: return invocImpl.getArgs();
308: }
309:
310: /**
311: * Sets the data used for the Invocation. The data
312: * is used by the application to communicate to the content
313: * handler and return data from the content handler.
314: * The array is not copied until the Invocation is <code>invoked</code>
315: * or <code>finish</code>ed;
316: * modifications to array elements will otherwise be visible.
317: *
318: * @param data the byte data array; may be <code>null</code>.
319: * A <code>null</code> is treated the same as a zero-length array
320: * @see #getData
321: */
322: public void setData(byte[] data) {
323: invocImpl.setData(data);
324: }
325:
326: /**
327: * Gets the data for the Invocation. The data
328: * is passed to the content handler.
329: * The content handler may modify and return the data
330: * if it returns a response.
331: *
332: * @return the data array, which MUST NOT be <code>null</code>
333: * @see #setData
334: */
335: public byte[] getData() {
336: return invocImpl.getData();
337: }
338:
339: /**
340: * Gets the URL for the invocation.
341: * The URL must be equal to the value set with {@link #setURL setURL}.
342: * @return the URL or <code>null</code> if it has not been set
343: * @see #setURL
344: */
345: public String getURL() {
346: return invocImpl.getURL();
347: }
348:
349: /**
350: * Sets the URL for the invocation.
351: * @param url the URL to be set; may be <code>null</code>
352: * @see #getURL
353: */
354: public void setURL(String url) {
355: invocImpl.setURL(url);
356: }
357:
358: /**
359: * Gets the content type for the Invocation.
360: * The type for this Invocation may be set by the application using
361: * {@link #setType setType}.
362: * The {@link #findType findType} method can be used by an application
363: * to find the type by accessing the content via the URL.
364: * When found, <code>findType</code> sets the type returned
365: * by <code>getType</code>.
366: *
367: * @return the content type or <code>null</code> if it has not been set
368: * @see #setType
369: * @see #findType
370: */
371: public String getType() {
372: return invocImpl.getType();
373: }
374:
375: /**
376: * Sets the type for the Invocation.
377: * @param type the type to be set for the content; may be <code>null</code>
378: * @see #getType
379: * @see #findType
380: */
381: public void setType(String type) {
382: invocImpl.setType(type);
383: }
384:
385: /**
386: * Gets the action to be performed on the content.
387: * @return the content action or <code>null</code> if it has not been set
388: * @see #setAction
389: */
390: public String getAction() {
391: return invocImpl.getAction();
392: }
393:
394: /**
395: * Sets the action to be performed on the content.
396: * @param action the action to be performed on the content;
397: * may be <code>null</code>
398: * @see #getAction
399: */
400: public void setAction(String action) {
401: invocImpl.setAction(action);
402: }
403:
404: /**
405: * Gets the <code>responseRequired</code> mode for
406: * this Invocation.
407: * If <code>true</code>, then the invoking application requires a
408: * response to the Invocation.
409: * @return the current value of the <code>responseRequired</code>
410: * mode. If
411: * <code>true</code>, then a response must be returned to the
412: * invoking application.
413: * @see #setResponseRequired
414: */
415: public boolean getResponseRequired() {
416: return invocImpl.getResponseRequired();
417: }
418:
419: /**
420: * Sets the <code>responseRequired</code> mode for
421: * this Invocation.
422: * If <code>true</code>, then the invoking application requires a
423: * response to the Invocation.
424: * The value in the request can be changed only if the status is
425: * <code>INIT</code>.
426: * @param responseRequired
427: * <code>true</code> to require a response,
428: * <code>false</code> otherwise
429: * @exception IllegalStateException is thrown if the status is not
430: * <code>INIT</code>
431: * @see #getResponseRequired
432: */
433: public void setResponseRequired(boolean responseRequired) {
434: invocImpl.setResponseRequired(responseRequired);
435: }
436:
437: /**
438: * Gets the status of this Invocation, which can be
439: * <code>INIT</code>, <code>WAITING</code>, <code>HOLD</code>,
440: * <code>ACTIVE</code>, <code>OK</code>,
441: * <code>CANCELLED</code>,
442: * <code>INITIATED</code>, or <code>ERROR</code>.
443: *
444: * @return the status of this Invocation
445: *
446: * @see Registry#invoke
447: * @see Registry#getResponse
448: * @see ContentHandlerServer#getRequest
449: * @see ContentHandlerServer#finish
450: */
451: public int getStatus() {
452: // Delegated to the implementation class
453: return invocImpl.getStatus();
454: }
455:
456: /**
457: * Gets the content handler ID for this Invocation.
458: *
459: * @return the ID of the ContentHandler; may be
460: * <code>null</code>
461: * @see Registry#forID
462: * @see #setID
463: */
464: public String getID() {
465: // Delegated to the implementation class
466: return invocImpl.getID();
467: }
468:
469: /**
470: * Sets the ID of the content handler for this Invocation.
471: * @param ID of the content handler; may be <code>null</code>
472: * @see #getID
473: */
474: public void setID(String ID) {
475: // Delegated to the implementation class
476: invocImpl.setID(ID);
477: }
478:
479: /**
480: * Gets the previous Invocation saved in this
481: * Invocation by
482: * {@link Registry#invoke Registry.invoke} or
483: * {@link Registry#getResponse Registry.getResponse}.
484: * Invocations returned by
485: * {@link ContentHandlerServer#getRequest ContentHandlerServer.getRequest}
486: * MUST return <code>null</code>.
487: *
488: * @return the previous Invocation, if any, saved when this
489: * Invocation was invoked or returned as a response;
490: * may be <code>null</code>
491: *
492: * @see Registry#invoke
493: * @see Registry#getResponse
494: */
495: public Invocation getPrevious() {
496: InvocationImpl prev = invocImpl.getPrevious();
497: if (prev != null) {
498: if (prev.invocation == null) {
499: /*
500: * An InvocationImpl created by the implementation needs
501: * a Invocation to return to the application.
502: */
503: prev.invocation = new Invocation(prev);
504: }
505: return prev.invocation;
506: } else {
507: return null;
508: }
509: }
510:
511: /**
512: * Gets the authority, if any, used to authenticate the
513: * application that invoked this request.
514: * This value MUST be <code>null</code> unless the device has been
515: * able to authenticate this application.
516: * If <code>non-null</code>, it is the string identifying the
517: * authority.
518: *
519: * @return the authority used to authenticate this application
520: * and if the status is either <code>ACTIVE</code> or <code>HOLD</code>;
521: * otherwise it is <code>null</code>,
522: * the application has not been authenticated
523: *
524: * @see ContentHandler#getAuthority
525: */
526: public String getInvokingAuthority() {
527: // Delegated to the implementation class
528: return invocImpl.getInvokingAuthority();
529: }
530:
531: /**
532: * Gets the ID of the application that invoked the content
533: * handler. This information is available only if the status is
534: * <code>ACTIVE</code> or <code>HOLD</code>.
535: *
536: * This information has been authenticated only if
537: * <code>getInvokingAuthority</code> is non-null.
538: *
539: * @return the invoking application's ID if the Invocation status
540: * is <code>ACTIVE</code>
541: * or <code>HOLD</code>; <code>null</code> otherwise
542: *
543: * @see Registry#getID
544: */
545: public String getInvokingID() {
546: // Delegated to the implementation class
547: return invocImpl.getInvokingID();
548: }
549:
550: /**
551: * Get the user-friendly name of the application that invoked
552: * the content handler. This information is available only if the status is
553: * <code>ACTIVE</code> or <code>HOLD</code>.
554: *
555: * This information has been authenticated only if
556: * <code>getInvokingAuthority</code> is non-null.
557: *
558: * @return the application's name if status is <code>ACTIVE</code>
559: * or <code>HOLD</code>; <code>null</code> otherwise
560: *
561: * @see ContentHandler#getID
562: */
563: public String getInvokingAppName() {
564: // Delegated to the implementation class
565: return invocImpl.getInvokingAppName();
566: }
567:
568: /**
569: * Finds the type of the content in this Invocation.
570: * If the <tt>getType</tt> method return value is
571: * <code>non-null</code>, then the type is returned.
572: * <p>
573: * If the type is <code>null</code> and the URL is non-<code>null</code>,
574: * then the content type will be found by accessing the content
575: * through the URL.
576: * When found, the type is set as if the <code>setType</code> method
577: * was called; subsequent calls to
578: * {@link #getType getType} and {@link #findType findType}
579: * will return the type.
580: * If an exception is thrown, the <code>getType</code> method will
581: * return <code>null</code>.
582: * <p>
583: * The calling thread blocks while the type is being determined.
584: * If a network access is needed there may be an associated delay.
585: *
586: * @return the <code>non-null</code> content type
587: * @exception IOException if access to the content fails
588: *
589: * @exception ContentHandlerException is thrown with a reason of
590: * {@link ContentHandlerException#TYPE_UNKNOWN}
591: * if the type is <code>null</code> and cannot be found from the
592: * content either because the URL is <code>null</code> or the type is
593: * not available from the content
594: * @exception IllegalArgumentException if the content is accessed via
595: * the URL and the URL is invalid
596: * @exception SecurityException is thrown if access to the content
597: * is required and is not permitted
598: *
599: * @see Invocation#setType
600: * @see Invocation#getType
601: */
602: public String findType() throws IOException,
603: ContentHandlerException, SecurityException {
604: // Delegated to the implementation class
605: return invocImpl.findType();
606: }
607:
608: /**
609: * Creates and opens a Connection to the content addressed by
610: * the URL in {@link #getURL getURL}. This method is
611: * similar to <code>Connector.open(getURL(), READ, timeouts)</code>
612: * but may deliver the content from a cache.
613: * The application should use this method to access the
614: * content of the URL
615: * so that any type or content information cached by the
616: * implementation can be utilized. The content is opened
617: * in read only mode.
618: * Regardless of whether or not the content is cached, the
619: * application or content handler must have permission to access
620: * the content via the URL.
621: *
622: * @param timeouts a flag to indicate that the caller
623: * wants timeout exceptions
624: * @return a Connection object
625: *
626: * @exception ConnectionNotFoundException is thrown if:
627: * <ul>
628: * <li>the target URL can not be found, or</li>
629: * <li>the requested protocol type is not supported</li>
630: * </ul>
631: * @exception NullPointerException if the URL is null
632: * @exception IllegalArgumentException if a parameter is invalid.
633: * @exception IOException if some other kind of I/O error occurs
634: * @exception SecurityException is thrown if access to the
635: * protocol handler is prohibited
636: */
637: public Connection open(boolean timeouts) throws IOException,
638: SecurityException {
639: String url = getURL();
640: url.length(); // Throw NPE if null
641: Connection conn = Connector.open(url, Connector.READ, timeouts);
642: return conn;
643: }
644:
645: /**
646: * Provide the credentials needed to access the content.
647: * Use of the credential is protocol specific.
648: * @param username the username; may be <code>null</code>
649: * @param password the password for the username;
650: * may be <code>null</code>
651: */
652: public void setCredentials(String username, char[] password) {
653: invocImpl.setCredentials(username, password);
654: }
655:
656: /**
657: * Gets the InvocationImpl for this Invocation.
658: * @return the InvocationImpl delgate.
659: */
660: InvocationImpl getInvocImpl() {
661: return invocImpl;
662: }
663:
664: /**
665: * Sets the InvocationImpl for this Invocation.
666: * @param invocImpl the InvocationImpl delgate.
667: */
668: void setInvocImpl(InvocationImpl invocImpl) {
669: this.invocImpl = invocImpl;
670: }
671: }
|