Mercurial > hg > release > icedtea-web-1.8
changeset 568:a1112e2c3bc6
Firefox session-backup and stubs for softkiller, multiple listeners,
processes handling moved to separate class.
line wrap: on
line diff
--- a/ChangeLog Wed Nov 21 14:55:44 2012 -0500 +++ b/ChangeLog Fri Nov 23 11:31:19 2012 +0100 @@ -1,3 +1,34 @@ +2012-11-23 Jiri Vanek <jvanek@redhat.com> + + Firefox session-backup and stubs for softkiller, multiple listeners, + processes handling moved to separate class. + * tests/reproducers/simple/AppletTest/testcases/AppletTestTests.java: + Removed unwanted assert on termination + * tests/test-extensions/net/sourceforge/jnlp/ContentReader.java: + Added support for multiple listeners. + * tests/test-extensions/net/sourceforge/jnlp/ProcessAssasin.java: + (destroyProcess()), non static wrapper around former (destroyProcess + (process)), introducing marks that process is being killed, added setter + for reactigProcess. + * tests/test-extensions/net/sourceforge/jnlp/ProcessWrapper.java: + Wrapper around former ServerAccess.executeProcess set of methods. + * tests/test-extensions/net/sourceforge/jnlp/ServerAccess.java: all + executeProcess/Javaws/Browser are now just api compatibility methods + around ProcessWrapper. + (executeProcess) main method moved to ProcessWrapper.execute. + * tests/test-extensions/net/sourceforge/jnlp/ThreadedProcess.java: + made public and synchronized with ProcessAssasin's (destroyProcess) + * tests/test-extensions/net/sourceforge/jnlp/browsertesting/Browser.java + is now implementing ReactingProcess + * tests/test-extensions/net/sourceforge/jnlp/browsertesting/ReactingProcess.java: + new interface for communication with main events of ThreadedProcess lifecycle. + * tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Firefox.java: + is containing singleton of FirefoxProfilesOperator (FPO) and is responding to + (beforeProcess) by FPO's (backupingProfiles), to (beforeKill) by calling + ProcessAssasin's (closeWindows), and to (afterKill) by FPO's (restoreProfiles) + * tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/firefox/FirefoxProfilesOperator.java: + New class to backup and restore firefox profiles. + 2012-11-21 Adam Domurad <adomurad@redhat.com> * Makefile.am: Fix new clean targets not cleaning properly
--- a/tests/reproducers/simple/AppletTest/testcases/AppletTestTests.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/reproducers/simple/AppletTest/testcases/AppletTestTests.java Fri Nov 23 11:31:19 2012 +0100 @@ -131,7 +131,7 @@ try { ProcessResult pr = server.executeBrowser("/appletAutoTests2.html", new CountingClosingListenerImpl(), new CountingClosingListenerImpl()); evaluateApplet(pr, false); - Assert.assertTrue(pr.wasTerminated); + //Assert.assertTrue(pr.wasTerminated); this checks asre evil //Assert.assertEquals((Integer) 0, pr.returnValue); due to destroy is null } finally { ServerAccess.PROCESS_TIMEOUT = 20 * 1000; //back to normal
--- a/tests/test-extensions/net/sourceforge/jnlp/ContentReader.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/ContentReader.java Fri Nov 23 11:31:19 2012 +0100 @@ -34,23 +34,25 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package net.sourceforge.jnlp; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.ArrayList; +import java.util.List; /** - * Class to read content of stdout/stderr of process, and to cooperate with its running/terminated/finished statuses. + * Class to read content of stdout/stderr of process, and to cooperate with its + * running/terminated/finished statuses. */ class ContentReader implements Runnable { StringBuilder sb = new StringBuilder(); private final InputStream is; private boolean done; - ContentReaderListener listener; + final List<ContentReaderListener> listeners = new ArrayList(1); public String getContent() { return sb.toString(); @@ -62,15 +64,24 @@ public ContentReader(InputStream is, ContentReaderListener l) throws IOException { this.is = is; - this.listener = l; + if (l != null) { + this.listeners.add(l); + } } - public void setListener(ContentReaderListener listener) { - this.listener = listener; + public ContentReader(InputStream is, List<ContentReaderListener> l) throws IOException { + this.is = is; + if (l != null) { + this.listeners.addAll(l); + } } - public ContentReaderListener getListener() { - return listener; + public void addListener(ContentReaderListener listener) { + this.listeners.add(listener); + } + + public List<ContentReaderListener> getListener() { + return listeners; } /** @@ -96,8 +107,12 @@ while (true) { int s = br.read(); if (s < 0) { - if (line.length() > 0 && listener != null) { - listener.lineReaded(line.toString()); + if (line.length() > 0 && listeners != null) { + for (ContentReaderListener listener : listeners) { + if (listener != null) { + listener.lineReaded(line.toString()); + } + } } break; } @@ -105,21 +120,31 @@ sb.append(ch); line.append(ch); if (ch == '\n') { - if (listener != null) { - listener.lineReaded(line.toString()); + if (listeners != null) { + for (ContentReaderListener listener : listeners) { + if (listener != null) { + listener.lineReaded(line.toString()); + } + } } line = new StringBuilder(); } - if (listener != null) { - listener.charReaded(ch); + if (listeners != null) { + for (ContentReaderListener listener : listeners) { + if (listener != null) { + listener.charReaded(ch); + } + } } } - //do not want to bother output with terminations - //mostly compaling when assassin kill the process about StreamClosed - //do not want to bother output with terminations - //mostly compaling when assassin kill the process about StreamClosed - } catch (Exception ex) { + } catch (NullPointerException ex) { + ex.printStackTrace(); + } + //do not want to bother output with terminations + //mostly compaling when assassin kill the process about StreamClosed + catch (Exception ex) { // logException(ex); + //ex.printStackTrace(); } finally { try { is.close();
--- a/tests/test-extensions/net/sourceforge/jnlp/ProcessAssasin.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/ProcessAssasin.java Fri Nov 23 11:31:19 2012 +0100 @@ -39,24 +39,32 @@ import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import net.sourceforge.jnlp.browsertesting.ReactingProcess; /** - * class which timeout any ThreadedProcess. This killing of 'thread with process' replaced not working process.destroy(). + * class which timeout any ThreadedProcess. This killing of 'thread with + * process' replaced not working process.destroy(). */ -class ProcessAssasin extends Thread { +public class ProcessAssasin extends Thread { long timeout; private final ThreadedProcess p; //false == is disabled:( private boolean canRun = true; private boolean wasTerminated = false; + //signifies that assasin have been summoned + private volatile boolean killing = false; + //signifies that assasin have done its job + private volatile boolean killed = false; /** - * if this is true, then process is not destroyed after timeout, but just left to its own destiny. - * Its stdout/err is no longer recorded, and it is leaking system resources until it dies by itself - * The contorl is returned to main thread with all informations recorded untill now. - * You will be able to listen to std out from listeners still + * if this is true, then process is not destroyed after timeout, but just + * left to its own destiny. Its stdout/err is no longer recorded, and it is + * leaking system resources until it dies by itself The contorl is returned + * to main thread with all informations recorded untill now. You will be + * able to listen to std out from listeners still */ private boolean skipInstedOfDesroy = false; + private ReactingProcess reactingProcess; public ProcessAssasin(ThreadedProcess p, long timeout) { this.p = (p); @@ -123,7 +131,7 @@ if (p.getP() != null) { try { if (!skipInstedOfDesroy) { - destroyProcess(p); + destroyProcess(); } } catch (Throwable ex) { if (p.deadlyException == null) { @@ -165,12 +173,34 @@ } } - public static void destroyProcess(ThreadedProcess pp) { + public void destroyProcess() { + try { + killing = true; + destroyProcess(p, reactingProcess); + } finally { + killed = true; + } + } + + public boolean haveKilled() { + return killed; + } + + public boolean isKilling() { + return killing; + } + + + + public static void destroyProcess(ThreadedProcess pp, ReactingProcess reactingProcess) { Process p = pp.getP(); try { Field f = p.getClass().getDeclaredField("pid"); f.setAccessible(true); String pid = (f.get(p)).toString(); + if (reactingProcess != null) { + reactingProcess.beforeKill(pid); + }; sigInt(pid); //sigTerm(pid); //sigKill(pid); @@ -178,6 +208,9 @@ ServerAccess.logException(ex); } finally { p.destroy(); + if (reactingProcess != null) { + reactingProcess.afterKill(""); + }; } } @@ -193,7 +226,7 @@ kill(pid, "SIGTERM"); } - public static void kill(String pid,String signal) throws InterruptedException, Exception { + public static void kill(String pid, String signal) throws InterruptedException, Exception { List<String> ll = new ArrayList<String>(4); ll.add("kill"); ll.add("-s"); @@ -203,4 +236,31 @@ //before affected application close Thread.sleep(1000); } + + void setReactingProcess(ReactingProcess reactingProcess) { + this.reactingProcess = reactingProcess; + } + + public static void closeWindow(String pid) throws Exception { + List<String> ll = new ArrayList<String>(2); + ll.add(ServerAccess.getInstance().getDir().getParent() + "/softkiller"); + ll.add(pid); + ServerAccess.executeProcess(ll); //sync, but acctually release + //before affected application "close" + Thread.sleep(100); + + } + + public static void closeWindows(String s) throws Exception { + closeWindows(s, 10); + } + + public static void closeWindows(String s, int count) throws Exception { + //each close closes just one tab... + for (int i = 0; i < count; i++) { + ProcessAssasin.closeWindow(s); + } + } + + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-extensions/net/sourceforge/jnlp/ProcessWrapper.java Fri Nov 23 11:31:19 2012 +0100 @@ -0,0 +1,235 @@ +/* ProcessWrapper.java +Copyright (C) 2011,2012 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea 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, version 2. + +IcedTea 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. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +package net.sourceforge.jnlp; + +import java.io.File; +import java.io.OutputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import net.sourceforge.jnlp.browsertesting.ReactingProcess; +import org.junit.Assert; + + + +/** + * This class wraps execution of ThreadedProcess. + * Add listeners and allows another setters, eg of ReactingProcess + * + */ +public class ProcessWrapper { + + private List<String> args; + private File dir; + private final List<ContentReaderListener> stdoutl = new ArrayList(1); + private final List<ContentReaderListener> stderrl = new ArrayList(1); + private String[] vars; + private ReactingProcess reactingProcess; + + public ProcessWrapper() { + } + + public ProcessWrapper(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars) throws Exception { + Assert.assertNotNull(u); + Assert.assertNotNull(toBeExecuted); + Assert.assertTrue(toBeExecuted.trim().length() > 1); + if (otherargs == null) { + otherargs = new ArrayList(1); + } + List<String> urledArgs = new ArrayList(otherargs); + urledArgs.add(0, toBeExecuted); + urledArgs.add(u.toString()); + this.args = urledArgs; + this.addStdOutListener(stdoutl); + this.addStdErrListener(stderrl); + this.vars=vars; + + } + + ProcessWrapper(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars) { + this.args = args; + this.dir = dir; + this.addStdOutListener(stdoutl); + this.addStdErrListener(stderrl); + this.vars = vars; + } + + public final void addStdOutListener(ContentReaderListener l) { + if (l == null) { + return; + } + stdoutl.add(l); + + } + + public final void addStdErrListener(ContentReaderListener l) { + if (l == null) { + return; + } + stderrl.add(l); + + } + + /** + * @return the args + */ + public List<String> getArgs() { + return args; + } + + /** + * @param args the args to set + */ + public void setArgs(List<String> args) { + this.args = args; + } + + /** + * @return the dir + */ + public File getDir() { + return dir; + } + + /** + * @param dir the dir to set + */ + public void setDir(File dir) { + this.dir = dir; + } + + /** + * @return the stdoutl + */ + public List<ContentReaderListener> getStdoutListeners() { + return stdoutl; + } + + /** + * @return the stderrl + */ + public List<ContentReaderListener> getStderrListeners() { + return stderrl; + } + + /** + * @return the vars + */ + public String[] getVars() { + return vars; + } + + /** + * @param vars the vars to set + */ + public void setVars(String[] vars) { + this.vars = vars; + } + + public ServerAccess.ProcessResult execute() throws Exception { + if (reactingProcess !=null ){ + reactingProcess.beforeProcess(""); + }; + ThreadedProcess t = new ThreadedProcess(args, dir, vars); + if (ServerAccess.PROCESS_LOG) { + String connectionMesaage = createConnectionMessage(t); + ServerAccess.log(connectionMesaage, true, true); + } + ProcessAssasin pa = new ProcessAssasin(t, ServerAccess.PROCESS_TIMEOUT); + t.setAssasin(pa); + pa.setReactingProcess(reactingProcess); + setUpClosingListener(stdoutl, pa, t); + setUpClosingListener(stderrl, pa, t); + pa.start(); + t.start(); + while (t.getP() == null && t.deadlyException == null) { + Thread.sleep(100); + } + if (t.deadlyException != null) { + pa.setCanRun(false); + return new ServerAccess.ProcessResult("", "", null, true, Integer.MIN_VALUE, t.deadlyException); + } + ContentReader crs = new ContentReader(t.getP().getInputStream(), stdoutl); + ContentReader cre = new ContentReader(t.getP().getErrorStream(), stderrl); + + OutputStream out = t.getP().getOutputStream(); + if (out != null) { + out.close(); + } + + new Thread(crs).start(); + new Thread(cre).start(); + while (t.isRunning()) { + Thread.sleep(100); + } + + while (!t.isDestoyed()) { + Thread.sleep(100); + } + pa.setCanRun(false); + // ServerAccess.logOutputReprint(t.getP().exitValue()); when process is killed, this throws exception + + ServerAccess.ProcessResult pr = new ServerAccess.ProcessResult(crs.getContent(), cre.getContent(), t.getP(), pa.wasTerminated(), t.getExitCode(), null); + if (ServerAccess.PROCESS_LOG) { + ServerAccess.log(pr.stdout, true, false); + ServerAccess.log(pr.stderr, false, true); + } + if (reactingProcess != null) { + reactingProcess.afterProcess(""); + }; + return pr; + } + + private static void setUpClosingListener(List<ContentReaderListener> listeners, ProcessAssasin pa, ThreadedProcess t) { + for (ContentReaderListener listener : listeners) { + if (listener != null && (listener instanceof ClosingListener)) { + ((ClosingListener) listener).setAssasin(pa); + ((ClosingListener) listener).setProcess(t); + } + } + + } + + private static String createConnectionMessage(ThreadedProcess t) { + return "Connecting " + t.getCommandLine(); + } + + void setReactingProcess(ReactingProcess reactingProcess) { + this.reactingProcess = reactingProcess; + } +}
--- a/tests/test-extensions/net/sourceforge/jnlp/ServerAccess.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/ServerAccess.java Fri Nov 23 11:31:19 2012 +0100 @@ -592,17 +592,27 @@ } public ProcessResult executeBrowser(List<String> otherargs, String resource) throws Exception { - return executeProcessUponURL(getBrowserLocation(), otherargs, getUrlUponThisInstance(resource)); + ProcessWrapper rpw = new ProcessWrapper(getBrowserLocation(), otherargs, getUrlUponThisInstance(resource), null, null, null); + rpw.setReactingProcess(getCurrentBrowser());//current browser may be null, but it does not metter + return rpw.execute(); } - public ProcessResult executeBrowser(List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { - return executeProcessUponURL(getBrowserLocation(), otherargs, getUrlUponThisInstance(resource),stdoutl,stderrl); + + public ProcessResult executeBrowser(List<String> otherargs, String resource, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { + ProcessWrapper rpw = new ProcessWrapper(getBrowserLocation(), otherargs, getUrlUponThisInstance(resource), stdoutl, stderrl, null); + rpw.setReactingProcess(getCurrentBrowser());//current browser may be null, but it does not metter + return rpw.execute(); } - public ProcessResult executeBrowser(Browser b,List<String> otherargs, String resource) throws Exception { - return executeProcessUponURL(b.getBin(), otherargs, getUrlUponThisInstance(resource)); + public ProcessResult executeBrowser(Browser b, List<String> otherargs, String resource) throws Exception { + ProcessWrapper rpw = new ProcessWrapper(b.getBin(), otherargs, getUrlUponThisInstance(resource), null, null, null); + rpw.setReactingProcess(b); + return rpw.execute(); } - public ProcessResult executeBrowser(Browser b,List<String> otherargs, String resource,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { - return executeProcessUponURL(b.getBin(), otherargs, getUrlUponThisInstance(resource),stdoutl,stderrl); + + public ProcessResult executeBrowser(Browser b, List<String> otherargs, String resource, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { + ProcessWrapper rpw = new ProcessWrapper(b.getBin(), otherargs, getUrlUponThisInstance(resource), stdoutl, stderrl, null); + rpw.setReactingProcess(b); + return rpw.execute(); } /** @@ -651,23 +661,15 @@ * @throws Exception */ public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u) throws Exception { - return executeProcessUponURL(toBeExecuted, otherargs, u,null,null); + return new ProcessWrapper(toBeExecuted, otherargs, u, null, null, null).execute(); } - public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u,ContentReaderListener stdoutl,ContentReaderListener stderrl) throws Exception { - return executeProcessUponURL(toBeExecuted, otherargs, u, stdoutl, stderrl, null); + public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl) throws Exception { + return new ProcessWrapper(toBeExecuted, otherargs, u, stdoutl, stderrl, null).execute(); } - public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u,ContentReaderListener stdoutl,ContentReaderListener stderrl,String[] vars) throws Exception { - Assert.assertNotNull(u); - Assert.assertNotNull(toBeExecuted); - Assert.assertTrue(toBeExecuted.trim().length() > 1); - if (otherargs == null) { - otherargs = new ArrayList<String>(1); - } - List<String> urledArgs = new ArrayList<String>(otherargs); - urledArgs.add(0, toBeExecuted); - urledArgs.add(u.toString()); - return executeProcess(urledArgs, stdoutl, stderrl,vars); + + public static ProcessResult executeProcessUponURL(String toBeExecuted, List<String> otherargs, URL u, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars) throws Exception { + return new ProcessWrapper(toBeExecuted, otherargs, u, stdoutl, stderrl, vars).execute(); } public static ProcessResult executeProcess(final List<String> args) throws Exception { @@ -699,10 +701,6 @@ return executeProcess(args, dir, null, null); } - private static String createConnectionMessage(ThreadedProcess t) { - return "Connecting " + t.getCommandLine(); - } - /** * Proceed message s to logging with request to reprint to System.err * @param s @@ -727,7 +725,7 @@ log(s, false, false); } - private static void log(String message, boolean printToOut, boolean printToErr) { + static void log(String message, boolean printToOut, boolean printToErr) { String idded; StackTraceElement ste = getTestMethod(); String fullId = ste.getClassName() + "." + ste.getMethodName(); @@ -772,26 +770,30 @@ private static StackTraceElement getTestMethod(StackTraceElement[] stack) { //0 is always thread - //1 is net.sourceforge.jnlp.ServerAccess + //1 is net.sourceforge.jnlp.* + //we need to get out of all of classes from this package or pick last of it StackTraceElement result = stack[1]; String baseClass = stack[1].getClassName(); int i = 2; for (; i < stack.length; i++) { result = stack[i];//at least moving up - if(stack[i].getClassName().contains("$")){ + if (stack[i].getClassName().contains("$")) { continue; } - if (!baseClass.equals(stack[i].getClassName())) { + //probablky it is necessary to get out of net.sourceforge.jnlp. + //package where are right now all test-extensions + //for now keeping exactly the three clases helping yo acces the log + if (!stack[i].getClassName().startsWith("net.sourceforge.jnlp.")) { break; } } //if nothing left in stack then we have been in ServerAccess already //so the target method is the highest form it and better to return it //rather then die to ArrayOutOfBounds - if(i >= stack.length){ + if (i >= stack.length) { return result; } - //now we are out of net.sourceforge.jnlp.ServerAccess + //now we are out of net.sourceforge.jnlp.* //method we need (the test) is highest from following class baseClass = stack[i].getClassName(); for (; i < stack.length; i++) { @@ -811,57 +813,8 @@ return executeProcess(args, dir, stdoutl, stderrl,null); } - public static ProcessResult executeProcess(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl,String[] vars) throws Exception { - ThreadedProcess t = new ThreadedProcess(args, dir,vars); - if (PROCESS_LOG) { - String connectionMesaage = createConnectionMessage(t); - log(connectionMesaage, true, true); - } - ProcessAssasin pa = new ProcessAssasin(t, PROCESS_TIMEOUT); - setUpClosingListener(stdoutl, pa, t); - setUpClosingListener(stderrl, pa, t); - pa.start(); - t.start(); - while (t.getP() == null && t.deadlyException == null) { - Thread.sleep(100); - } - if (t.deadlyException != null) { - pa.setCanRun(false); - return new ProcessResult("", "", null, true, Integer.MIN_VALUE, t.deadlyException); - } - ContentReader crs = new ContentReader(t.getP().getInputStream(),stdoutl); - ContentReader cre = new ContentReader(t.getP().getErrorStream(),stderrl); - - OutputStream out = t.getP().getOutputStream(); - if (out != null) { - out.close(); - } - - new Thread(crs).start(); - new Thread(cre).start(); - while (t.isRunning()) { - Thread.sleep(100); - } - - while (!t.isDestoyed()) { - Thread.sleep(100); - } - pa.setCanRun(false); - // ServerAccess.logOutputReprint(t.getP().exitValue()); when process is killed, this throws exception - - ProcessResult pr=new ProcessResult(crs.getContent(), cre.getContent(), t.getP(), pa.wasTerminated(), t.getExitCode(), null); - if (PROCESS_LOG) { - log(pr.stdout, true, false); - log(pr.stderr, false, true); - } - return pr; - } - - private static void setUpClosingListener(ContentReaderListener listener, ProcessAssasin pa, ThreadedProcess t) { - if (listener != null && (listener instanceof ClosingListener)) { - ((ClosingListener) listener).setAssasin(pa); - ((ClosingListener) listener).setProcess(t); - } + public static ProcessResult executeProcess(final List<String> args, File dir, ContentReaderListener stdoutl, ContentReaderListener stderrl, String[] vars) throws Exception { + return new ProcessWrapper(args, dir, stdoutl, stderrl, vars).execute(); } /**
--- a/tests/test-extensions/net/sourceforge/jnlp/ThreadedProcess.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/ThreadedProcess.java Fri Nov 23 11:31:19 2012 +0100 @@ -45,7 +45,7 @@ * wrapper around Runtime.getRuntime().exec(...) which ensures that process is run inside its own, by us controlled, thread. * Process builder caused some unexpected and weird behavior :/ */ -class ThreadedProcess extends Thread { +public class ThreadedProcess extends Thread { Process p = null; List<String> args; @@ -59,6 +59,7 @@ * check DeadLockTestTest.testDeadLockTestTerminated2 */ private boolean destoyed = false; + private ProcessAssasin assasin; public boolean isDestoyed() { return destoyed; @@ -143,6 +144,9 @@ try { exitCode = p.waitFor(); Thread.sleep(500); //this is giving to fast done proecesses's e/o readers time to read all. I would like to know better solution :-/ + while(assasin.isKilling() && !assasin.haveKilled()){ + Thread.sleep(100); + }; } finally { destoyed = true; } @@ -163,4 +167,8 @@ running = false; } } + + void setAssasin(ProcessAssasin pa) { + this.assasin=pa; + } }
--- a/tests/test-extensions/net/sourceforge/jnlp/browsertesting/Browser.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/Browser.java Fri Nov 23 11:31:19 2012 +0100 @@ -42,7 +42,7 @@ /** * interface which represents individual browsers */ -public interface Browser { +public interface Browser extends ReactingProcess{ public String getDefaultBin(); public String getDefaultPluginExpectedLocation(); public String getBin(); @@ -52,5 +52,4 @@ public List<String> getComaptibilitySwitches(); public List<String> getDefaultSwitches(); - }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/ReactingProcess.java Fri Nov 23 11:31:19 2012 +0100 @@ -0,0 +1,63 @@ +/* ReactingProcess.java +Copyright (C) 2012 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea 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, version 2. + +IcedTea 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. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +package net.sourceforge.jnlp.browsertesting; + + +/** + * interface which represents process which can react to events during its lifetime. + */ +public interface ReactingProcess { + /** + * called before process is launched + */ + public void beforeProcess(String s); + /** + * called after process is finished or killed + */ + public void afterProcess(String s); + /** + * called after before process is timeouted and is going to be killed + */ + public void beforeKill(String s); + /** + * called after process have been killed + */ + public void afterKill(String s); + + +}
--- a/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Epiphany.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Epiphany.java Fri Nov 23 11:31:19 2012 +0100 @@ -34,22 +34,27 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package net.sourceforge.jnlp.browsertesting.browsers; +import java.util.Arrays; +import java.util.List; import net.sourceforge.jnlp.browsertesting.Browsers; public class Epiphany extends MozillaFamilyLinuxBrowser { + String[] cs = {"-new-tab"}; + public Epiphany(String bin) { super(bin); } @Override + public List<String> getComaptibilitySwitches() { + return Arrays.asList(cs); + } + + @Override public Browsers getID() { return Browsers.epiphany; } - - - }
--- a/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Firefox.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Firefox.java Fri Nov 23 11:31:19 2012 +0100 @@ -34,20 +34,23 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ - package net.sourceforge.jnlp.browsertesting.browsers; import java.util.Arrays; import java.util.List; +import net.sourceforge.jnlp.ProcessAssasin; +import net.sourceforge.jnlp.ServerAccess; import net.sourceforge.jnlp.browsertesting.Browsers; +import net.sourceforge.jnlp.browsertesting.browsers.firefox.FirefoxProfilesOperator; public class Firefox extends MozillaFamilyLinuxBrowser { + private static final FirefoxProfilesOperator firefoxProfilesOperatorSingleton = new FirefoxProfilesOperator(); + public Firefox(String bin) { super(bin); } - - String[] cs={"-new-tab"}; + String[] cs = {"-new-tab"}; @Override public Browsers getID() { @@ -59,8 +62,35 @@ return Arrays.asList(cs); } + @Override + public void beforeProcess(String s) { + try { + firefoxProfilesOperatorSingleton.backupProfiles(); //assuming firefox is not in safemode already + } catch (Exception ex) { + throw new RuntimeException("Firefox profile backup failed", ex); + } + } - + @Override + public void afterProcess(String s) { + } - + @Override + public void beforeKill(String s) { + try { + //ProcessAssasin.closeWindows(s); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void afterKill(String s) { + try { + firefoxProfilesOperatorSingleton.restoreProfiles(); + } catch (Exception ex) { + throw new RuntimeException("Firefox profile restoration failed", ex); + } + + } }
--- a/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/LinuxBrowser.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/LinuxBrowser.java Fri Nov 23 11:31:19 2012 +0100 @@ -92,6 +92,25 @@ } } + @Override + public void beforeProcess(String s) { + + } + + @Override + public void afterProcess(String s) { + + } + + @Override + public void beforeKill(String s) { + + } + + @Override + public void afterKill(String s) { + + } }
--- a/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Midory.java Wed Nov 21 14:55:44 2012 -0500 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/Midory.java Fri Nov 23 11:31:19 2012 +0100 @@ -50,6 +50,6 @@ return Browsers.midori; } - + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-extensions/net/sourceforge/jnlp/browsertesting/browsers/firefox/FirefoxProfilesOperator.java Fri Nov 23 11:31:19 2012 +0100 @@ -0,0 +1,175 @@ +/* FirefoxProfilesOperator.java +Copyright (C) 2011,2012 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea 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, version 2. + +IcedTea 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. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + */ + +package net.sourceforge.jnlp.browsertesting.browsers.firefox; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.channels.FileChannel; +import net.sourceforge.jnlp.ServerAccess; + +/** + * This class is able to backup and restore firefox profiles. + * + */ +public class FirefoxProfilesOperator { + + private File backupDir; + private File sourceDir; + private boolean backuped = false; + private FilenameFilter firefoxProfilesFilter = new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".default") || name.equals("profiles.ini"); + } + }; + + + public void backupProfiles() throws IOException { + if (backuped) { + return; + } + sourceDir = new File(System.getProperty("user.home") + "/.mozilla/firefox/"); + File f = File.createTempFile("backupedFirefox_", "_profiles.default"); + f.delete(); + f.mkdir(); + backupDir = f; + String message = "Backuping firefox profiles from " + sourceDir.getAbsolutePath() + " to " + backupDir.getAbsolutePath(); + ServerAccess.logOutputReprint(message); + copyDirs(sourceDir, backupDir, firefoxProfilesFilter); + backuped = true; + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + try { + restoreProfiles(); + } catch (Exception ex) { + ServerAccess.logException(ex); + } + } + })); + + } + + public void restoreProfiles() throws IOException { + if (!backuped) { + return; + } + try { + removeProfiles(); + } catch (Exception ex) { + ServerAccess.logException(ex); + } + String message = ("Restoring all firefox profiles in " + sourceDir.getAbsolutePath() + " from in " + backupDir.getAbsolutePath()); + ServerAccess.logOutputReprint(message); + copyDirs(backupDir, sourceDir, firefoxProfilesFilter); + + } + + public void removeProfiles() throws IOException { + if (!backuped) { + return; + } + String message = ("Removing all firefox profiles from " + sourceDir.getAbsolutePath() + " backup avaiable in " + backupDir.getAbsolutePath()); + ServerAccess.logOutputReprint(message); + File[] oldProfiles = sourceDir.listFiles(firefoxProfilesFilter); + for (File file : oldProfiles) { + deleteRecursively(file); + + } + + } + + private void copyDirs(File sourceDir, File backupDir, FilenameFilter firefoxProfilesFilter) throws IOException { + File[] profiles = sourceDir.listFiles(firefoxProfilesFilter); + for (File file : profiles) { + copyRecursively(file, backupDir); + } + } + + private static void copyFile(File from, File to) throws IOException { + FileInputStream is = new FileInputStream(from); + FileOutputStream fos = new FileOutputStream(to); + FileChannel f = is.getChannel(); + FileChannel f2 = fos.getChannel(); + try { + f.transferTo(0, f.size(), f2); + } finally { + f2.close(); + f.close(); + } + } + + private static void deleteRecursively(File f) throws IOException { + if (f.isDirectory()) { + for (File c : f.listFiles()) { + deleteRecursively(c); + } + } + boolean d = true; + d = f.delete(); + if (!d) { + throw new IOException("Failed to delete file: " + f); + } + } + + private static void copyRecursively(File srcFileDir, File destDir) throws IOException { + if (srcFileDir.isDirectory()) { + File nwDest = new File(destDir, srcFileDir.getName()); + nwDest.mkdir(); + for (File c : srcFileDir.listFiles()) { + copyRecursively(c, nwDest); + } + } else { + copyFile(srcFileDir, new File(destDir, srcFileDir.getName())); + } + + } + + public static void main(String[] args) throws IOException { + FirefoxProfilesOperator ff = new FirefoxProfilesOperator(); + ff.restoreProfiles(); + ff.backupProfiles(); + ff.restoreProfiles(); + ff.backupProfiles(); + + } +}