# HG changeset patch # User Jiri Vanek # Date 1452070418 -3600 # Node ID f48d4c62c2e3347f8b7af9b4da8194a2ee9c9f61 # Parent f589afe6e0080fb1f43ed3d946dc34d1a9d5ef36 Added redirection tests diff -r f589afe6e008 -r f48d4c62c2e3 ChangeLog --- a/ChangeLog Tue Jan 05 10:27:13 2016 +0100 +++ b/ChangeLog Wed Jan 06 09:53:38 2016 +0100 @@ -1,3 +1,16 @@ +2016-01-06 Jiri Vanek + + Added redirection tests + * tests/test-extensions/net/sourceforge/jnlp/ServerLauncher.java: Enhanced so + it can redirect requests to another instance. Enhanced to be able to count requests + * tests/test-extensions/net/sourceforge/jnlp/TinyHttpdImpl.java: same + * tests/reproducers/simple/simpletest1/testcases/SimpleTest1Test.java: small + refactoring to reuse checking methods + * tests/reproducers/simple/simpletest1/testcases/SimpleTest1CountRequests.java: + added set of tests to test behavior under various redirect codes + * tests/reproducers/simple/simpletest1/testcases/SimpleTestDefaultRedirects.java: + Added FAILING tests for 2591 - counting ITW requests to test server + 2016-01-05 Jiri Vanek * NEWS: mentioned PR2779 diff -r f589afe6e008 -r f48d4c62c2e3 tests/reproducers/simple/simpletest1/testcases/SimpleTest1CountRequests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/simpletest1/testcases/SimpleTest1CountRequests.java Wed Jan 06 09:53:38 2016 +0100 @@ -0,0 +1,109 @@ +/* SimpleTest1Test.java + Copyright (C) 2011 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. + */ + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.sourceforge.jnlp.ProcessResult; +import net.sourceforge.jnlp.ServerAccess; +import net.sourceforge.jnlp.ServerLauncher; +import net.sourceforge.jnlp.annotations.Bug; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; + +import org.junit.Test; + +@Bug(id = "PR2591") +public class SimpleTest1CountRequests { + + private static final ServerAccess server = new ServerAccess(); + private static ServerLauncher server0; + private static final Map> counter = new HashMap<>(); + private static final List hv = Arrays.asList(new String[]{ServerAccess.VERBOSE_OPTION, ServerAccess.HEADLES_OPTION}); + + @BeforeClass + public static void createCountingServer() { + server0 = ServerAccess.getIndependentInstance(); + server0.setRequestsCounter(counter); + } + + @AfterClass + public static void stopCountingServer() { + server0.stop(); + } + + @Bug(id = "PR2591") + @Test + public void testSimpletest1EachResourceOnePerRun() throws Exception { + server0.setSupportingHeadRequest(true); + counter.clear(); + ProcessResult pr = ServerAccess.executeProcessUponURL(server.getJavawsLocation(), + hv, + server0.getUrl("/simpletest1.jnlp"), + null, + null + ); + SimpleTest1Test.checkLaunched(pr); + Assert.assertTrue(counter.get("./simpletest1.jnlp").get("GET").equals(1)); //2 without bugfix + Assert.assertTrue(counter.get("./simpletest1.jnlp").get("HEAD").equals(1)); + Assert.assertTrue(counter.get("./simpletest1.jar").get("GET").equals(1));//2 without bugfix + Assert.assertTrue(counter.get("./simpletest1.jar").get("HEAD").equals(1)); + + } + + @Bug(id = "PR2591") + @Test + public void testSimpletest1EachResourceOnePerRunHeadsOff() throws Exception { + server0.setSupportingHeadRequest(false); + counter.clear(); + ProcessResult pr = ServerAccess.executeProcessUponURL(server.getJavawsLocation(), + hv, + server0.getUrl("/simpletest1.jnlp"), + null, + null + ); + SimpleTest1Test.checkLaunched(pr); + Assert.assertTrue(counter.get("./simpletest1.jnlp").get("GET").equals(2)); //3 without bugfix + Assert.assertTrue(counter.get("./simpletest1.jnlp").get("HEAD") == null); + Assert.assertTrue(counter.get("./simpletest1.jar").get("GET").equals(2));//3 without bugfix + Assert.assertTrue(counter.get("./simpletest1.jar").get("HEAD") == (null)); + + } + +} diff -r f589afe6e008 -r f48d4c62c2e3 tests/reproducers/simple/simpletest1/testcases/SimpleTest1Test.java --- a/tests/reproducers/simple/simpletest1/testcases/SimpleTest1Test.java Tue Jan 05 10:27:13 2016 +0100 +++ b/tests/reproducers/simple/simpletest1/testcases/SimpleTest1Test.java Wed Jan 06 09:53:38 2016 +0100 @@ -1,38 +1,38 @@ /* SimpleTest1Test.java -Copyright (C) 2011 Red Hat, Inc. + Copyright (C) 2011 Red Hat, Inc. -This file is part of IcedTea. + 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 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. + 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. + 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. + 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. + 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. */ import java.io.File; @@ -50,14 +50,18 @@ public class SimpleTest1Test { - private static ServerAccess server = new ServerAccess(); + private static final ServerAccess server = new ServerAccess(); private static final List strict = Arrays.asList(new String[]{"-strict", ServerAccess.VERBOSE_OPTION}); - private void checkLaunched(ProcessResult pr) { + static void checkLaunched(ProcessResult pr) { checkLaunched(pr, false); } - private void checkLaunched(ProcessResult pr, boolean negate) { + static void checkLaunched(ProcessResult pr, boolean negate) { + checkLaunched(pr, negate, true); + } + + static void checkLaunched(ProcessResult pr, boolean negate, boolean checkTermination) { String s = "Good simple javaws exapmle"; if (negate) { Assert.assertFalse("testSimpletest1lunchOk stdout should NOT contains " + s + " bud did", pr.stdout.contains(s)); @@ -71,8 +75,14 @@ //disabled, unnecessary exceptions may occure //Assert.assertFalse("testSimpletest1lunchOk stderr should not contains " + ss + " but did", pr.stderr.contains(ss)); } - Assert.assertFalse(pr.wasTerminated); - Assert.assertEquals((Integer) 0, pr.returnValue); + if (checkTermination) { + Assert.assertFalse(pr.wasTerminated); + if (negate) { + Assert.assertEquals((Integer) 1, pr.returnValue); + } else { + Assert.assertEquals((Integer) 0, pr.returnValue); + } + } } @Test diff -r f589afe6e008 -r f48d4c62c2e3 tests/reproducers/simple/simpletest1/testcases/SimpleTestDefaultRedirects.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/reproducers/simple/simpletest1/testcases/SimpleTestDefaultRedirects.java Wed Jan 06 09:53:38 2016 +0100 @@ -0,0 +1,290 @@ +/* SimpleTest1Test.java + Copyright (C) 2011 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. + */ + +import java.net.MalformedURLException; +import java.util.Arrays; +import java.util.List; +import net.sourceforge.jnlp.OptionsDefinitions; +import net.sourceforge.jnlp.ProcessResult; +import net.sourceforge.jnlp.ServerAccess; +import net.sourceforge.jnlp.ServerLauncher; +import org.junit.Assert; + +import org.junit.Test; + +public class SimpleTestDefaultRedirects { + + private static final ServerAccess server = new ServerAccess(); + + private static final String D = "-J-Dhttp.maxRedirects=20"; //default - https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html , but... + //unluckily, setting http.maxRedirects to eg 1 do not have testing benefit + //as httpconnection then jsut throws exception instead of returning header to app's investigations + //I doubt it is worthy to struggle with setInstanceFollowRedirects in production code + + private static final List hr = Arrays.asList(new String[]{D, ServerAccess.HEADLES_OPTION, OptionsDefinitions.OPTIONS.REDIRECT.option}); + private static final List hrv = Arrays.asList(new String[]{D, ServerAccess.VERBOSE_OPTION, ServerAccess.HEADLES_OPTION, OptionsDefinitions.OPTIONS.REDIRECT.option}); + private static final List hv = Arrays.asList(new String[]{D, ServerAccess.VERBOSE_OPTION, ServerAccess.HEADLES_OPTION}); + +/* creates redirecting instances so oe can debug itw against it */ +// public static void main(String[] args) throws InterruptedException, MalformedURLException { +// ServerLauncher[] servers = new ServerLauncher[3]; +// +// ServerLauncher server0 = ServerAccess.getIndependentInstance(); +// server0.setRedirect(ServerAccess.getInstance()); //redirecting to normal server singleton +// server0.setRedirectCode(301); +// servers[0] = server0; +// +// ServerLauncher server1 = ServerAccess.getIndependentInstance(); +// server1.setRedirect(server0); +// server1.setRedirectCode(301); +// servers[1] = server1; +// +// ServerLauncher server2 = ServerAccess.getIndependentInstance(); +// server2.setRedirect(server1); +// server2.setRedirectCode(301); +// servers[2] = server2; +// +// System.out.println(server0); +// System.out.println(server1); +// System.out.println(server2); +// +// try { +// System.out.println(server0.getUrl("/" + "simpletest1.jnlp")); +// System.out.println(server1.getUrl("/" + "simpletest1.jnlp")); +// System.out.println(server2.getUrl("/" + "simpletest1.jnlp")); +// while (true) { +// Thread.sleep(100); +// } +// } finally { +// for (ServerLauncher server : servers) { +// server.stop(); +// } +// } +// } + + public void testbody(List args, boolean pass, int... redirectCodes) throws Exception { + testbody(args, pass, -1, redirectCodes); + } + + public void testbody(List args, boolean pass, int breakChain, int... redirectCodes) throws Exception { + if (redirectCodes.length < 1) { + throw new RuntimeException("At least one redrection server pelase"); + } + ServerLauncher[] servers = new ServerLauncher[redirectCodes.length]; + + ServerLauncher server0 = ServerAccess.getIndependentInstance(); + server0.setRedirect(ServerAccess.getInstance()); //redirecting to normal server singleton + server0.setRedirectCode(redirectCodes[0]); //redirecting by first code + servers[0] = server0; + + //create redirect chain + for (int i = 1; i < redirectCodes.length; i++) { + ServerLauncher serverI = ServerAccess.getIndependentInstance(); + serverI.setRedirect(servers[i - 1]); //redirecting to pevious in chain + serverI.setRedirectCode(redirectCodes[i]); //by given code + servers[i] = serverI; + + } + testbody(args, pass, breakChain, servers); + } + + public void testbody(List args, boolean pass, int breakChain, ServerLauncher[] servers) throws Exception { + if (breakChain >= 0) { + servers[breakChain].setRedirect(null); + servers[breakChain].stop(); + } + ServerLauncher server3012378 = servers[servers.length - 1]; + try { + //now connect to last in chain and we should always get reposnse from ServerAccess.getInstance() + ProcessResult pr = ServerAccess.executeProcessUponURL(server.getJavawsLocation(), + args, + server3012378.getUrl("/" + "simpletest1.jnlp"), + null, + null + ); + SimpleTest1Test.checkLaunched(pr, !pass, false); + if (pass) { + Assert.assertTrue(0 == pr.returnValue); + } else { + //1.6 have wrong handling of pr.return value + //Assert.assertFalse(0 == pr.returnValue); + } + } finally { + for (int i = 0; i < servers.length; i++) { + if (i != breakChain) { + ServerLauncher serverI = servers[i]; + try { + serverI.setRedirect(null); + serverI.stop(); + } catch (Exception ex) { + ServerAccess.logException(ex); + } + } + } + } + } + + // note, tonly 308 needs help form ITW,others are redirected autmatically in http connection + // https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html#setInstanceFollowRedirects%28boolean%29 + public void testbody308(boolean pass, int... redirectCodes) throws Exception { + if (pass) { + testbody(hr, pass, redirectCodes); + } else { + testbody(hv, pass, redirectCodes); + } + } + + public void testbodyOthers(boolean pass, int... redirectCodes) throws Exception { + if (pass) { + testbody(hr, true, redirectCodes); + } else { + testbody(hv, true, redirectCodes); + } + } + + //some chains tests + @Test + public void testSimpletest1RedirectChain1AllowedOk() throws Exception { + testbodyOthers(true, 301, 302, 303, 307); + } + + @Test + public void testSimpletest1RedirectChain1NotAllowedOk() throws Exception { + testbodyOthers(false, 301, 302, 303, 307); + } + + @Test + public void testSimpletest1RedirectChain2AllowedOk() throws Exception { + testbody308(true, 301, 308, 302, 303, 307); + } + + @Test + public void testSimpletest1RedirectChain2NotAllowedOk() throws Exception { + server.executeJavawsClearCache(); + testbody308(false, 301, 308, 302, 303, 307); + } + + @Test + public void testSimpletest1RedirectChain3AllowedBroken() throws Exception { + server.executeJavawsClearCache(); + testbody(hrv, false, 1, new int[]{301, 302, 302, 303, 307}); + } + + @Test + public void testSimpletest1RedirectChain3NotAllowedBroken() throws Exception { + server.executeJavawsClearCache(); + testbody(hv, false, 1, new int[]{301, 302, 302, 303, 307}); + } + + @Test + public void testSimpletest1RedirectChain3AlowedCycle() throws Exception { + server.executeJavawsClearCache(); + ServerLauncher[] servers = new ServerLauncher[3]; + + ServerLauncher server0 = ServerAccess.getIndependentInstance(); + server0.setRedirect(ServerAccess.getInstance()); //redirecting to normal server singleton + server0.setRedirectCode(301); + servers[0] = server0; + + ServerLauncher server1 = ServerAccess.getIndependentInstance(); + server1.setRedirectCode(301); + servers[1] = server1; + + ServerLauncher server2 = ServerAccess.getIndependentInstance(); + server2.setRedirectCode(301); + servers[2] = server2; + + server1.setRedirect(server2); + server2.setRedirect(server1); + testbody(hrv, false, -1, servers); + } + + //end chains + // basic tests + @Test + public void testSimpletest1Redirect301AllowedOk() throws Exception { + testbodyOthers(true, 301); + } + + @Test + public void testSimpletest1Redirect301NotAllowedOk() throws Exception { + testbodyOthers(false, 301); + } + + @Test + public void testSimpletest1Redirect302AllowedOk() throws Exception { + testbodyOthers(true, 302); + } + + @Test + public void testSimpletest1Redirect302NotAllowedOk() throws Exception { + testbodyOthers(false, 302); + } + + @Test + public void testSimpletest1Redirect303AllowedOk() throws Exception { + testbodyOthers(true, 303); + } + + @Test + public void testSimpletest1Redirect331NotAllowedOk() throws Exception { + testbodyOthers(false, 303); + } + + @Test + public void testSimpletest1Redirect307AllowedOk() throws Exception { + testbodyOthers(true, 307); + } + + @Test + public void testSimpletest1Redirect307NotAllowedOk() throws Exception { + testbodyOthers(false, 307); + } + + @Test + public void testSimpletest1Redirect308AllowedOk() throws Exception { + testbody308(true, 308); + } + + @Test + public void testSimpletest1Redirect308NotAllowedOk() throws Exception { + server.executeJavawsClearCache(); + testbody308(false, 308); + } + // end basic tests + +} diff -r f589afe6e008 -r f48d4c62c2e3 tests/test-extensions/net/sourceforge/jnlp/ServerLauncher.java --- a/tests/test-extensions/net/sourceforge/jnlp/ServerLauncher.java Tue Jan 05 10:27:13 2016 +0100 +++ b/tests/test-extensions/net/sourceforge/jnlp/ServerLauncher.java Wed Jan 06 09:53:38 2016 +0100 @@ -1,46 +1,46 @@ /* ServerLauncher.java -Copyright (C) 2011,2012 Red Hat, Inc. + 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. + This file is part of IcedTea. -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. + 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. -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. + 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. -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. + 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. + 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.net.MalformedURLException; import java.net.ServerSocket; import java.net.URL; +import java.util.Map; /** * wrapper around tiny http server to separate lunch configurations and servers. @@ -49,8 +49,8 @@ public class ServerLauncher implements Runnable { /** - * default url name part. - * This can be changed in runtime, but will affect all following tasks upon those server + * default url name part. This can be changed in runtime, but will affect + * all following tasks upon those server */ private String serverName = ServerAccess.DEFAULT_LOCALHOST_NAME; private boolean running; @@ -108,12 +108,42 @@ this(8181, new File(System.getProperty("user.dir"))); } + /** + * When redirect is set, the requests to this server will just redirect to + * the underlying ServerLauncher + */ + private ServerLauncher redirect = null; + /** + * one of: 301, 302,303, 307, 308, + */ + private int redirectCode = 302; + + public void setRedirect(ServerLauncher redirect) { + this.redirect = redirect; + + } + + public void setRedirectCode(int redirectPort) { + this.redirectCode = redirectPort; + } + + //resoource -> request -> number of requests on of this rsource on this server + // eg simpletest1.jnlp -> GET -> 3 + private Map> requestsCounter; + + public void setRequestsCounter(Map> requestsCounter) { + this.requestsCounter = requestsCounter; + } + public void run() { running = true; try { serverSocket = new ServerSocket(port); while (running) { TinyHttpdImpl server = new TinyHttpdImpl(serverSocket.accept(), dir, false); + server.setRedirect(redirect); + server.setRedirectCode(redirectCode); + server.setRequestsCounter(requestsCounter); server.setSupportingHeadRequest(isSupportingHeadRequest()); server.start(); } diff -r f589afe6e008 -r f48d4c62c2e3 tests/test-extensions/net/sourceforge/jnlp/TinyHttpdImpl.java --- a/tests/test-extensions/net/sourceforge/jnlp/TinyHttpdImpl.java Tue Jan 05 10:27:13 2016 +0100 +++ b/tests/test-extensions/net/sourceforge/jnlp/TinyHttpdImpl.java Wed Jan 06 09:53:38 2016 +0100 @@ -1,40 +1,39 @@ /* TinyHttpdImpl.java -Copyright (C) 2011,2012 Red Hat, Inc. + 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. + This file is part of IcedTea. -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. + 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. -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. + 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. -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. + 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. + 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.BufferedReader; @@ -47,19 +46,20 @@ import java.net.Socket; import java.net.SocketException; import java.net.URLDecoder; -import java.security.cert.CRL; import java.util.Date; +import java.util.HashMap; +import java.util.Map; import java.util.StringTokenizer; import net.sourceforge.jnlp.cache.ResourceTracker; /** - * based on http://www.mcwalter.org/technology/java/httpd/tiny/index.html - * Very small implementation of http return headers for our served resources - * Originally Licenced under GPLv2.0 + * based on http://www.mcwalter.org/technology/java/httpd/tiny/index.html Very + * small implementation of http return headers for our served resources + * Originally Licenced under GPLv2.0 * - * When resource starts with XslowX prefix, then resouce (without XslowX) - * is returned, but its delivery is delayed + * When resource starts with XslowX prefix, then resouce (without XslowX) is + * returned, but its delivery is delayed */ public class TinyHttpdImpl extends Thread { @@ -143,52 +143,77 @@ String filePath = t.nextToken(); boolean slowSend = filePath.startsWith(XSX); - if (slowSend) { - filePath = filePath.replace(XSX, "/"); + if (requestsCounter != null) { + String resource = filePath.replace(XSX, "/"); + resource = urlToFilePath(resource); + Map reosurceRecord = requestsCounter.get(resource); + if (reosurceRecord == null) { + reosurceRecord = new HashMap<>(); + requestsCounter.put(resource, reosurceRecord); + } + Integer i = reosurceRecord.get(request); + if (i == null) { + i = 0; + } + i++; + reosurceRecord.put(request, i); } - ServerAccess.logOutputReprint("Getting- " + request + ": " + filePath); - filePath = urlToFilePath(filePath); + if (redirect != null) { + String where = redirect.getUrl(filePath).toExternalForm(); + ServerAccess.logOutputReprint("Redirecting " + request + "as " + redirectCode + " to " + where); + writer.writeBytes("HTTP/1.0 " + redirectCode + " Moved" + CRLF); + writer.writeBytes("Location: " + where + CRLF); + writer.writeBytes(CRLF); + } else { - File resource = new File(this.testDir, filePath); + if (slowSend) { + filePath = filePath.replace(XSX, "/"); + } - if (!(resource.isFile() && resource.canRead())) { - ServerAccess.logOutputReprint("Could not open file " + filePath); - writer.writeBytes(HTTP_NOT_FOUND); - continue; - } - ServerAccess.logOutputReprint("Serving- " + request + ": " + filePath); + ServerAccess.logOutputReprint("Getting- " + request + ": " + filePath); + filePath = urlToFilePath(filePath); + + File resource = new File(this.testDir, filePath); - int resourceLength = (int) resource.length(); - byte[] buff = new byte[resourceLength]; - FileInputStream fis = new FileInputStream(resource); - fis.read(buff); - fis.close(); + if (!(resource.isFile() && resource.canRead())) { + ServerAccess.logOutputReprint("Could not open file " + filePath); + writer.writeBytes(HTTP_NOT_FOUND); + continue; + } + ServerAccess.logOutputReprint("Serving- " + request + ": " + filePath); - String contentType = "Content-Type: "; - if (filePath.toLowerCase().endsWith(".jnlp")) { - contentType += "application/x-java-jnlp-file"; - } else if (filePath.toLowerCase().endsWith(".jar")) { - contentType += "application/x-jar"; - } else { - contentType += "text/html"; - } - String lastModified = ""; - if (supportLastModified) { - lastModified = "Last-Modified: " + new Date(resource.lastModified()) + CRLF; - } - writer.writeBytes(HTTP_OK + "Content-Length:" + resourceLength + CRLF + lastModified + contentType + CRLF + CRLF); + int resourceLength = (int) resource.length(); + byte[] buff = new byte[resourceLength]; + FileInputStream fis = new FileInputStream(resource); + fis.read(buff); + fis.close(); - if (isGetRequest) { - if (slowSend) { - byte[][] bb = splitArray(buff, 10); - for (int j = 0; j < bb.length; j++) { - Thread.sleep(2000); - byte[] bs = bb[j]; - writer.write(bs, 0, bs.length); + String contentType = "Content-Type: "; + if (filePath.toLowerCase().endsWith(".jnlp")) { + contentType += "application/x-java-jnlp-file"; + } else if (filePath.toLowerCase().endsWith(".jar")) { + contentType += "application/x-jar"; + } else { + contentType += "text/html"; + } + String lastModified = ""; + if (supportLastModified) { + lastModified = "Last-Modified: " + new Date(resource.lastModified()) + CRLF; + } + writer.writeBytes(HTTP_OK + "Content-Length:" + resourceLength + CRLF + lastModified + contentType + CRLF + CRLF); + + if (isGetRequest) { + if (slowSend) { + byte[][] bb = splitArray(buff, 10); + for (int j = 0; j < bb.length; j++) { + Thread.sleep(2000); + byte[] bs = bb[j]; + writer.write(bs, 0, bs.length); + } + } else { + writer.write(buff, 0, resourceLength); } - } else { - writer.write(buff, 0, resourceLength); } } } @@ -207,13 +232,14 @@ } /** - * This function splits input array to severasl pieces - * from byte[length] splitt to n pieces s is retrunrd byte[n][length/n], except - * last piece which contains length%n + * This function splits input array to severasl pieces from byte[length] + * splitt to n pieces s is retrunrd byte[n][length/n], except last piece + * which contains length%n * * @param input - array to be splitted * @param pieces - to how many pieces it should be broken - * @return inidividual pices of original array, which concatet again givs original array + * @return inidividual pices of original array, which concatet again givs + * original array */ public static byte[][] splitArray(byte[] input, int pieces) { int rest = input.length; @@ -239,12 +265,13 @@ } /** - * This function transforms a request URL into a path to a file which the server - * will return to the requester. - * @param url - the request URL - * @return a String representation of the local path to the file - * @throws UnsupportedEncodingException - */ + * This function transforms a request URL into a path to a file which the + * server will return to the requester. + * + * @param url - the request URL + * @return a String representation of the local path to the file + * @throws UnsupportedEncodingException + */ public static String urlToFilePath(String url) throws UnsupportedEncodingException { url = URLDecoder.decode(url, "UTF-8"); // Decode URL encoded charaters, eg "%3B" becomes ';' if (url.startsWith(XSX)) { @@ -261,8 +288,9 @@ } /** - * This function removes the HTTP Path Parameter from a given JAR URL, assuming that the - * path param delimiter is a semicolon + * This function removes the HTTP Path Parameter from a given JAR URL, + * assuming that the path param delimiter is a semicolon + * * @param url - the URL from which to remove the path parameter * @return the URL with the path parameter removed */ @@ -282,4 +310,31 @@ } return url; } + + /** + * When redirect is set, the requests to this server will just redirect to + * the underlying ServerLauncher + */ + private ServerLauncher redirect = null; + + void setRedirect(ServerLauncher redirect) { + this.redirect = redirect; + } + + /** + * one of: 301, 302,303, 307, 308, + */ + private int redirectCode = 302; + + void setRedirectCode(int redirectPort) { + this.redirectCode = redirectPort; + } + + //resoource -> request -> number of requests on of this rsource on this server + // eg simpletest1.jnlp -> GET -> 3 + private Map> requestsCounter; + + public void setRequestsCounter(Map> requestsCounter) { + this.requestsCounter = requestsCounter; + } }