package ecologylab.appframework; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; import java.util.Stack; import ecologylab.appframework.types.prefs.Pref; import ecologylab.appframework.types.prefs.PrefEnum; import ecologylab.appframework.types.prefs.PrefSet; import ecologylab.appframework.types.prefs.PrefSetBaseClassProvider; import ecologylab.collections.Scope; import ecologylab.generic.Debug; import ecologylab.io.DownloadProcessor; import ecologylab.io.Files; import ecologylab.io.ZipDownload; import ecologylab.net.ParsedURL; import ecologylab.platformspecifics.FundamentalPlatformSpecifics; import ecologylab.serialization.SIMPLTranslationException; import ecologylab.serialization.SimplTypesScope; import ecologylab.serialization.XMLTranslationExceptionTypes; import ecologylab.serialization.formatenums.StringFormat; /** * An instance of Environment, which is an application, rather than an applet, or a servlet. The * Environment mechanism is used to enable the provision of contextual runtime configuration * parameter services in a way that is independent of the deployment structure. * * @author Andruid * @author Zachary O. Toups (zach@ecologylab.net) */ public class ApplicationEnvironment extends Debug implements Environment, XMLTranslationExceptionTypes, ApplicationPropertyNames { static { FundamentalPlatformSpecifics.get().initializePlatformSpecificTranslation(); } public static final PrefEnum LAUNCH_TYPE_PREF = Pref.usePrefEnum( LAUNCH_TYPE, LaunchType.ECLIPSE); /** Subdirectory for eclipse launches. */ protected static final String ECLIPSE_PREFS_DIR = "config/preferences/"; public static final String PREFERENCES = "preferences/"; protected The the = new The(); Scope sessionScope; SimplTypesScope translationScope; /** * Used for forming codeBase relative ParsedURLs. A simulation of the property available in * applets. The codebase is the address where the java code comes from. */ ParsedURL codeBase; /** * Used for forming codeBase relative ParsedURLs. A simulation of the property available in * applets. The docbase is the address where the launching HTML file comes from. */ ParsedURL docBase; /** Set of actual <code>Pref</code>s being used locally. */ PrefSet prefSet; /** Place where <code>Pref</code>s are loaded from and stored to. */ protected ParsedURL prefsPURL; protected String applicationName; protected enum LaunchType { JNLP, LOCAL_JNLP, ECLIPSE, JAR, STUDIES, } protected LaunchType launchType; /** Stores the argument stack for use by subclasses. */ protected Stack<String> argStack; /** * Create an ApplicationEnvironment. Create an empty properties object for application parameters. * <p/> * No command line argument is processed. Only default preferences are loaded, and processed with * the default TranslationSpace. * * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @throws SIMPLTranslationException */ public ApplicationEnvironment(String applicationName) throws SIMPLTranslationException { this(null, applicationName, null); } /** * Create an ApplicationEnvironment. Load preferences from XML file founds in the * config/preferences directory. Default preferences will be loaded from preferences.xml. If there * is a 0th command line argument, that is the name of an additional preferences file. * * @param applicationName * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ public ApplicationEnvironment(String applicationName, SimplTypesScope translationScope, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this(applicationName, translationScope, (SimplTypesScope) null, args, prefsAssetVersion); } /** * Create an ApplicationEnvironment. Load preferences from XML file founds in the * config/preferences directory. Default preferences will be loaded from preferences.xml. If there * is a 0th command line argument, that is the name of an additional preferences file. * * @param applicationName * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param customPrefs * TODO * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ public ApplicationEnvironment(String applicationName, SimplTypesScope translationScope, Class<? extends Pref<?>>[] customPrefs, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this(applicationName, (Scope<?>) null, translationScope, customPrefs, args, prefsAssetVersion); } /** * * @param applicationName * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param sessionScope * @param customPrefs * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * @throws SIMPLTranslationException */ public ApplicationEnvironment(String applicationName, Scope<?> sessionScope, SimplTypesScope translationScope, Class<? extends Pref<?>>[] customPrefs, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this( (Class<?>) null, applicationName, sessionScope, translationScope, prefsClassArrayToTranslationScope(customPrefs), args, prefsAssetVersion); } /** * Create an ApplicationEnvironment. Load preferences from XML file founds in the * config/preferences directory. Default preferences will be loaded from preferences.xml. If there * is a 0th command line argument, that is the name of an additional preferences file. * * @param applicationName * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param customPrefsTranslationScope * TODO * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ public ApplicationEnvironment(String applicationName, SimplTypesScope translationScope, SimplTypesScope customPrefsTranslationScope, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this( (Class<?>) null, applicationName, (Scope<?>) null, translationScope, customPrefsTranslationScope, args, prefsAssetVersion); } /** * Configures a TranslationScope for the PREFS_TRANSLATION_SCOPE using the given customPrefs and * returns it. * * @param customPrefs * @return */ protected static final SimplTypesScope prefsClassArrayToTranslationScope( Class<? extends Pref<?>>[] customPrefs) { // configure the PrefSet translation scope, incorporating custom translations, if any if (customPrefs == null) customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); return SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); } /** * Create an ApplicationEnvironment. Load preferences from XML files found in the * config/preferences directory. Default preferences will be loaded from preferences.xml. If there * is a 0th command line argument, that is the name of an additional preferences file. * <p/> * The default TranslationSpace, from * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * * @param applicationName * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @throws SIMPLTranslationException */ public ApplicationEnvironment(String applicationName, String args[]) throws SIMPLTranslationException { this(applicationName, (SimplTypesScope) null, (SimplTypesScope) null, args, 0); } /** * Create an ApplicationEnvironment. Get the base for finding the path to the "codeBase" by using * the package path of the baseClass passed in. * <p/> * Load preferences from XML file founds in the codeBase/config/preferences directory. Default * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that * is the name of an additional preferences file. * <p/> * Also, sets the Assets cacheRoot to the applicationDir(). * <p/> * The default TranslationSpace, from * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * * @param baseClass * Used for computing codeBase property. * @param applicationName * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full * @throws SIMPLTranslationException */ public ApplicationEnvironment(Class<?> baseClass, String applicationName, String args[]) throws SIMPLTranslationException { this(baseClass, applicationName, null, null, null, args, 0); } /** * Additional constructor to hold the session scope for post processing loaded preferences. * * @param applicationName * @param sessionScope */ public ApplicationEnvironment(Class<?> baseClass, String applicationName, SimplTypesScope translationScope, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this(baseClass, applicationName, null, translationScope, null, args, prefsAssetVersion); } /** * Create an ApplicationEnvironment. * <p/> * Treats the args array like a stack. If any args are missing (based on their format), they are * skipped. * <p/> * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local * relative path, or a URL-based absolute path. * <p/> * The next possible arg is a preferences file. This ends with .xml. * <p/> * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost * half; 3; near full; 4 full * <p/> * Get the base for finding the path to the "codeBase" by using the package path of the baseClass * passed in. * <p/> * Load preferences from XML file founds in the codeBase/config/preferences directory. Default * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that * is the name of an additional preferences file. * <p/> * Also, sets the Assets cacheRoot to the applicationDir(). * <p/> * The default TranslationSpace, from * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * * @param baseClass * Used for computing codeBase property. * @param applicationName * Name of the application. * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ public ApplicationEnvironment(Class<?> baseClass, String applicationName, Scope<?> sessionScope, SimplTypesScope translationScope, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this(baseClass, applicationName, sessionScope, translationScope, null, args, prefsAssetVersion); } /** * Create an ApplicationEnvironment. * <p/> * Treats the args array like a stack. If any args are missing (based on their format), they are * skipped. * <p/> * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local * relative path, or a URL-based absolute path. * <p/> * The next possible arg is a preferences file. This ends with .xml. * <p/> * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost * half; 3; near full; 4 full * <p/> * Get the base for finding the path to the "codeBase" by using the package path of the baseClass * passed in. * <p/> * Load preferences from XML file founds in the codeBase/config/preferences directory. Default * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that * is the name of an additional preferences file. * <p/> * Also, sets the Assets cacheRoot to the applicationDir(). * <p/> * The default TranslationSpace, from * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * * @param baseClass * Used for computing codeBase property. * @param applicationName * Name of the application. * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param customPrefs * An array of Pref subclasses that are used for this specific application. These classes * will be automatically composed into a special translation scope used for translating * prefs for the application. Note that translationScope is NOT used for translating the * application prefs, but is still required for other translations in the application. * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ public ApplicationEnvironment(Class<?> baseClass, String applicationName, Scope<?> sessionScope, SimplTypesScope translationScope, SimplTypesScope customPrefsTranslationScope, String args[], float prefsAssetVersion) throws SIMPLTranslationException { this( baseClass, applicationName, sessionScope, translationScope, customPrefsTranslationScope, makeStack(args), prefsAssetVersion); } /** * Create an ApplicationEnvironment. * <p/> * Treats the args array like a stack. If any args are missing (based on their format), they are * skipped. * <p/> * The first arg we seek is codeBase. This is a path that ends in slash. It may be a local * relative path, or a URL-based absolute path. * <p/> * The next possible arg is a preferences file. This ends with .xml. * <p/> * The next 2 possible args are integers, for graphicsDev and screenSize. graphics_device (screen * number) to display window. count from 0. screenSize used in TopLevel -- 1 - quarter; 2 - almost * half; 3; near full; 4 full * <p/> * Get the base for finding the path to the "codeBase" by using the package path of the baseClass * passed in. * <p/> * Load preferences from XML file founds in the codeBase/config/preferences directory. Default * preferences will be loaded from preferences.xml. If there is a 0th command line argument, that * is the name of an additional preferences file. * <p/> * Also, sets the Assets cacheRoot to the applicationDir(). * <p/> * The default TranslationSpace, from * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * * @param baseClass * Used for computing codeBase property. * @param applicationName * Name of the application. * @param translationScope * TranslationSpace used for translating preferences XML. If this is null, * {@link ecologylab.oodss.messages.DefaultServicesTranslations * ecologylab.oodss.message.DefaultServicesTranslations} will be used. * @param customPrefs * An array of Pref subclasses that are used for this specific application. These classes * will be automatically composed into a special translation scope used for translating * prefs for the application. Note that translationScope is NOT used for translating the * application prefs, but is still required for other translations in the application. * @param args * The args array, which is treated as a stack with optional entries. They are: *) JNLP * -- if that is the launch method *) preferences file if you are running in eclipse. * Relative to CODEBASE/config/preferences/ *) graphics_device (screen number) *) * screen_size (used in TopLevel -- 1 - quarter; 2 - almost half; 3; near full; 4 full) * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ public ApplicationEnvironment(Class<?> baseClass, String applicationName, Scope<?> sessionScope, SimplTypesScope translationScope, SimplTypesScope customPrefsTranslationScope, Stack<String> argStack, float prefsAssetVersion) throws SIMPLTranslationException { this.argStack = argStack; // setup the translations used for prefs SimplTypesScope prefTranslations; if (customPrefsTranslationScope != null) { SimplTypesScope[] arrayToMakeJavaShutUp = { customPrefsTranslationScope }; prefTranslations = SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, arrayToMakeJavaShutUp, PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses()); } else { Class[] customPrefs = PrefSetBaseClassProvider.STATIC_INSTANCE.provideClasses(); prefTranslations = SimplTypesScope.get(PrefSet.PREFS_TRANSLATION_SCOPE, customPrefs); } this.sessionScope = sessionScope; setApplicationName(applicationName); // setup os specific system preferences PropertiesAndDirectories.setOSSpecificProperties(this.applicationName); ZipDownload.setDownloadProcessor(assetsDownloadProcessor()); if (translationScope == null) // default translation scope changed by andruid 5/27/10 translationScope = prefTranslations; // translationScope = DefaultServicesTranslations.get(); this.translationScope = translationScope; processArgsAndPrefs(baseClass, translationScope, prefsAssetVersion); } /** * Sets this.applicationName. * * @param applicationName */ protected void setApplicationName(String applicationName) { this.applicationName = applicationName; } /** Convert the args array into a Stack. */ protected static Stack<String> makeStack(String[] strings) { Stack<String> retStack = new Stack<String>(); if (strings != null) for (int i = strings.length - 1; i >= 0; i--) retStack.push(strings[i]); return retStack; } protected void processArgsAndPrefs(Class<?> baseClass, SimplTypesScope translationScope, float prefsAssetVersion) throws SIMPLTranslationException { processPrefs(baseClass, translationScope, argStack, prefsAssetVersion); Debug.initialize(); } /** * request User's prefSet from the preferenceServlet and return the prefSetXML string. * * @author eunyee * @param prefServlet * @param translationScope * TODO * @param uid * @return */ protected PrefSet requestPrefFromServlet(String prefServlet, SimplTypesScope translationScope) { System.out.println("retrieving preferences set from servlet: " + prefServlet); try { URL url = new URL(prefServlet); URLConnection connection = url.openConnection(); // specify the content type that binary data is sent connection.setRequestProperty("Content-Type", "text/xml"); // define a new BufferedReader on the input stream BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); // receive data from the servlet String prefSetXML = in.readLine(); PrefSet prfs = null; try { prfs = PrefSet.loadFromCharSequence(prefSetXML, translationScope); System.out.println("Prefs loaded From Servlet:: "); if (prfs != null) SimplTypesScope.serialize(prfs, System.out, StringFormat.XML); System.out.println(" --- End Prefs"); } catch (SIMPLTranslationException e) { e.printStackTrace(); } in.close(); return prfs; } catch (IOException e) { warning("not a <pref_set> servlet URL: " + prefServlet); } return null; } /** * Load Prefs, if possible * * @param baseClass * @param translationScope * @param argStack * @param prefsAssetVersion * TODO * @throws SIMPLTranslationException */ private void processPrefs(Class<?> baseClass, SimplTypesScope translationScope, Stack<String> argStack, float prefsAssetVersion) throws SIMPLTranslationException { LaunchType launchType = LaunchType.ECLIPSE; // current default // look for launch method identifier in upper case String arg = pop(argStack); if (arg != null) { String uc = arg.toUpperCase(); if ("JNLP".equals(uc)) { // tells us how we were launched: e.g., JNLP, ECLIPSE, ... launchType = LaunchType.JNLP; } else if ("STUDIES".equals(uc)) { launchType = LaunchType.STUDIES; } else { // TODO -- recognize JAR here !!! argStack.push(arg); } LAUNCH_TYPE_PREF.setValue(launchType); } println("LaunchType = " + launchType); this.launchType = launchType; // look for codeBase path arg = pop(argStack); // read perhaps meta-preferences and surely preferences from application data dir File applicationDir = PropertiesAndDirectories.thisApplicationDir(this); ParsedURL applicationDataPURL = new ParsedURL(applicationDir); prefsPURL = applicationDataPURL.getRelative("preferences/prefs.xml"); debugA("prefsPURL= " + prefsPURL); System.out.println("arg: " + arg); switch (launchType) { case STUDIES: case JNLP: // next arg *should* be code base if ((arg != null) && arg.endsWith("/")) { // JNLP only! (as of now) // right now this only works for http:// ParsedURL codeBase = ParsedURL.getAbsolute(arg, "Setting up codebase"); this.setCodeBase(codeBase); // from supplied URL instead of from here try { debugA("Considering prefSet=" + prefSet + "\tprefsPURL=" + prefsPURL); if (prefSet == null) // Normal Case { prefSet = PrefSet.load(prefsPURL, translationScope); if (prefSet != null) println("OK: Loaded Prefs from " + prefsPURL); else println("No Prefs to load from " + prefsPURL); } } catch (SIMPLTranslationException e) { // meta prefs o.k. we can continue warning("Couldn't load Prefs:"); e.printTraceOrMessage(this, "Prefs", prefsPURL); println("\tContinuing."); } debugA("argStack.size() = " + argStack.size()); if (argStack.size() > 0) { String prefSpec = ""; if (arg.startsWith("http://")) { // PreferencesServlet prefSpec = pop(argStack); if (prefSpec != null) { // load URLEncoded prefs XML straight from the argument PrefSet JNLPPrefSet = loadPrefsFromJNLP(prefSpec); if (JNLPPrefSet != null) { if (prefSet == null) prefSet = JNLPPrefSet; else prefSet.append(JNLPPrefSet); } else { // if we got args straight from jnlp, then continue if (JNLPPrefSet != null) prefSpec = pop(argStack); if (prefSpec != null) { PrefSet servletPrefSet = requestPrefFromServlet(prefSpec, translationScope); if (servletPrefSet == null) error("incorrect prefXML string returned from the servlet=" + prefSpec); else { if (prefSet == null) prefSet = servletPrefSet; else prefSet.append(servletPrefSet); } } } } } } } else { error("No code base argument :-( Can't load preferences."); } break; case ECLIPSE: case JAR: // NB: This gets executed even if arg was null! File localCodeBasePath = deriveLocalFileCodeBase(baseClass); // sets codeBase()! argStack.push(arg); // load the application dir prefs from this machine // (e.g., c:\Documents and Settings\andruid\Application // Data\combinFormation\preferences\prefs.xml // these are the ones that get edited interactively! prefSet = PrefSet.load(prefsPURL, translationScope); if (prefSet != null) println("Loaded Prefs from: " + prefsPURL); else println("No Prefs to load from: " + prefsPURL); // now seek the path to an application specific xml preferences file arg = pop(argStack); // if (arg == null) // return; if (arg != null) { // load preferences specific to this invocation if (arg.endsWith(".xml")) { File argPrefsFile = new File(localCodeBasePath, ECLIPSE_PREFS_DIR + arg); ParsedURL argPrefsPURL = new ParsedURL(argPrefsFile); try { PrefSet argPrefSet = PrefSet.load(argPrefsPURL, translationScope); if (argPrefSet != null) { println("OK: Loaded Prefs from: " + argPrefsFile); if (prefSet != null) prefSet.addPrefSet(argPrefSet); else prefSet = argPrefSet; } else { println(""); String doesntExist = argPrefsFile.exists() ? "" : "\n\tFile does not exist!!!\n\n"; println("ERROR: Loading Prefs from: " + argPrefsFile + doesntExist); } } catch (SIMPLTranslationException e) { // meta prefs o.k. we can continue without having loaded Prefs now e.printTraceOrMessage(this, "Couldn't load Prefs", argPrefsPURL); println("\tContinuing."); } } else argStack.push(arg); } else argStack.push(arg); // let the next code handle returning. break; } System.out.println("Printing Prefs:\n"); try { if (prefSet != null) SimplTypesScope.serialize(prefSet, System.out, StringFormat.XML); } catch (SIMPLTranslationException e) { e.printStackTrace(); } System.out.println("\nPrefs Printed"); if (prefSet != null) postProcessPrefs(prefSet); } /** * Look for pref Ops, if delayed: setup their timers, and also set scope for their ops. * * @param prefSet */ private void postProcessPrefs(PrefSet prefSet) { if (sessionScope == null) return; for (Pref<?> pref : prefSet.values()) if (pref != null) pref.postLoadHook(sessionScope); } private PrefSet loadPrefsFromJNLP(String prefSpec) { PrefSet prefSet = null; debugA("loadPrefsFromJNLP()"); if (prefSpec.startsWith("%3Cpref_set")) { try { String decodedPrefsXML = URLDecoder.decode(prefSpec, "UTF-8"); debugA("Loading prefs from JNLP: " + decodedPrefsXML); // debugA("TranslationScope: \n"); // for (ClassDescriptor c : translationScope.getClassDescriptors()) // { // debugA(c.toString()); // } prefSet = PrefSet.loadFromCharSequence(decodedPrefsXML, translationScope); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (SIMPLTranslationException e) { e.printStackTrace(); } } return prefSet; } /** * Get the user.dir property. Form a path from it, ending in slash. See if there is path within * that that includes the package of baseClass. If so, remove that component from the path. * * Form a File from this path, and a ParsedURL from the file. Set codeBase to this ParsedURL. * * @param baseClass * Class of the subclass of this that is the main program that was executed. * * @return File that corresponds to the path of the local codeBase. */ protected File deriveLocalFileCodeBase(Class<?> baseClass) { // setup codeBase if (baseClass == null) baseClass = this.getClass(); Package basePackage = baseClass.getPackage(); String packageName = basePackage.getName(); String packageNameAsPath = packageName.replace('.', Files.sep); String pathName = System.getProperty("user.dir") + Files.sep; File path = new File(pathName); String pathString = path.getAbsolutePath(); int packageIndex = pathString.lastIndexOf(packageNameAsPath); if (packageIndex != -1) { pathString = pathString.substring(0, packageIndex); path = new File(pathString + Files.sep); } codeBase = new ParsedURL(path); println("codeBase=" + codeBase); return path; } /** * @see ecologylab.appframework.Environment#runtimeEnv() */ @Override public int runtimeEnv() { return APPLICATION; } /** * @see ecologylab.appframework.Environment#status(String) */ public void showStatus(String s) { System.out.println(s); } /** * @see ecologylab.appframework.Environment#status(String) */ @Override public void status(String msg) { if (msg != null) showStatus(msg); } /** * @see ecologylab.appframework.Environment#codeBase() return the path to root of the */ @Override public ParsedURL codeBase() { return codeBase; } /** * @see ecologylab.appframework.Environment#docBase() return the current working directory of the * application which is "c:\web\code\java\cm" */ @Override public ParsedURL docBase() { ParsedURL purl = new ParsedURL(new File(System.getProperty("user.dir"))); return purl; } public ParsedURL preferencesDir() { ParsedURL codeBase = codeBase(); ParsedURL purl = codeBase.getRelative(ECLIPSE_PREFS_DIR, "forming preferences dir"); return purl; } /** * Set the codebase for the application. Should only be done at startup. */ public void setCodeBase(ParsedURL codeBase) { this.codeBase = codeBase; } protected static <T> T pop(Stack<T> stack) { return stack.isEmpty() ? null : stack.pop(); } /** * Translation space used to parse Preferences for this Application. * * @return TranslationSpace in use for parsing Preferences */ public SimplTypesScope translationScope() { return translationScope; } public DownloadProcessor assetsDownloadProcessor() { return new SimpleDownloadProcessor(); } /** * Remove the Pref from the PrefSet associated with this, and from the global set. * * @param key * @return */ public void clearPref(String key) { if (prefSet != null) prefSet.clearPref(key); } /** * * @return The set of <code>Pref</code>s associated with this application. */ protected PrefSet prefSet() { return prefSet; } /** * Adds otherPrefs to this.prefSet, replacing any entries with the same name. * * @param otherPrefs */ protected void augmentPrefSet(PrefSet otherPrefs) { if (prefSet == null) { synchronized (this) { if (prefSet == null) this.prefSet = new PrefSet(); } } synchronized (prefSet) { for (String k : otherPrefs.keySet()) { this.prefSet.put(k, otherPrefs.get(k)); } } } /** * TODO Not sure how we can handle this in a non-static way; for now, this version does nothing. * * @see ecologylab.appframework.Environment#exit(int) */ @Override public void exit(int code) { } /** * XXX not implemented * * @see ecologylab.appframework.Environment#navigate(ecologylab.net.ParsedURL, java.lang.String) */ @Override public void navigate(ParsedURL purl, String frame) { } /** * XXX not implemented * * @see ecologylab.appframework.Environment#browser() */ @Override public int browser() { return 0; } public boolean isRunningInEclipse() { return LaunchType.ECLIPSE == this.launchType; } public boolean isRunningLocalhost() { return LaunchType.LOCAL_JNLP == this.launchType; } @Override public String getApplicationName() { return applicationName; } @Override public boolean hasFirefox() { // TODO Auto-generated method stub return false; } }