001: /*
002: *
003: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: /*
027: * @(#)AMS.java 1.5 06/10/10
028: */
029: package com.sun.javax.microedition.midlet;
030:
031: import javax.microedition.midlet.*;
032: import java.util.jar.*;
033: import java.util.*;
034: import java.io.*;
035: import java.net.URL;
036: import sun.misc.MIDletClassLoader;
037: import sun.misc.MIDPImplementationClassLoader;
038: import sun.misc.MemberFilter;
039: import sun.misc.MIDPConfig;
040: import java.security.PermissionCollection;
041: import java.security.Permissions;
042:
043: /*
044: * A pair of strings used for maintaining our MIDlet suite table of contents.
045: */
046: class MIDletPair {
047: String name;
048: String className;
049:
050: public MIDletPair(String printname, String classname) {
051: name = printname;
052: className = classname;
053: }
054: }
055:
056: public class AMS implements MidletAMS {
057:
058: /*
059: * Shared structures:
060: * These are used by all midlet suites
061: */
062: static MIDPImplementationClassLoader midpImpl;
063: static boolean setup = false;
064:
065: /*
066: * Per-midlet-suite structures:
067: * This includes the JAR that we're loading out of,
068: * the table of contents, which we read from the manifest,
069: * and the class loader we set up to load the midlets.
070: * If we were managing muliple midlets at once, then we'd
071: * also have a collection of MIDlets here, and perhaps of
072: * Threads as well.
073: */
074: String midpURL; // url of a JAR
075: String midpPath; // file path of JAR
076: JarFile midpSuite; // the JAR once its open
077: MIDletPair toc[]; // JAR manifest information
078: int tocSize;
079: MIDletClassLoader midpSuiteLoader;
080:
081: /*
082: * Construct one AMS instance per midlet suite.
083: */
084: public AMS() {
085: }
086:
087: /*
088: * Some places we want a file name,
089: * some places we want a URL.
090: */
091: static String filenameToURL(String filename) {
092: java.io.File f = new File(filename);
093: String longname;
094: try {
095: longname = f.getCanonicalPath();
096: } catch (IOException e) {
097: throw new Error("IOException");
098: }
099: return longname;
100: }
101:
102: /*
103: * Table-of-contents management.
104: * Read from the MIDlet suite manifest.
105: * Print.
106: */
107:
108: void formToc(Manifest m) {
109: Vector tempToc = new Vector();
110: int nameend;
111: int imageend;
112: int ordinal = 1;
113: Attributes attr = m.getMainAttributes();
114: while (true) {
115: // this assumes well-formed entries.
116: String attributeName = "MIDlet-".concat(Integer
117: .toString(ordinal));
118: String attributeValue = attr.getValue(attributeName);
119: if (attributeValue == null)
120: break;
121: nameend = attributeValue.indexOf(',');
122: imageend = attributeValue.lastIndexOf(',');
123: tempToc.add(new MIDletPair(attributeValue.substring(0,
124: nameend), attributeValue.substring(imageend + 1)));
125: ordinal += 1;
126: }
127: toc = new MIDletPair[ordinal - 1];
128: tempToc.copyInto(toc);
129: tocSize = ordinal - 1;
130: }
131:
132: void printToc() {
133: for (int i = 0; i < tocSize; i++) {
134: System.out.print(" ");
135: System.out.print(i + 1);
136: System.out.print("\t");
137: System.out.println(toc[i].name);
138: }
139: }
140:
141: byte inBuff[] = new byte[10]; // private to promptForMidletNumber
142:
143: int promptForMidletNumber() {
144: int nchars = 0;
145: int v;
146: while (true) {
147: printToc();
148: System.out.print("midletNumber (eof to end)? ");
149: try {
150: nchars = System.in.read(inBuff);
151: } catch (IOException e) {
152: // don't try to deal with error.
153: return 0;
154: }
155: if (nchars <= 0)
156: return 0; // EOF.
157: if (inBuff[nchars - 1] == '\n')
158: nchars -= 1; // exclude newline from int conversion.
159: String numString = new String(inBuff, 0, nchars);
160: try {
161: v = Integer.parseInt(numString);
162: } catch (NumberFormatException e) {
163: System.out.print(numString);
164: System.out
165: .println(" not recognized as decimal integer");
166: continue;
167: }
168: if (v < 0 || v > tocSize) {
169: System.out.print(numString);
170: System.out.println(" out of range");
171: continue;
172: }
173: return v;
174: }
175: }
176:
177: /*
178: * Once only: all AMS instances share the same
179: * MIDPImplementationClassLoader and MemberFilter
180: * Security needs to be turned on only once.
181: * Would more logically be static and invoked using
182: * reflection, but that would be more work and would not be
183: * very enlightening.
184: */
185: public boolean setupSharedState(MIDPImplementationClassLoader m,
186: MemberFilter f) throws SecurityException {
187: if (setup == true)
188: return false; // once only.
189: /*
190: * Initialize the shared resources we'll use:
191: * the MemberFilter and the MIDPImplementationClassLoader
192: */
193: midpImpl = m;
194: if (midpImpl == null) {
195: System.out.println("MIDPImplementationClassLoader is null");
196: return false;
197: }
198:
199: /*
200: * Make sure that a security manager is installed.
201: */
202: if (System.getSecurityManager() == null)
203: System.setSecurityManager(new java.lang.SecurityManager());
204:
205: setup = true;
206: return true;
207: }
208:
209: /*
210: * Per-instance: each gets a different path to the jar containing
211: * the midlet suite.
212: *
213: * Read the manifest so we know what the midlets in the suite are.
214: * Make a MIDletClassLoader to load classes from it.
215: */
216: public boolean initializeSuite(String path) {
217: Manifest m;
218: midpPath = path;
219: midpURL = filenameToURL(path);
220: try {
221: midpSuite = new JarFile(midpPath);
222: } catch (IOException e) {
223: System.err.println("Caught error opening " + midpPath);
224: e.printStackTrace();
225: return false;
226: }
227: try {
228: m = midpSuite.getManifest();
229: } catch (IOException e) {
230: System.err.println("Caught error getting manifest from "
231: + midpPath);
232: e.printStackTrace();
233: return false;
234: }
235: if (m == null) {
236: System.err.println("JAR file has no manifest: " + midpPath);
237: return false;
238: }
239: formToc(m);
240: midpSuiteLoader = MIDPConfig
241: .newMIDletClassLoader(new String[] { midpURL });
242: if (midpSuiteLoader == null) {
243: System.err
244: .println("Could not instantiate MIDletClassLoader");
245: return false;
246: }
247: return true;
248: }
249:
250: /*
251: * promptForMidletNumber will display the menu of midlets
252: * and wait for user input (very crude, but we have no
253: * other user interface here). Run the midlet indicated.
254: * When it is done, repeat.
255: */
256: public void runSuite() {
257: while (true) {
258: int midletNumber = promptForMidletNumber();
259: if (midletNumber <= 0) {
260: System.out.println();
261: return;
262: }
263: /*DEBUG*/System.out.println("Running MIDlet named "
264: + toc[midletNumber - 1].name + " from class "
265: + toc[midletNumber - 1].className + " in path "
266: + midpPath);
267: runMidlet(toc[midletNumber - 1].className);
268: }
269: }
270:
271: /*
272: * Try to load the designated class using the midpSuiteLoader.
273: * Cast it to a midlet.
274: * Start it.
275: *
276: */
277: public void runMidlet(String classname) {
278: Class targetClass;
279: MIDlet m;
280:
281: try {
282: targetClass = midpSuiteLoader.loadClass(classname, true);
283: } catch (Exception e) {
284: System.err.println("MIDlet class lookup:");
285: e.printStackTrace();
286: return;
287: }
288: try {
289: m = (MIDlet) targetClass.newInstance();
290: m.startApp();
291: } catch (Throwable e) {
292: System.err.println("MIDlet create/start:");
293: e.printStackTrace();
294: return;
295: }
296: }
297:
298: }
|