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 com.sun.midp.content;
028:
029: import javax.microedition.content.Registry;
030: import javax.microedition.content.Invocation;
031: import javax.microedition.content.ContentHandler;
032: import javax.microedition.content.ContentHandlerException;
033:
034: import java.io.IOException;
035: import java.io.DataInputStream;
036: import java.io.DataOutputStream;
037:
038: import javax.microedition.io.Connection;
039: import javax.microedition.io.Connector;
040: import javax.microedition.io.HttpConnection;
041:
042: import com.sun.midp.midlet.MIDletSuite;
043:
044: /**
045: * Implementation of Invocation class.
046: * <p>
047: * This class MUST NOT have any public methods that are not also
048: * public in Invocation (the superclass). The sensistive methods
049: * of the class MUST be package private.
050: */
051: public final class InvocationImpl {
052: /**
053: * The Invocation delegating to this instance.
054: * This field is public to Invocation can set it.
055: * This allows the implementation to pass a InvocationImpl to
056: * back to the Invocation class and it can wrap it in an Invocation
057: * before passing it to the application.
058: */
059: public Invocation invocation;
060:
061: /**
062: * The URL of the content; may be <code>null</code>.
063: * URLs of up to and including 256 characters in length MUST be
064: * supported. A URL with a length of zero is treated as
065: * <code>null</code> and is ignored..
066: */
067: String url;
068:
069: /** The content type; may be <code>null</code>. */
070: String type;
071:
072: /** The content handler ID; may be <code>null</code> */
073: String ID;
074:
075: /** The action to perform on the content; may be <code>null</code> */
076: String action;
077:
078: /** The array of arguments; may be <code>null</code> */
079: String[] arguments;
080:
081: /** The length (returned by get0) of the argument array. */
082: int argsLen;
083:
084: /** The data array; may be <code>null</code>. */
085: byte[] data;
086:
087: /** The length (returned by get0) needed for the data array. */
088: int dataLen;
089:
090: /**
091: * Set to <code>true</code> if the invoker must be notified of
092: * completion.
093: */
094: boolean responseRequired;
095:
096: /** The username in case it is needed for authentication. */
097: String username;
098:
099: /** The password in case it is needed for authentication. */
100: String password;
101:
102: /** Transaction Identifier. */
103: int tid;
104:
105: /** The MIDlet suite that should handle this Invocation. */
106: int suiteId;
107:
108: /** The classname of the MIDlet to deliver to. */
109: String classname;
110:
111: /**
112: * The status of the request; one of
113: * {@link Invocation#ACTIVE},
114: * {@link Invocation#WAITING},
115: * {@link Invocation#ERROR},
116: * {@link Invocation#OK}, or
117: * {@link Invocation#CANCELLED}.
118: */
119: int status;
120:
121: /** The authority that authenticated this Invocation. */
122: String invokingAuthority;
123:
124: /** The ID that authenticated this Invocation. */
125: String invokingID;
126:
127: /** The MIDlet suite of the invoking application. */
128: int invokingSuiteId;
129:
130: /** The classname in the invoking MIDlet suite for the response. */
131: String invokingClassname;
132:
133: /** The application name of the invoking MIDlet suite. */
134: String invokingAppName;
135:
136: /** The previous invocation, if any. */
137: InvocationImpl previous;
138:
139: /** The tid of the previous Invocation, if any. */
140: int previousTid;
141:
142: /** A zero length array of strings to re-use when needed. */
143: private static final byte[] ZERO_BYTES = new byte[0];
144:
145: /**
146: * The DISPOSE status is used with {@link #setStatus setStatus}
147: * to discard the native Invocation. It must not overlap with
148: * Status values defined in the Invocation class and must match
149: * STATUS_DISPOSE defined in invocStore.c.
150: */
151: static final int DISPOSE = 100;
152:
153: /**
154: * Create a fresh InvocationImpl.
155: */
156: InvocationImpl() {
157: status = Invocation.INIT;
158: responseRequired = true;
159: arguments = ContentHandlerImpl.ZERO_STRINGS;
160: data = ZERO_BYTES;
161: }
162:
163: /**
164: * Create a fresh InvocationImpl that is being delegated to byte
165: * an Invocation instance created by an application.
166: * @param invocation the Invocation delegating to this implementation
167: */
168: public InvocationImpl(Invocation invocation) {
169: this ();
170: this .invocation = invocation;
171: }
172:
173: /**
174: * Sets the argument list to a new array of Strings. The arguments
175: * are used by the application to communicate to the content
176: * handler and return results from the content handler.
177: * The values of the arguments are not checked when they are set.
178: * Instead, they are checked during
179: * {@link Registry#invoke Registry.invoke} to
180: * check that none of the values are <code>null</code>.
181: * @param args the String array; may be <code>null</code>.
182: * A <code>null</code>
183: * argument is treated the same as a zero-length array
184: * @see #getArgs
185: */
186: public void setArgs(String[] args) {
187: this .arguments = (args == null) ? ContentHandlerImpl.ZERO_STRINGS
188: : args;
189: }
190:
191: /**
192: * Gets the argument list as an array of Strings. These values
193: * are passed to the content handler and are returned from
194: * the content handler.
195: * The array is not copied; modifications to array elements
196: * will be visible.
197: * @return the arguments array, which MUST NOT be <code>null</code>
198: * @see #setArgs
199: */
200: public String[] getArgs() {
201: return arguments;
202: }
203:
204: /**
205: * Sets the data used for the Invocation. The data
206: * is used by the application to communicate to the content
207: * handler and return data from the content handler.
208: * @param data the byte data array; may be <code>null</code>.
209: * A <code>null</code> is treated the same as a zero-length array
210: * @see #getData
211: */
212: public void setData(byte[] data) {
213: this .data = (data == null) ? ZERO_BYTES : data;
214: }
215:
216: /**
217: * Gets the data for the Invocation. The data
218: * is passed to the content handler.
219: * The content handler may modify and return the data
220: * if it returns a response.
221: * The array is not copied; modifications to array elements
222: * will be visible.
223: * @return the data array, which MUST NOT be <code>null</code>
224: * @see #setData
225: */
226: public byte[] getData() {
227: return data;
228: }
229:
230: /**
231: * Gets the URL for the invocation.
232: * The URL must be equal to the value set with {@link #setURL setURL}.
233: * @return the URL or <code>null</code> if it has not been set
234: * @see #setURL
235: */
236: public String getURL() {
237: return url;
238: }
239:
240: /**
241: * Sets the URL for the invocation.
242: * @param url the URL to be set; may be <code>null</code>
243: * @see #getURL
244: */
245: public void setURL(String url) {
246: this .url = url;
247: }
248:
249: /**
250: * Gets the content type for the Invocation.
251: * @return the content type or <code>null</code> if it has not been set
252: * @see #setType
253: * @see #findType
254: */
255: public String getType() {
256: return type;
257: }
258:
259: /**
260: * Sets the type for the Invocation.
261: * @param type the type to be set for the content; may be <code>null</code>
262: * @see #getType
263: */
264: public void setType(String type) {
265: this .type = type;
266: }
267:
268: /**
269: * Gets the action to be performed on the content.
270: * @return the content action or <code>null</code> if it has not been set
271: * @see #setAction
272: */
273: public String getAction() {
274: return action;
275: }
276:
277: /**
278: * Sets the action to be performed on the content.
279: * @param action the action to be performed on the content;
280: * may be <code>null</code>
281: * @see #getAction
282: */
283: public void setAction(String action) {
284: this .action = action;
285: }
286:
287: /**
288: * Gets the <code>responseRequired</code> mode for
289: * this Invocation.
290: * If <code>true</code>, then the invoking application requires a
291: * response to the Invocation.
292: * @return the current value of the <code>responseRequired</code>
293: * mode. If
294: * <code>true</code>, then a response must be returned to the
295: * invoking application.
296: * @see #setResponseRequired
297: */
298: public boolean getResponseRequired() {
299: return responseRequired;
300: }
301:
302: /**
303: * Sets the <code>responseRequired</code> mode for
304: * this Invocation.
305: * If <code>true</code>, then the invoking application requires a
306: * response to the Invocation.
307: * The value in the request can be changed only if the status is
308: * <code>INIT</code>.
309: * @param responseRequired
310: * <code>true</code> to require a response,
311: * <code>false</code> otherwise
312: * @exception IllegalStateException is thrown if the status is not
313: * <code>INIT</code>
314: * @see #getResponseRequired
315: */
316: public void setResponseRequired(boolean responseRequired) {
317: if (getStatus() != Invocation.INIT) {
318: throw new IllegalStateException();
319: }
320: this .responseRequired = responseRequired;
321: }
322:
323: /**
324: * Gets the content handler ID for this Invocation.
325: * @see Registry#forID
326: * @return the ID of the ContentHandler; may be
327: * <code>null</code>
328: * @see #setID
329: */
330: public String getID() {
331: return ID;
332: }
333:
334: /**
335: * Sets the ID of the content handler for this Invocation.
336: * @param ID of the content handler; may be <code>null</code>
337: * @see #getID
338: */
339: public void setID(String ID) {
340: this .ID = ID;
341: }
342:
343: /**
344: * Checks this Invocation and uses the ID, type, URL, and action
345: * find a matching ContentHandler and queue this request to it.
346: * The actual launching of the application is done in the Registry.
347: *
348: * If the <code>previous</code> Invocation is <code>null</code> then
349: * a new transaction is created; otherwise, this
350: * Invocation will use the same transaction as the
351: * <code>previous</code> Invocation.
352: * <p>
353: * The status of this Invocation must be <code>INIT</code>.
354: * If there is a previous Invocation, that Invocation must
355: * have a status of <code>ACTIVE</code>.
356: * <p>
357: * Candidate content handlers are found as described in
358: * {@link Registry#findHandler Registry.findHandler}.
359: * If any handlers are
360: * found, one is arbitrarily selected for this Invocation.
361: * <p>
362: * The status of this Invocation is set to <code>WAITING</code>.
363: * If there is a non-null previous Invocation,
364: * its status is set to <code>HOLD</code>.
365: * A copy of the Invocation is made, the status is set to
366: * <code>ACTIVE</code> and then queued to the
367: * target content handler.
368: * If the invoked content handler is not running, it must be started
369: * as described in <a href="#execution">Invocation Processing</a>.
370: *
371: * <p>
372: * The calling thread blocks while the content handler is being determined.
373: * If a network access is needed there may be an associated delay.
374: *
375: * @param previous a previous Invocation for this Invocation;
376: * may be <code>null</code>
377: * @param handler the ContentHandlerImpl that is the target
378: *
379: * @return <code>true</code> if the application MUST first
380: * voluntarily exit before the content handler can be started;
381: * <code>false</code> otherwise
382: *
383: * @exception IllegalArgumentException is thrown if:
384: * <ul>
385: * <li> the <code>classname</code> does not implement the
386: * lifecycle required by the Java runtime, or </li>
387: * <li> the ID, type, and URL are all <code>null</code>, or </li>
388: * <li> the argument array contains any <code>null</code>
389: * references</li>
390: * </ul>
391: * @exception IOException is thrown if the URL to be accessed is
392: * not available
393: * @exception ContentHandlerException is thrown with a reason of:
394: * <ul>
395: * <li><code>TYPE_UNKNOWN</code> if the type
396: * is not set and cannot be determined from the URL, or</li>
397: * <li><code>NO_REGISTERED_HANDLER</code> if
398: * there is no registered content handler for the type or
399: * ID</li>
400: * </ul>
401: * @exception IllegalStateException is thrown if the status of this
402: * Invocation is not <code>INIT</code> or if the status of the previous
403: * Invocation, if any, is not <code>ACTIVE</code>
404: * @exception SecurityException if an invoke operation is not permitted
405: */
406: boolean invoke(InvocationImpl previous, ContentHandlerImpl handler)
407: throws IllegalArgumentException, IOException,
408: ContentHandlerException {
409: /*
410: * Check all of the arguments for validity.
411: */
412: for (int i = 0; i < arguments.length; i++) {
413: if (arguments[i] == null) {
414: throw new IllegalArgumentException("argument is null");
415: }
416: }
417:
418: if (previous != null) {
419: this .previous = previous;
420: this .previousTid = previous.tid;
421: }
422:
423: // Fill information about the target content handler.
424: setStatus(Invocation.INIT);
425: setID(handler.ID);
426: suiteId = handler.storageId;
427: classname = handler.classname;
428:
429: // Queue this Invocation
430: InvocationStore.put(this );
431:
432: // Launch the target application if necessary.
433: boolean shouldExit = false;
434:
435: try {
436: if (handler.registrationMethod == ContentHandlerImpl.REGISTERED_NATIVE) {
437: shouldExit = RegistryStore.launch(handler);
438: finish(Invocation.INITIATED);
439: } else {
440: try {
441: AppProxy appl = AppProxy.getCurrent().forApp(
442: suiteId, classname);
443: shouldExit = appl.launch(handler.getAppName());
444: // Set the status of this Invocation to WAITING
445: status = Invocation.WAITING;
446: } catch (ClassNotFoundException cnfe) {
447: throw new ContentHandlerException(
448: "Invoked handler has been removed",
449: ContentHandlerException.NO_REGISTERED_HANDLER);
450: }
451: }
452: } catch (ContentHandlerException che) {
453: // remove this invocation from the queue before throwing
454: setStatus(DISPOSE);
455: throw che;
456: }
457:
458: // Set the status of the previous invocation
459: if (previous != null) {
460: previous.setStatus(Invocation.HOLD);
461: }
462: return shouldExit;
463: }
464:
465: /**
466: * Execute the User Environment Policy to select the next
467: * application to run.
468: * Check for and select the next MIDlet suite to run
469: * based on the contents of the Invocation queue.
470: *
471: * From the most recently queued Invocation that is an Invocation
472: * in INIT.
473: * If none, find the most recently queued Invocation that is
474: * a response.
475: */
476: static void invokeNext() {
477: InvocationImpl invoc = null;
478: int tid;
479:
480: // Look for a recently queued Invocation to launch
481: tid = 0;
482: while ((invoc = InvocationStore.getByTid(tid, -1)) != null) {
483: if (invoc.status == Invocation.INIT) {
484: AppProxy.getCurrent().logInfo(
485: "invokeNext has request: " + invoc);
486: if (invoc.suiteId != MIDletSuite.UNUSED_SUITE_ID
487: && invoc.classname != null) {
488: try {
489: AppProxy appl = AppProxy.getCurrent().forApp(
490: invoc.suiteId, invoc.classname);
491: appl.launch("Application");
492: return;
493: } catch (ClassNotFoundException cnfe) {
494: // Ignore
495: }
496: } else if (invoc.ID != null) {
497: // check if it is native handler
498: ContentHandlerImpl handler = RegistryStore
499: .getHandler(null, invoc.ID,
500: RegistryStore.SEARCH_EXACT);
501: if (handler != null
502: && handler.registrationMethod == ContentHandlerImpl.REGISTERED_NATIVE) {
503: try {
504: RegistryStore.launch(handler);
505: invoc.finish(Invocation.INITIATED);
506: continue;
507: } catch (ContentHandlerException che) {
508: // Ignore
509: }
510: }
511: }
512:
513: // can't process this invocation - remove it
514: invoc.setStatus(DISPOSE);
515: } else if (invoc.status == Invocation.ERROR) {
516: AppProxy.getCurrent().logInfo(
517: "invokeNext has response: " + invoc);
518: if (invoc.suiteId != MIDletSuite.UNUSED_SUITE_ID
519: && invoc.classname != null) {
520: try {
521: AppProxy appl = AppProxy.getCurrent().forApp(
522: invoc.suiteId, invoc.classname);
523: appl.launch("Application");
524: return;
525: } catch (ClassNotFoundException cnfe) {
526: // Ignore
527: }
528: }
529:
530: // can't process this invocation - remove it
531: invoc.setStatus(DISPOSE);
532: }
533: tid = invoc.tid;
534: }
535: }
536:
537: /**
538: * Finish this Invocation and set the status for the response.
539: *
540: * @param status the new status of the Invocation. This MUST be either
541: * <code>OK</code> or <code>CANCELLED</code>.
542: *
543: * @return <code>true</code> if the MIDlet suite MUST
544: * voluntarily exit before the response can be returned to the
545: * invoking application
546: *
547: * @exception IllegalArgumentException if the new
548: * <code>status</code> of the Invocation
549: * is not <code>OK</code> or <code>CANCELLED</code>
550: */
551: boolean finish(int status) {
552: if (status != Invocation.OK && status != Invocation.CANCELLED
553: && status != Invocation.INITIATED) {
554: throw new IllegalArgumentException();
555: }
556:
557: /*
558: * If a response is required by the invoking application,
559: * the native code requeues it.
560: * The application mutable parameters are saved to the
561: * native invocation.
562: */
563: if (getResponseRequired()) {
564: if (tid != 0) {
565: InvocationStore.setParams(this );
566: }
567: }
568:
569: setStatus(status);
570:
571: if (getResponseRequired()) {
572: // Launch the target application if necessary.
573: try {
574: AppProxy appl = AppProxy.getCurrent().forApp(suiteId,
575: classname);
576: return appl.launch(invokingAppName);
577: } catch (ClassNotFoundException cnfe) {
578: AppProxy.getCurrent().logInfo(
579: "Unable to launch invoking application "
580: + invokingAppName + "; classname = "
581: + classname + " from suite = "
582: + suiteId);
583: }
584: }
585: return false;
586: }
587:
588: /**
589: * Creates and opens a Connection to the content accessable by
590: * using the URL. This method is
591: * equivalent to
592: * {@link javax.microedition.io.Connector#open Connector.open}
593: * with the URL provided.
594: * The application should use this method to access the
595: * content of the URL
596: * so that any type or content information cached by the
597: * implementation can be fully utilized. The content is opened
598: * in read only mode.
599: *
600: * @param timeouts a flag to indicate that the caller
601: * wants timeout exceptions
602: * @return a Connection object
603: *
604: * @exception ConnectionNotFoundException is thrown if:
605: * <ul>
606: * <li>there is no URL, or</li>
607: * <li>the target URL cannot be found, or</li>
608: * <li>the requested protocol type is not supported</li>
609: * </ul>
610: * @exception IOException if some other kind of I/O error occurs
611: * @exception SecurityException may be thrown if access to the
612: * protocol handler is prohibited
613: */
614: public Connection open(boolean timeouts) throws IOException {
615: Connection conn = Connector.open(getURL(), Connector.READ,
616: timeouts);
617: return conn;
618: }
619:
620: /**
621: * Provide the credentials needed to access the content.
622: * @param username the username; may be <code>null</code>
623: * @param password the password for the username;
624: * may be <code>null</code>
625: */
626: public void setCredentials(String username, char[] password) {
627: this .username = username;
628: this .password = (password == null) ? null
629: : new String(password);
630:
631: }
632:
633: /**
634: * Returns the status of this Invocation, which can be
635: * <code>INIT</code>, <code>WAITING</code>, <code>HOLD</code>,
636: * <code>ACTIVE</code>, <code>OK</code>,
637: * <code>CANCELLED</code>, or <code>ERROR</code>.
638: * The application uses the status to determine how
639: * to process an Invocation returned from
640: * <code>getInvocation</code>.
641: *
642: * @see javax.microedition.content.Registry#invoke
643: *
644: * @return the current status of this Invocation
645: */
646: public int getStatus() {
647: return status;
648: }
649:
650: /**
651: * Set the status of this InvocationImpl.
652: * If the invocation is still active in the native code
653: * set the status in native also.
654: * @param status the new status
655: */
656: void setStatus(int status) {
657: this .status = status;
658: if (tid != 0) {
659: InvocationStore.setStatus(this );
660: }
661: }
662:
663: /**
664: * Finds the type of the content in this Invocation.
665: * If the <tt>getType</tt> method return value is
666: * <code>non-null</code>, then the type is returned.
667: * <p>
668: * If the type is <code>null</code> and the URL is non-<code>null</code>,
669: * then the content type will be found by accessing the content
670: * through the URL.
671: * When found, the type is set as if the <code>setType</code> method
672: * was called; subsequent calls to
673: * {@link #getType getType} and {@link #findType findType}
674: * will return the type.
675: * If an exception is thrown, the <code>getType</code> method will
676: * return <code>null</code>.
677: * <p>
678: * The calling thread blocks while the type is being determined.
679: * If a network access is needed there may be an associated delay.
680: *
681: * @return the <code>non-null</code> content type
682: * @exception IOException if access to the content fails
683: *
684: * @exception ContentHandlerException is thrown with a reason of
685: * {@link ContentHandlerException#TYPE_UNKNOWN}
686: * if the type is <code>null</code> and cannot be found from the
687: * content either because the URL is <code>null</code> or the type is
688: * not available from the content
689: * @exception IllegalArgumentException if the content is accessed via
690: * the URL and the URL is invalid
691: * @exception SecurityException is thrown if access to the content
692: * is required and is not permitted
693: */
694: public String findType() throws IOException,
695: ContentHandlerException {
696: if (type != null) {
697: return type;
698: }
699: if (url == null) {
700: // No URL to examine, leave the type null
701: throw new ContentHandlerException("URL is null",
702: ContentHandlerException.TYPE_UNKNOWN);
703: }
704:
705: // Open a connection to the content.
706: Connection conn = null;
707: int rc = 0;
708: try {
709: while (true) {
710: // Loop to enable redirects.
711: conn = Connector.open(url);
712: if (conn instanceof HttpConnection) {
713: HttpConnection httpc = (HttpConnection) conn;
714: httpc.setRequestMethod(httpc.HEAD);
715:
716: // Get the response code
717: rc = httpc.getResponseCode();
718: if (rc == HttpConnection.HTTP_OK) {
719: type = httpc.getType();
720: if (type != null) {
721: // Check for and remove any parameters (rfc2616)
722: int ndx = type.indexOf(';');
723: if (ndx >= 0) {
724: type = type.substring(0, ndx);
725: }
726: type = type.trim();
727: }
728: if (type == null || type.length() == 0) {
729: type = null;
730: throw new ContentHandlerException(
731: "unable to determine type",
732: ContentHandlerException.TYPE_UNKNOWN);
733: }
734: break;
735: } else if (rc == HttpConnection.HTTP_TEMP_REDIRECT
736: || rc == HttpConnection.HTTP_MOVED_TEMP
737: || rc == HttpConnection.HTTP_MOVED_PERM) {
738: // Get the new location and close the connection
739: url = httpc.getHeaderField("location");
740:
741: conn.close();
742: conn = null;
743: continue; // restart with the new url
744: } else {
745: throw new IOException("http status: " + rc);
746: }
747: } else {
748: // Not HTTP, this isn't going to work
749: // TBD: Check suffixes
750: throw new ContentHandlerException(
751: "URL scheme not supported",
752: ContentHandlerException.TYPE_UNKNOWN);
753: }
754: }
755:
756: } finally {
757: if (conn != null) {
758: try {
759: conn.close();
760: } catch (Exception ex) {
761: }
762: }
763: }
764: return type;
765: }
766:
767: /**
768: * Returns the previous Invocation linked to this
769: * Invocation by this application's previous call to
770: * {@link Registry#invoke(Invocation invoc, Invocation previous)}.
771: *
772: * @return the previous Invocation, if any, set when this
773: * Invocation was invoked;
774: * <code>null</code> is returned if the Invocation was not
775: * invoked with a previous Invocation.
776: */
777: public InvocationImpl getPrevious() {
778: return previous;
779: }
780:
781: /**
782: * Gets the authority, if any, used to authenticate the
783: * application that invoked this request.
784: * This value MUST be <code>null</code> unless the device has been
785: * able to authenticate this application.
786: * If <code>non-null</code>, it is the string identifiying the
787: * authority. For example,
788: * if the application was a signed MIDlet, then this is the
789: * "subject" of the certificate used to sign the application.
790: *
791: * <p>The format of the authority for X.509 certificates is defined
792: * by the MIDP Printable Representation of X.509 Distinguished
793: * Names as defined in class
794: *
795: * <code>javax.microedition.pki.Certificate</code>. </p>
796: * @return the authority used to authenticate this application
797: * or <code>null</code> otherwise
798: *
799: * @exception IllegalStateException if the current status is not
800: * <code>ACTIVE</code> or <code>HOLD</code>
801: *
802: * @see ContentHandler#getAuthority
803: */
804: public String getInvokingAuthority() {
805: if (status != Invocation.ACTIVE && status != Invocation.HOLD) {
806: return null;
807: }
808: return invokingAuthority;
809: }
810:
811: /**
812: * Get the user-friendly name of the application that invoked
813: * the content handler. This information is available only if the status is
814: * <code>ACTIVE</code> or <code>HOLD</code>.
815: *
816: * This information has been authenticated only if
817: * <code>getInvokingAuthority</code> is non-null.
818: *
819: * @return the application's name if status is <code>ACTIVE</code>
820: * or <code>HOLD</code>; <code>null</code> otherwise
821: *
822: * @see ContentHandler#getID
823: */
824: public String getInvokingAppName() {
825: if (status != Invocation.ACTIVE && status != Invocation.HOLD) {
826: return null;
827: }
828: return invokingAppName;
829: }
830:
831: /**
832: * Gets the ID of the application that invoked the content
833: * handler. This information is available only if the status is
834: * <code>ACTIVE</code> or <code>HOLD</code>.
835: *
836: * This information has been authenticated only if
837: * <code>getInvokingAuthority</code> is non-null.
838: *
839: * @return the application's ID if status is <code>ACTIVE</code>
840: * or <code>HOLD</code>; <code>null</code> otherwise
841: *
842: * @exception IllegalStateException if the current status is not
843: * <code>ACTIVE</code> or <code>HOLD</code>
844: *
845: * @see ContentHandler#getID
846: */
847: public String getInvokingID() {
848: if (status != Invocation.ACTIVE && status != Invocation.HOLD) {
849: return null;
850: }
851: return invokingID;
852: }
853:
854: /**
855: * Return a printable form of InvocationImpl.
856: * Disabled if not logging
857: * @return a String containing a printable form
858: */
859: public String toString() {
860: if (AppProxy.LOG_INFO) {
861: StringBuffer sb = new StringBuffer(200);
862: sb.append("tid: ");
863: sb.append(tid);
864: sb.append(" status: ");
865: sb.append(status);
866: // sb.append(" suiteId: "); sb.append(suiteId);
867: sb.append(", type: ");
868: sb.append(getType());
869: sb.append(", url: ");
870: sb.append(getURL());
871: sb.append(", respReq: ");
872: sb.append(getResponseRequired());
873: // sb.append(", args: "); sb.append(getArgs());
874: // sb.append(", prevTid: "); sb.append(previousTid);
875: // sb.append(", previous: ");
876: // sb.append((previous == null) ? "null" : "non-null");
877: // sb.append("_suiteId: "); sb.append(invokingSuiteId);
878: sb.append("\n invokee: ");
879: sb.append(classname);
880: sb.append(", invoker: ");
881: sb.append(invokingClassname);
882: // sb.append(", _authority: "); sb.append(invokingAuthority);
883: // sb.append(", _ID: "); sb.append(invokingID);
884: return sb.toString();
885: } else {
886: return super.toString();
887: }
888: }
889: }
|