/* * * Copyright 1990-2008 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. */ /* * @(#)AMS.java 1.5 06/10/10 */ package com.sun.javax.microedition.midlet; import javax.microedition.midlet.*; import java.util.jar.*; import java.util.*; import java.io.*; import java.net.URL; import sun.misc.MIDletClassLoader; import sun.misc.MIDPImplementationClassLoader; import sun.misc.MemberFilter; import sun.misc.MIDPConfig; import java.security.PermissionCollection; import java.security.Permissions; /* * A pair of strings used for maintaining our MIDlet suite table of contents. */ class MIDletPair { String name; String className; public MIDletPair(String printname, String classname){ name = printname; className = classname; } } public class AMS implements MidletAMS { /* * Shared structures: * These are used by all midlet suites */ static MIDPImplementationClassLoader midpImpl; static boolean setup = false; /* * Per-midlet-suite structures: * This includes the JAR that we're loading out of, * the table of contents, which we read from the manifest, * and the class loader we set up to load the midlets. * If we were managing muliple midlets at once, then we'd * also have a collection of MIDlets here, and perhaps of * Threads as well. */ String midpURL; // url of a JAR String midpPath; // file path of JAR JarFile midpSuite; // the JAR once its open MIDletPair toc[]; // JAR manifest information int tocSize; MIDletClassLoader midpSuiteLoader; /* * Construct one AMS instance per midlet suite. */ public AMS(){ } /* * Some places we want a file name, * some places we want a URL. */ static String filenameToURL(String filename){ java.io.File f = new File(filename); String longname; try { longname = f.getCanonicalPath(); } catch (IOException e ){ throw new Error("IOException"); } return longname; } /* * Table-of-contents management. * Read from the MIDlet suite manifest. * Print. */ void formToc(Manifest m){ Vector tempToc = new Vector(); int nameend; int imageend; int ordinal = 1; Attributes attr = m.getMainAttributes(); while(true){ // this assumes well-formed entries. String attributeName = "MIDlet-".concat(Integer.toString(ordinal)); String attributeValue = attr.getValue(attributeName); if (attributeValue == null) break; nameend = attributeValue.indexOf(','); imageend = attributeValue.lastIndexOf(','); tempToc.add( new MIDletPair( attributeValue.substring(0,nameend), attributeValue.substring(imageend+1) ) ); ordinal += 1; } toc = new MIDletPair[ordinal-1]; tempToc.copyInto(toc); tocSize = ordinal-1; } void printToc(){ for (int i=0; i<tocSize; i++ ){ System.out.print(" "); System.out.print(i+1); System.out.print("\t"); System.out.println(toc[i].name); } } byte inBuff[] = new byte[10]; // private to promptForMidletNumber int promptForMidletNumber(){ int nchars = 0; int v; while(true){ printToc(); System.out.print("midletNumber (eof to end)? "); try { nchars = System.in.read(inBuff); }catch(IOException e){ // don't try to deal with error. return 0; } if (nchars <= 0) return 0; // EOF. if (inBuff[nchars-1] == '\n') nchars -= 1; // exclude newline from int conversion. String numString = new String(inBuff, 0, nchars); try { v = Integer.parseInt(numString); }catch(NumberFormatException e){ System.out.print(numString); System.out.println(" not recognized as decimal integer"); continue; } if (v < 0 || v > tocSize ){ System.out.print(numString); System.out.println(" out of range"); continue; } return v; } } /* * Once only: all AMS instances share the same * MIDPImplementationClassLoader and MemberFilter * Security needs to be turned on only once. * Would more logically be static and invoked using * reflection, but that would be more work and would not be * very enlightening. */ public boolean setupSharedState(MIDPImplementationClassLoader m, MemberFilter f) throws SecurityException { if (setup == true) return false; // once only. /* * Initialize the shared resources we'll use: * the MemberFilter and the MIDPImplementationClassLoader */ midpImpl = m; if (midpImpl == null){ System.out.println("MIDPImplementationClassLoader is null"); return false; } /* * Make sure that a security manager is installed. */ if (System.getSecurityManager() == null) System.setSecurityManager( new java.lang.SecurityManager() ); setup = true; return true; } /* * Per-instance: each gets a different path to the jar containing * the midlet suite. * * Read the manifest so we know what the midlets in the suite are. * Make a MIDletClassLoader to load classes from it. */ public boolean initializeSuite(String path){ Manifest m; midpPath = path; midpURL = filenameToURL(path); try{ midpSuite = new JarFile(midpPath); } catch (IOException e){ System.err.println("Caught error opening "+midpPath); e.printStackTrace(); return false; } try{ m = midpSuite.getManifest(); } catch (IOException e){ System.err.println("Caught error getting manifest from "+midpPath); e.printStackTrace(); return false; } if (m == null){ System.err.println("JAR file has no manifest: "+midpPath); return false; } formToc(m); midpSuiteLoader = MIDPConfig.newMIDletClassLoader(new String[]{midpURL}); if (midpSuiteLoader == null){ System.err.println("Could not instantiate MIDletClassLoader"); return false; } return true; } /* * promptForMidletNumber will display the menu of midlets * and wait for user input (very crude, but we have no * other user interface here). Run the midlet indicated. * When it is done, repeat. */ public void runSuite(){ while (true){ int midletNumber = promptForMidletNumber(); if (midletNumber <= 0){ System.out.println(); return; } /*DEBUG*/System.out.println("Running MIDlet named "+ toc[midletNumber-1].name+" from class "+ toc[midletNumber-1].className + " in path "+midpPath); runMidlet( toc[midletNumber-1].className ); } } /* * Try to load the designated class using the midpSuiteLoader. * Cast it to a midlet. * Start it. * */ public void runMidlet(String classname) { Class targetClass; MIDlet m; try { targetClass = midpSuiteLoader.loadClass(classname, true); } catch (Exception e){ System.err.println("MIDlet class lookup:"); e.printStackTrace(); return; } try{ m = (MIDlet)targetClass.newInstance(); m.startApp(); }catch(Throwable e){ System.err.println("MIDlet create/start:"); e.printStackTrace(); return; } } }