/* * File : JClicApplet.java * Created : 01-feb-2001 13:39 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2008 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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 for more details (see the LICENSE file). */ import edu.xtec.jclic.Player; import edu.xtec.jclic.PlayerSettings; import edu.xtec.jclic.RunnableComponent; import edu.xtec.jclic.media.CheckMediaSystem; import edu.xtec.jclic.project.ProjectInstallerDlg; import edu.xtec.util.BasicResourceBridge; import edu.xtec.util.Check; import edu.xtec.util.LFUtil; import edu.xtec.util.Messages; import edu.xtec.util.Options; import edu.xtec.util.ResourceManager; import java.net.URL; import javax.swing.RootPaneContainer; /** * Default JClic applet. Shows a splash screen at startup and loads a {@link Player} * in a separate process. * * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.10.02 */ public class JClicApplet extends javax.swing.JApplet implements edu.xtec.jclic.Constants { private Options options; private RunnableComponent rc; private String activityPack, sequence; private boolean initiated; private boolean trace; private javax.swing.JLabel splashLabel; private boolean isInstaller; // useful constants private static final String HTTP = "http:", HTTPS = "https", FILE = "file:"; private static final String STRING = "string", BOOL = "boolean", URL = "url"; // parameters private static final String ACTIVITY_PACK = "activityPack"; private static final String SEQUENCE = "sequence"; private static final int NUM_PRIVATE_PARAMS = 2; private static final String[][] pInfo = { {ACTIVITY_PACK, STRING, "absolute or relative URL of the JClic project to load"}, {SEQUENCE, STRING, "optional project's starting sequence name"}, {Messages.LANGUAGE, STRING, "two-char language code"}, {Messages.COUNTRY, STRING, "two-char country code"}, {Messages.VARIANT, STRING, "locale variant code"}, {SKIN, STRING, "skin to be used"}, {COOKIE, STRING, "optional session cookie value. currently not used"}, {REPORTER_CLASS, STRING, "reporter class name"}, {REPORTER_PARAMS, STRING, "reporter parameters"}, {EXIT_URL, URL, "URL where to redirect navigation at end"}, {INFO_URL_FRAME, STRING, "optional frame where to display info documents. If unespecified, _BLANK will be used"}, {SYSTEM_SOUNDS, BOOL, "to play or not system sounds"}, {COMPRESS_IMAGES, BOOL, "to compress or not images in cells"}, {LFUtil.LOOK_AND_FEEL, STRING, "look & feel to use"}, {AUDIO_ENABLED, BOOL, "to have audio enabled or not"}, {MEDIA_SYSTEM, STRING, "preferred multimedia system: 'JMF' for Java Media Framework or 'QT' for QuickTime"}, {TRACE, BOOL, "show debug messages in console"}, {MYURL, STRING, "URL of the document containing the applet, used as a base for relative paths"} }; /** * Creates new JClicApplet */ public JClicApplet() { super(); trace = false; rc = null; initiated = false; activityPack = null; sequence = null; options = new Options(this); splashLabel = new javax.swing.JLabel(" ", ResourceManager.getImageIcon("icons/logo_applet.png"), javax.swing.SwingConstants.CENTER); splashLabel.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); splashLabel.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); splashLabel.setBackground(BG_COLOR); splashLabel.setOpaque(true); getContentPane().add(splashLabel, java.awt.BorderLayout.CENTER); } @Override public void init() { // init only once by applet instance if (initiated) { return; } initiated = true; // get "trace" flag trace = TRUE.equals(getParameter(TRACE)); final StringBuilder sb = new StringBuilder(); final RootPaneContainer rpc = this; /* if (getParameter(ACTIVITY_PACK)!=null && getParameter(ACTIVITY_PACK).endsWith(".jclic.inst")){ JClicInstaller.main(new String[]{getParameter(ACTIVITY_PACK)}); return; } * */ edu.xtec.util.SwingWorker sw = new edu.xtec.util.SwingWorker() { @Override public Object construct() { // get parameters for (int i = NUM_PRIVATE_PARAMS; i < pInfo.length; i++) { options.put(pInfo[i][0], getParameter(pInfo[i][0])); if (trace) { System.out.println(">>> param " + pInfo[i][0] + " is " + getParameter(pInfo[i][0])); } } Messages messages; try { messages = edu.xtec.util.PersistentSettings.getMessages(options, DEFAULT_BUNDLE); } catch (Exception ex) { System.err.println("Unable to get default user messages language!\n" + ex); messages = Messages.getMessages(options, DEFAULT_BUNDLE); } messages.addBundle(COMMON_SETTINGS); if (splashLabel != null) { splashLabel.setText(messages.get("LOADING")); } if (!Check.checkSignature(options, true)) { return null; } CheckMediaSystem.check(options, false); // process JClic project parameters activityPack = getParameter(ACTIVITY_PACK); sequence = getParameter(SEQUENCE); if (activityPack != null) { if (activityPack.indexOf("http://") < 0 && activityPack.indexOf("https://") < 0 && activityPack.indexOf(":") < 1 && activityPack.indexOf("\\\\") < 0) { /* Correction of Bug: Since Java 7.40, Applet.getDocumentBase() returns * null when called from a local filesystem. * Solved thanks to Duckware (http://www.duckware.com/tech/java-security-clusterfuck.html) * passing a parameter called "myurl" in the Applet invocation script. */ //String base = getDocumentBase().toString(); String base = ""; URL baseURL=getDocumentBase(); if(baseURL!=null) base=baseURL.toString(); else if(options.getString(MYURL)!=null) base=options.getString(MYURL); if (trace) { System.out.println(">>> original base is: " + base); } int i = base.indexOf("file:/"); if (i >= 0) { base = base.substring(i + 6); if (trace) { System.out.println(">>> protocol is 'file', so base is: " + base); } // Mozilla in Linux if (!options.getBoolean(Options.WIN) && !base.startsWith(java.io.File.pathSeparator)) { base = "/" + base; if (trace) { System.out.println(">>> non-Windows and not starts with '/', so base is: " + base); } } } // Opera if (base.startsWith("/localhost/")) { base = base.substring(11); } // Opera if (base.endsWith(".htm") || base.endsWith(".html")) { i = base.lastIndexOf('/'); if (i < 0) { i = base.lastIndexOf('\\'); } if (i > 0) { base = base.substring(0, i + 1); } } options.put(URL_BASE, base); if (trace) { System.out.println(">>> corrected base is: " + base); } activityPack = base + activityPack; if (trace) { System.out.println(">>> project path is: " + activityPack); } String s = options.getString(SKIN); if (s != null && !s.startsWith("@") && !s.startsWith(HTTP) && !s.startsWith(HTTPS) && !s.startsWith(FILE)) { options.put(SKIN, base + s); } s = options.getString(EXIT_URL); if (s != null && !s.startsWith(HTTP) && !s.startsWith(HTTPS) && !s.startsWith(FILE)) { options.put(EXIT_URL, base + s); } } // Check if activityPack is an installer if (activityPack.endsWith(".jclic.inst")) { isInstaller = true; messages.addBundle(edu.xtec.jclic.ExtendedPlayer.MESSAGES_BUNDLE); } } // build player try { if (isInstaller) { String installer = activityPack; activityPack = null; BasicResourceBridge rb = new BasicResourceBridge(options); PlayerSettings settings = PlayerSettings.loadPlayerSettings(rb); if (settings.promptPassword(null, null)) { settings.checkLibrary(); ProjectInstallerDlg pi = ProjectInstallerDlg.getProjectInstallerDlg(null, settings.libraryManager, installer); if (pi != null) { pi.setVisible(true); if (!pi.cancel && pi.launchNow && pi.pathToMainProject != null) { activityPack = pi.pathToMainProject; } } } } //Class c=Class.forName("edu.xtec.jclic.Player"); //java.lang.reflect.Constructor cons=c.getConstructor(new Class[]{edu.xtec.util.Options.class}); //rc=(RunnableComponent)cons.newInstance(new Object[]{options}); if (activityPack != null) { rc = new Player(options); } } catch (Exception ex) { sb.append("ERROR: ").append(ex); } return rc; } @Override public void finished() { if (getValue() == null) { if (isInstaller && options.getString(EXIT_URL) != null) { try { String url = options.getString(EXIT_URL); if (url.indexOf(':') < 0) // no protocol, assume "file://" { url = "file://" + url; } getAppletContext().showDocument(new URL(url)); } catch (Exception ex) { sb.append("ERROR: ").append(ex); } } // no player build! if (splashLabel != null) { String s = sb.substring(0); splashLabel.setText(s); System.err.println(s); } } else { // remove label and place player getContentPane().removeAll(); splashLabel = null; //rc.addTo(getContentPane(), java.awt.BorderLayout.CENTER); rc.addTo(rpc, java.awt.BorderLayout.CENTER); getRootPane().revalidate(); // load project javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { rc.start(activityPack, sequence); } }); } } }; if (trace) { System.out.println(">>> initializing..."); } // launch swingWorker sw.start(); } @Override public void start() { if (trace) { System.out.println(">>> applet started"); } } @Override public void stop() { if (rc != null) { rc.stop(); } if (trace) { System.out.println(">>> applet stopped"); } } @Override public void destroy() { if (rc != null) { if (trace) { System.out.println(">>> destroying applet..."); } getContentPane().removeAll(); rc.end(); rc = null; initiated = false; } if (trace) { System.out.println(">>> applet destroyed"); } } @Override public String getAppletInfo() { return "JClic applet"; } @Override public String[][] getParameterInfo() { return pInfo; } }