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.main;
028:
029: import java.io.IOException;
030:
031: import javax.microedition.io.Connection;
032: import javax.microedition.io.ConnectionNotFoundException;
033: import javax.microedition.io.Connector;
034: import javax.microedition.io.HttpConnection;
035:
036: import com.sun.midp.io.Util;
037:
038: import com.sun.midp.log.Logging;
039: import com.sun.midp.log.LogChannels;
040:
041: import com.sun.midp.midlet.MIDletSuite;
042: import com.sun.midp.midlet.PlatformRequest;
043:
044: import com.sun.midp.security.SecurityToken;
045:
046: /**
047: * Implements platform request functionality for CLDC platform.
048: */
049: class CldcPlatformRequest implements PlatformRequest {
050:
051: /** Class name of the installer use for plaformRequest. */
052: static final String INSTALLER_CLASS = "com.sun.midp.installer.GraphicalInstaller";
053:
054: /** Media-Type for valid application descriptor files. */
055: static final String JAD_MT = "text/vnd.sun.j2me.app-descriptor";
056:
057: /** Media-Type for valid Jar file. */
058: static final String JAR_MT_1 = "application/java";
059:
060: /** Media-Type for valid Jar file. */
061: static final String JAR_MT_2 = "application/java-archive";
062:
063: /** This class has a different security domain than the application. */
064: private SecurityToken securityToken;
065:
066: /**
067: * Initializes the security token for this object, so it can
068: * perform actions that a normal MIDlet Suite cannot.
069: *
070: * @param token security token for this object
071: */
072: CldcPlatformRequest(SecurityToken token) {
073: securityToken = token;
074: }
075:
076: /**
077: * Requests that the device handle (e.g. display or install)
078: * the indicated URL.
079: *
080: * <p>If the platform has the appropriate capabilities and
081: * resources available, it SHOULD bring the appropriate
082: * application to the foreground and let the user interact with
083: * the content, while keeping the MIDlet suite running in the
084: * background. If the platform does not have appropriate
085: * capabilities or resources available, it MAY wait to handle the
086: * URL request until after the MIDlet suite exits. In this case,
087: * when the requesting MIDlet suite exits, the platform MUST then
088: * bring the appropriate application to the foreground to let the
089: * user interact with the content.</p>
090: *
091: * <p>This is a non-blocking method. In addition, this method does
092: * NOT queue multiple requests. On platforms where the MIDlet
093: * suite must exit before the request is handled, the platform
094: * MUST handle only the last request made. On platforms where the
095: * MIDlet suite and the request can be handled concurrently, each
096: * request that the MIDlet suite makes MUST be passed to the
097: * platform software for handling in a timely fashion.</p>
098: *
099: * <p>If the URL specified refers to a MIDlet suite (either an
100: * Application Descriptor or a JAR file), the request is
101: * interpreted as a request to install the named package. In this
102: * case, the platform's normal MIDlet suite installation process
103: * SHOULD be used, and the user MUST be allowed to control the
104: * process (including cancelling the download and/or
105: * installation). If the MIDlet suite being installed is an
106: * <em>update</em> of the currently running MIDlet suite, the
107: * platform MUST first stop the currently running MIDlet suite
108: * before performing the update. On some platforms, the currently
109: * running MIDlet suite MAY need to be stopped before any
110: * installations can occur.</p>
111: *
112: * <p>If the URL specified is of the form
113: * <code>tel:<number></code>, as specified in <a
114: * href="http://rfc.net/rfc2806.html">RFC2806</a>, then the
115: * platform MUST interpret this as a request to initiate a voice
116: * call. The request MUST be passed to the "phone"
117: * application to handle if one is present in the platform.</p>
118: *
119: * <p>Devices MAY choose to support additional URL schemes beyond
120: * the requirements listed above.</p>
121: *
122: * <p>Many of the ways this method will be used could have a
123: * financial impact to the user (e.g. transferring data through a
124: * wireless network, or initiating a voice call). Therefore the
125: * platform MUST ask the user to explicitly acknowledge each
126: * request before the action is taken. Implementation freedoms are
127: * possible so that a pleasant user experience is retained. For
128: * example, some platforms may put up a dialog for each request
129: * asking the user for permission, while other platforms may
130: * launch the appropriate application and populate the URL or
131: * phone number fields, but not take the action until the user
132: * explicitly clicks the load or dial buttons.</p>
133: *
134: * @return true if the MIDlet suite MUST first exit before the
135: * content can be fetched.
136: *
137: * @param URL The URL for the platform to load.
138: *
139: * @exception ConnectionNotFoundException if
140: * the platform cannot handle the URL requested.
141: *
142: */
143: public boolean dispatch(String URL)
144: throws ConnectionNotFoundException {
145: if ("".equals(URL)) {
146: if (Configuration.getIntProperty(
147: "useJavaInstallerForPlaformRequest", 0) != 0) {
148: /*
149: * This is request to try to cancel the last request.
150: *
151: * If the next MIDlet to run is the installer then it can be
152: * cancelled.
153: */
154: if (INSTALLER_CLASS.equals(MIDletSuiteUtils
155: .getNextMIDletToRun())) {
156: /*
157: * Try to cancel the installer midlet. Note this call only
158: * works now because suite are not run concurrently and
159: * must be queued to be run after this MIDlet is
160: * destroyed.
161: * This cancel code can be remove when the installer is
162: * runs concurrently with this suite.
163: */
164: MIDletSuiteUtils.execute(securityToken,
165: MIDletSuite.UNUSED_SUITE_ID, null, null);
166: return false;
167: }
168: }
169:
170: /*
171: * Give the platform a chance to cancel the request.
172: * Note: if the application was launched already this will
173: * not have any effect.
174: */
175: dispatchPlatformRequest("");
176: return false;
177: }
178:
179: /*
180: * Remove this "if", when not using the Installer MIDlet,
181: * or the native installer will not be launched.
182: */
183: if (Configuration.getIntProperty(
184: "useJavaInstallerForPlaformRequest", 0) != 0) {
185: if (isMidletSuiteUrl(URL)) {
186: return dispatchMidletSuiteUrl(URL);
187: }
188: }
189:
190: return dispatchPlatformRequest(URL);
191: }
192:
193: /**
194: * Find out if the given URL is a JAD or JAR HTTP URL by performing a
195: * HTTP head request and checking the MIME type.
196: *
197: * @param url The URL for to check
198: *
199: * @return true if the URL points to a MIDlet suite
200: */
201:
202: private boolean isMidletSuiteUrl(String url) {
203: Connection conn = null;
204: HttpConnection httpConnection = null;
205: String profile;
206: int space;
207: String configuration;
208: String locale;
209: int responseCode;
210: String mediaType;
211:
212: try {
213: conn = Connector.open(url, Connector.READ);
214: } catch (IllegalArgumentException e) {
215: return false;
216: } catch (IOException e) {
217: return false;
218: }
219:
220: try {
221: if (!(conn instanceof HttpConnection)) {
222: // only HTTP or HTTPS are supported
223: return false;
224: }
225:
226: httpConnection = (HttpConnection) conn;
227:
228: httpConnection.setRequestMethod(HttpConnection.HEAD);
229:
230: httpConnection.setRequestProperty("Accept", "*/*");
231:
232: profile = System.getProperty("microedition.profiles");
233: space = profile.indexOf(' ');
234: if (space != -1) {
235: profile = profile.substring(0, space);
236: }
237:
238: configuration = System
239: .getProperty("microedition.configuration");
240: httpConnection.setRequestProperty("User-Agent", "Profile/"
241: + profile + " Configuration/" + configuration);
242:
243: httpConnection.setRequestProperty("Accept-Charset",
244: "UTF-8, ISO-8859-1");
245:
246: /* locale can be null */
247: locale = System.getProperty("microedition.locale");
248: if (locale != null) {
249: httpConnection.setRequestProperty("Accept-Language",
250: locale);
251: }
252:
253: responseCode = httpConnection.getResponseCode();
254:
255: if (responseCode != HttpConnection.HTTP_OK) {
256: return false;
257: }
258:
259: mediaType = Util.getHttpMediaType(httpConnection.getType());
260: if (mediaType == null) {
261: return false;
262: }
263:
264: if (mediaType.equals(JAD_MT) || mediaType.equals(JAR_MT_1)
265: || mediaType.equals(JAR_MT_2)) {
266: return true;
267: }
268:
269: return false;
270: } catch (IOException ioe) {
271: return false;
272: } finally {
273: try {
274: conn.close();
275: } catch (Exception e) {
276: if (Logging.REPORT_LEVEL <= Logging.WARNING) {
277: Logging.report(Logging.WARNING, LogChannels.LC_AMS,
278: "Exception while closing connection");
279: }
280: }
281: }
282: }
283:
284: /**
285: * Dispatches the a JAD or JAD HTTP URL to the Graphical Installer.
286: *
287: * @param url The URL to dispatch
288: *
289: * @return true if the MIDlet suite MUST first exit before the
290: * content can be fetched.
291: */
292: private boolean dispatchMidletSuiteUrl(String url) {
293: return MIDletSuiteUtils.executeWithArgs(securityToken,
294: MIDletSuite.INTERNAL_SUITE_ID, INSTALLER_CLASS,
295: "MIDlet Suite Installer", "I", url, null);
296: }
297:
298: /**
299: * Passes the URL to the native handler.
300: *
301: * @param url The URL for the platform to load.
302: *
303: * @return true if the MIDlet suite MUST first exit before the
304: * content can be fetched.
305: *
306: * @exception ConnectionNotFoundException if
307: * the platform cannot handle the URL requested.
308: */
309: public native final boolean dispatchPlatformRequest(String url)
310: throws ConnectionNotFoundException;
311: }
|