/* * @see flash.tools.debugger.SessionManager#launch(java.lang.String, flash.tools.debugger.AIRLaunchInfo, boolean, flash.tools.debugger.IProgress) */ public Session launch( String uri, AIRLaunchInfo airLaunchInfo, boolean forDebugging, IProgress waitReporter) throws IOException { boolean modify = (getPreference(PREF_URI_MODIFICATION) != 0); LaunchInfo launchInfo = new LaunchInfo(uri); boolean nativeLaunch = launchInfo.isWebBrowserNativeLaunch() || launchInfo.isPlayerNativeLaunch(); // one of these is assigned to launchAction final int NO_ACTION = 0; // no special action final int SHOULD_LISTEN = 1; // create a ProcessListener final int WAIT_FOR_LAUNCH = 2; // block until process completes int launchAction; // either NO_ACTION, SHOULD_LISTEN, or WAIT_FOR_LAUNCH uri = uri.trim(); String osName = System.getProperty("os.name").toLowerCase(); // $NON-NLS-1$ boolean isMacOSX = osName.startsWith("mac os x"); // $NON-NLS-1$ boolean isWindows = osName.startsWith("windows"); // $NON-NLS-1$ // if isMacOSX and isWindows are both false, then it's *NIX if (airLaunchInfo == null) { // first let's see if it's an HTTP URL or not if (launchInfo.isHttpOrAbout()) { if (modify && forDebugging && !uri.startsWith("about:")) // $NON-NLS-1$ { // escape spaces if we have any uri = URLHelper.escapeSpace(uri); // be sure that ?debug=true is included in query string URLHelper urlHelper = new URLHelper(uri); Map params = urlHelper.getParameterMap(); params.put("debug", "true"); // $NON-NLS-1$ //$NON-NLS-2$ urlHelper.setParameterMap(params); uri = urlHelper.getURL(); } } else { // ok, its not an http: type request therefore we should be able to see // it on the file system, right? If not then it's probably not valid File f = null; if (uri.startsWith("file:")) // $NON-NLS-1$ { try { f = new File(new URI(uri)); } catch (URISyntaxException e) { IOException ioe = new IOException(e.getMessage()); ioe.initCause(e); throw ioe; } } else { f = new File(uri); } if (f != null && f.exists()) uri = f.getCanonicalPath(); else throw new FileNotFoundException(uri); } if (nativeLaunch) { // We used to have // // launchAction = SHOULD_LISTEN; // // However, it turns out that when you launch Firefox, if there // is another instance of Firefox already running, then the // new instance just passes a message to the old one and then // immediately exits. So, it doesn't work to abort when our // child process dies. launchAction = NO_ACTION; } else { launchAction = NO_ACTION; } /** * Various ways to launch this stupid thing. If we have the exe values for the player, then we * can launch it directly, monitor it and kill it when we die; otherwise we launch it through * a command shell (cmd.exe, open, or bash) and our Process object dies right away since it * spawned another process to run the Player within. */ if (isMacOSX) { if (launchInfo.isWebBrowserNativeLaunch()) { File httpExe = m_debuggerCallbacks.getHttpExe(); m_launchCommand = new String[] { "/usr/bin/open", "-a", httpExe.toString(), uri }; //$NON-NLS-1$ //$NON-NLS-2$ } else if (launchInfo.isPlayerNativeLaunch()) { File playerExe = m_debuggerCallbacks.getPlayerExe(); m_launchCommand = new String[] { "/usr/bin/open", "-a", playerExe.toString(), uri }; //$NON-NLS-1$ //$NON-NLS-2$ } else { m_launchCommand = new String[] {"/usr/bin/open", uri}; // $NON-NLS-1$ } } else { if (launchInfo.isWebBrowserNativeLaunch()) { File httpExe = m_debuggerCallbacks.getHttpExe(); m_launchCommand = new String[] {httpExe.toString(), uri}; } else if (launchInfo.isPlayerNativeLaunch()) { File playerExe = m_debuggerCallbacks.getPlayerExe(); m_launchCommand = new String[] {playerExe.toString(), uri}; } else { if (isWindows) { // We must quote all ampersands in the URL; if we don't, then // cmd.exe will interpret the ampersand as a command separator. uri = uri.replaceAll("&", "\"&\""); // $NON-NLS-1$ //$NON-NLS-2$ m_launchCommand = new String[] {"cmd", "/c", "start", uri}; // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } else { String exeName; if (launchInfo.isWebPage()) exeName = m_debuggerCallbacks.getHttpExeName(); else exeName = m_debuggerCallbacks.getPlayerExeName(); throw new FileNotFoundException(exeName); } } } } else // else, AIR { if (forDebugging) launchAction = SHOULD_LISTEN; // wait inside accept() until ADL exits else launchAction = NO_ACTION; // just launch it List cmdList = new LinkedList(); cmdList.add(airLaunchInfo.airDebugLauncher.getPath()); if (airLaunchInfo.airRuntimeDir != null && airLaunchInfo.airRuntimeDir.length() > 0) { cmdList.add("-runtime"); // $NON-NLS-1$ cmdList.add(airLaunchInfo.airRuntimeDir.getPath()); } if (airLaunchInfo.airSecurityPolicy != null && airLaunchInfo.airSecurityPolicy.length() > 0) { cmdList.add("-security-policy"); // $NON-NLS-1$ cmdList.add(airLaunchInfo.airSecurityPolicy.getPath()); } if (airLaunchInfo.airPublisherID != null && airLaunchInfo.airPublisherID.length() > 0) { cmdList.add("-pubid"); // $NON-NLS-1$ cmdList.add(airLaunchInfo.airPublisherID); } // If it's a "file:" URL, then pass the actual filename; otherwise, use the URL // ok, its not an http: type request therefore we should be able to see // it on the file system, right? If not then it's probably not valid File f = null; if (uri.startsWith("file:")) // $NON-NLS-1$ { try { f = new File(new URI(uri)); cmdList.add(f.getPath()); } catch (URISyntaxException e) { IOException ioe = new IOException(e.getMessage()); ioe.initCause(e); throw ioe; } } else { cmdList.add(uri); } if (airLaunchInfo.applicationContentRootDir != null) { cmdList.add(airLaunchInfo.applicationContentRootDir.getAbsolutePath()); } if (airLaunchInfo.applicationArguments != null && airLaunchInfo.applicationArguments.length() > 0) { cmdList.add("--"); // $NON-NLS-1$ cmdList.addAll(splitArgs(airLaunchInfo.applicationArguments)); } m_launchCommand = (String[]) cmdList.toArray(new String[cmdList.size()]); } ProcessListener pl = null; PlayerSession session = null; try { // create the process and attach a thread to watch it during our accept phase Process proc = m_debuggerCallbacks.launchDebugTarget(m_launchCommand); m_processMessages = new StringWriter(); new StreamListener(new InputStreamReader(proc.getInputStream()), m_processMessages).start(); new StreamListener(new InputStreamReader(proc.getErrorStream()), m_processMessages).start(); try { OutputStream stm = proc.getOutputStream(); if (stm != null) stm.close(); } catch (IOException e) { /* not serious; ignore */ } switch (launchAction) { case NO_ACTION: break; case SHOULD_LISTEN: { // allows us to hear when the process dies pl = new ProcessListener(this, proc); pl.start(); break; } case WAIT_FOR_LAUNCH: { // block until the process completes boolean done = false; while (!done) { try { proc.waitFor(); done = true; } catch (InterruptedException e) { /* do nothing */ } } if (proc.exitValue() != 0) { throw new IOException(m_processMessages.toString()); } break; } } if (forDebugging) { /* now wait for a connection */ session = (PlayerSession) accept(waitReporter, airLaunchInfo != null); session.setProcess(proc); session.setLaunchUrl(uri); session.setAIRLaunchInfo(airLaunchInfo); } } finally { if (pl != null) pl.finish(); } return session; }