// ======================================================================== // Copyright (c) Webtide LLC // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.apache.org/licenses/LICENSE-2.0.txt // // You may elect to redistribute this code under either of these licenses. // ======================================================================== package org.eclipse.jetty.start; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class ConfigTest { private void assertEquals(String msg, Classpath expected, Classpath actual) { Assert.assertNotNull(msg + " : expected classpath should not be null",expected); Assert.assertNotNull(msg + " : actual classpath should not be null",actual); Assert.assertTrue(msg + " : expected should have an entry",expected.count() >= 1); Assert.assertTrue(msg + " : actual should have an entry",actual.count() >= 1); if (expected.count() != actual.count()) { expected.dump(System.err); actual.dump(System.err); Assert.assertEquals(msg + " : count",expected.count(),actual.count()); } List<File> actualEntries = Arrays.asList(actual.getElements()); List<File> expectedEntries = Arrays.asList(expected.getElements()); int len = expectedEntries.size(); for (int i = 0; i < len; i++) { File expectedFile = expectedEntries.get(i); File actualFile = actualEntries.get(i); if (!expectedFile.equals(actualFile)) { expected.dump(System.err); actual.dump(System.err); Assert.assertEquals(msg + ": entry [" + i + "]",expectedEntries.get(i),actualEntries.get(i)); } } } private void assertEquals(String msg, Collection<String> expected, Collection<String> actual) { Assert.assertTrue(msg + " : expected should have an entry",expected.size() >= 1); Assert.assertEquals(msg + " : size",expected.size(),actual.size()); for (String expectedVal : expected) { Assert.assertTrue(msg + " : should contain <" + expectedVal + ">",actual.contains(expectedVal)); } } private String getJettyEtcFile(String name) { File etc = new File(getTestableJettyHome(),"etc"); return new File(etc,name).getAbsolutePath(); } private File getJettyHomeDir() { return new File(getTestResourcesDir(),"jetty.home"); } private String getTestableJettyHome() { return getJettyHomeDir().getAbsolutePath(); } private File getTestResourcesDir() { File src = new File(System.getProperty("user.dir"),"src"); File test = new File(src,"test"); return new File(test,"resources"); } @Before public void reset() { Config.clearProperties(); } /* * Test for SUBJECT "/=" for assign canonical path */ @Test public void testSubjectAssignCanonicalPath() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("test.resources.dir/=src/test/resources\n"); Config cfg = new Config(); cfg.parse(buf); Assert.assertEquals(getTestResourcesDir().getCanonicalPath(),Config.getProperty("test.resources.dir")); } /* * Test for SUBJECT "~=" for assigning Start Properties */ @Test public void testSubjectAssignStartProperty() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("test.jetty.start.text~=foo\n"); buf.append("test.jetty.start.quote~=Eatagramovabits\n"); Config options = new Config(); options.parse(buf); Assert.assertEquals("foo",Config.getProperty("test.jetty.start.text")); Assert.assertEquals("Eatagramovabits",Config.getProperty("test.jetty.start.quote")); } /* * Test for SUBJECT "=" for assigning System Properties */ @Test public void testSubjectAssignSystemProperty() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("test.jetty.start.text=foo\n"); buf.append("test.jetty.start.quote=Eatagramovabits\n"); Config options = new Config(); options.parse(buf); Assert.assertEquals("foo",System.getProperty("test.jetty.start.text")); Assert.assertEquals("Eatagramovabits",System.getProperty("test.jetty.start.quote")); } /* * Test for SUBJECT ending with "/**", all jar and zip components in dir (deep, recursive) */ @Test public void testSubjectComponentDirDeep() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("$(jetty.home)/lib/**\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath actual = options.getClasspath(); Classpath expected = new Classpath(); File lib = new File(getJettyHomeDir(),"lib"); expected.addComponent(new File(lib,"core.jar")); expected.addComponent(new File(lib,"example.jar")); expected.addComponent(new File(lib,"http.jar")); expected.addComponent(new File(lib,"io.jar")); expected.addComponent(new File(lib,"JSR.ZIP")); expected.addComponent(new File(lib,"LOGGING.JAR")); expected.addComponent(new File(lib,"server.jar")); expected.addComponent(new File(lib,"spec.zip")); expected.addComponent(new File(lib,"util.jar")); expected.addComponent(new File(lib,"xml.jar")); File ext = new File(lib,"ext"); expected.addComponent(new File(ext,"custom-impl.jar")); File foo = new File(lib,"foo"); File bar = new File(foo,"bar"); expected.addComponent(new File(bar,"foobar.jar")); assertEquals("Components (Deep)",expected,actual); } /* * Test for SUBJECT ending with "/*", all jar and zip components in dir (shallow, no recursion) */ @Test public void testSubjectComponentDirShallow() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("# Example of any shallow components in /lib/\n"); buf.append("$(jetty.home)/lib/*\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath actual = options.getClasspath(); Classpath expected = new Classpath(); File lib = new File(getJettyHomeDir(),"lib"); expected.addComponent(new File(lib,"core.jar")); expected.addComponent(new File(lib,"example.jar")); expected.addComponent(new File(lib,"http.jar")); expected.addComponent(new File(lib,"io.jar")); expected.addComponent(new File(lib,"JSR.ZIP")); expected.addComponent(new File(lib,"LOGGING.JAR")); expected.addComponent(new File(lib,"server.jar")); expected.addComponent(new File(lib,"spec.zip")); expected.addComponent(new File(lib,"util.jar")); expected.addComponent(new File(lib,"xml.jar")); assertEquals("Components (Shallow)",expected,actual); } /* * Test for SUBJECT ending with ".class", a Main Class */ @Test public void testSubjectMainClass() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("org.eclipse.jetty.xml.XmlConfiguration.class"); Config options = new Config(); options.parse(buf); Assert.assertEquals("org.eclipse.jetty.xml.XmlConfiguration",options.getMainClassname()); } /* * Test for SUBJECT ending with ".class", a Main Class */ @Test public void testSubjectMainClassConditionalPropertySet() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("org.eclipse.jetty.xml.XmlConfiguration.class\n"); buf.append("${start.class}.class property start.class"); Config options = new Config(); options.setProperty("start.class","net.company.server.Start"); options.parse(buf); Assert.assertEquals("net.company.server.Start",options.getMainClassname()); } /* * Test for SUBJECT ending with ".class", a Main Class */ @Test public void testSubjectMainClassConditionalPropertyUnset() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("org.eclipse.jetty.xml.XmlConfiguration.class\n"); buf.append("${start.class}.class property start.class"); Config options = new Config(); // The "start.class" property is unset. options.parse(buf); Assert.assertEquals("org.eclipse.jetty.xml.XmlConfiguration",options.getMainClassname()); } /* * Test for SUBJECT ending with "/", a simple Classpath Entry */ @Test public void testSubjectSimpleComponent() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("$(jetty.home)/resources/\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath actual = options.getClasspath(); Classpath expected = new Classpath(); expected.addComponent(new File(getJettyHomeDir(),"resources")); assertEquals("Simple Component",expected,actual); } /* * Test for SUBJECT ending with "/", a simple Classpath Entry */ @Test public void testSubjectSimpleComponentMultiple() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("$(jetty.home)/resources/\n"); buf.append("$(jetty.home)/etc/\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath actual = options.getClasspath(); Classpath expected = new Classpath(); expected.addComponent(new File(getJettyHomeDir(),"resources")); expected.addComponent(new File(getJettyHomeDir(),"etc")); assertEquals("Simple Component",expected,actual); } /* * Test for SUBJECT ending with "/", a simple Classpath Entry */ @Test public void testSubjectSimpleComponentNotExists() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("$(jetty.home)/resources/\n"); buf.append("$(jetty.home)/foo/\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath actual = options.getClasspath(); Classpath expected = new Classpath(); expected.addComponent(new File(getJettyHomeDir(),"resources")); assertEquals("Simple Component",expected,actual); } /* * Test for SUBJECT ending with ".xml", an XML Configuration File */ @Test public void testSubjectXmlConfigAlt() throws IOException { StringBuffer buf = new StringBuffer(); // Doesn't exist buf.append("$(jetty.home)/etc/jetty.xml nargs == 0\n"); // test-alt does exist. buf.append("./src/test/resources/test-alt.xml nargs == 0 AND ! exists $(jetty.home)/etc/jetty.xml"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); List<String> actual = options.getXmlConfigs(); String expected = new File("src/test/resources/test-alt.xml").getAbsolutePath(); Assert.assertEquals("XmlConfig.size",1,actual.size()); Assert.assertEquals(expected,actual.get(0)); } /* * Test for SUBJECT ending with ".xml", an XML Configuration File */ @Test public void testSubjectXmlConfigDefault() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("$(jetty.home)/etc/test-jetty.xml nargs == 0\n"); buf.append("./jetty-server/src/main/config/etc/test-jetty.xml nargs == 0 AND ! exists $(jetty.home)/etc/test-jetty.xml"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); List<String> actual = options.getXmlConfigs(); String expected = getJettyEtcFile("test-jetty.xml"); Assert.assertEquals("XmlConfig.size",1,actual.size()); Assert.assertEquals(expected,actual.get(0)); } /* * Test for SUBJECT ending with ".xml", an XML Configuration File. */ @Test public void testSubjectXmlConfigMultiple() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("$(jetty.home)/etc/test-jetty.xml nargs == 0\n"); buf.append("$(jetty.home)/etc/test-jetty-ssl.xml nargs == 0\n"); buf.append("$(jetty.home)/etc/test-jetty-security.xml nargs == 0\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); List<String> actual = options.getXmlConfigs(); List<String> expected = new ArrayList<String>(); expected.add(getJettyEtcFile("test-jetty.xml")); expected.add(getJettyEtcFile("test-jetty-ssl.xml")); expected.add(getJettyEtcFile("test-jetty-security.xml")); assertEquals("Multiple XML Configs",expected,actual); } /* * Test Section Handling */ @Test public void testSectionClasspathSingle() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("[All]\n"); buf.append("$(jetty.home)/lib/core-test.jar\n"); buf.append("$(jetty.home)/lib/util.jar\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath defaultClasspath = options.getClasspath(); Assert.assertNotNull("Default Classpath should not be null",defaultClasspath); Classpath foocp = options.getSectionClasspath("Foo"); Assert.assertNull("Foo Classpath should not exist",foocp); Classpath allcp = options.getSectionClasspath("All"); Assert.assertNotNull("Classpath section 'All' should exist",allcp); File lib = new File(getJettyHomeDir(),"lib"); Classpath expected = new Classpath(); expected.addComponent(new File(lib,"core-test.jar")); expected.addComponent(new File(lib,"util.jar")); assertEquals("Single Classpath Section",expected,allcp); } /* * Test Section Handling */ @Test public void testSectionClasspathAvailable() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("[All]\n"); buf.append("$(jetty.home)/lib/core.jar ! available org.eclipse.jetty.dummy.Handler\n"); buf.append("$(jetty.home)/lib/util.jar ! available org.eclipse.jetty.dummy.StringUtils\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath defaultClasspath = options.getClasspath(); Assert.assertNotNull("Default Classpath should not be null",defaultClasspath); Classpath foocp = options.getSectionClasspath("Foo"); Assert.assertNull("Foo Classpath should not exist",foocp); Classpath allcp = options.getSectionClasspath("All"); Assert.assertNotNull("Classpath section 'All' should exist",allcp); File lib = new File(getJettyHomeDir(),"lib"); Classpath expected = new Classpath(); expected.addComponent(new File(lib,"core.jar")); expected.addComponent(new File(lib,"util.jar")); assertEquals("Single Classpath Section",expected,allcp); } /* * Test Section Handling, with multiple defined sections. */ @Test public void testSectionClasspathMultiples() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("# default\n"); buf.append("$(jetty.home)/lib/spec.zip\n"); buf.append("\n"); buf.append("[*]\n"); buf.append("$(jetty.home)/lib/io.jar\n"); buf.append("$(jetty.home)/lib/util.jar\n"); buf.append("\n"); buf.append("[All,server,default]\n"); buf.append("$(jetty.home)/lib/core.jar\n"); buf.append("$(jetty.home)/lib/server.jar\n"); buf.append("$(jetty.home)/lib/http.jar\n"); buf.append("\n"); buf.append("[All,xml,default]\n"); buf.append("$(jetty.home)/lib/xml.jar\n"); buf.append("\n"); buf.append("[All,logging]\n"); buf.append("$(jetty.home)/lib/LOGGING.JAR\n"); String jettyHome = getTestableJettyHome(); Config cfg = new Config(); cfg.setProperty("jetty.home",jettyHome); cfg.parse(buf); Classpath defaultClasspath = cfg.getClasspath(); Assert.assertNotNull("Default Classpath should not be null",defaultClasspath); Classpath foocp = cfg.getSectionClasspath("Foo"); Assert.assertNull("Foo Classpath should not exist",foocp); // Test if entire section list can be fetched Set<String> sections = cfg.getSectionIds(); Set<String> expected = new HashSet<String>(); expected.add(Config.DEFAULT_SECTION); expected.add("*"); expected.add("All"); expected.add("server"); expected.add("default"); expected.add("xml"); expected.add("logging"); assertEquals("Multiple Section IDs",expected,sections); // Test fetch of specific section by name works Classpath cpAll = cfg.getSectionClasspath("All"); Assert.assertNotNull("Classpath section 'All' should exist",cpAll); File lib = new File(getJettyHomeDir(),"lib"); Classpath expectedAll = new Classpath(); expectedAll.addComponent(new File(lib,"core.jar")); expectedAll.addComponent(new File(lib,"server.jar")); expectedAll.addComponent(new File(lib,"http.jar")); expectedAll.addComponent(new File(lib,"xml.jar")); expectedAll.addComponent(new File(lib,"LOGGING.JAR")); assertEquals("Classpath 'All' Section",expectedAll,cpAll); // Test combined classpath fetch of multiple sections works List<String> activated = new ArrayList<String>(); activated.add("server"); activated.add("logging"); Classpath cpCombined = cfg.getCombinedClasspath(activated); Classpath expectedCombined = new Classpath(); // from default expectedCombined.addComponent(new File(lib,"spec.zip")); // from 'server' expectedCombined.addComponent(new File(lib,"core.jar")); expectedCombined.addComponent(new File(lib,"server.jar")); expectedCombined.addComponent(new File(lib,"http.jar")); // from 'logging' expectedCombined.addComponent(new File(lib,"LOGGING.JAR")); // from '*' expectedCombined.addComponent(new File(lib,"io.jar")); expectedCombined.addComponent(new File(lib,"util.jar")); assertEquals("Classpath combined 'server,logging'",expectedCombined,cpCombined); } @Test public void testDynamicSection() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("[All,default,=$(jetty.home)/lib/*]\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath defaultClasspath = options.getClasspath(); Assert.assertNotNull("Default Classpath should not be null",defaultClasspath); Classpath foocp = options.getSectionClasspath("foo"); Assert.assertNotNull("Foo Classpath should not exist",foocp); Classpath allcp = options.getSectionClasspath("All"); Assert.assertNotNull("Classpath section 'All' should exist",allcp); Classpath extcp = options.getSectionClasspath("ext"); Assert.assertNotNull("Classpath section 'ext' should exist", extcp); Assert.assertEquals("Deep Classpath Section",0,foocp.count()); File lib = new File(getJettyHomeDir(),"lib"); File ext = new File(lib, "ext"); Classpath expected = new Classpath(); expected.addComponent(new File(ext,"custom-impl.jar")); assertEquals("Single Classpath Section",expected,extcp); } @Test public void testDeepDynamicSection() throws IOException { StringBuffer buf = new StringBuffer(); buf.append("[All,default,=$(jetty.home)/lib/**]\n"); String jettyHome = getTestableJettyHome(); Config options = new Config(); options.setProperty("jetty.home",jettyHome); options.parse(buf); Classpath defaultClasspath = options.getClasspath(); Assert.assertNotNull("Default Classpath should not be null",defaultClasspath); Classpath foocp = options.getSectionClasspath("foo"); Assert.assertNotNull("Foo Classpath should not exist",foocp); Classpath allcp = options.getSectionClasspath("All"); Assert.assertNotNull("Classpath section 'All' should exist",allcp); Classpath extcp = options.getSectionClasspath("ext"); Assert.assertNotNull("Classpath section 'ext' should exist", extcp); File lib = new File(getJettyHomeDir(),"lib"); Classpath expected = new Classpath(); File foo = new File(lib, "foo"); File bar = new File(foo, "bar"); expected.addComponent(new File(bar,"foobar.jar")); assertEquals("Deep Classpath Section",expected,foocp); File ext = new File(lib, "ext"); expected = new Classpath(); expected.addComponent(new File(ext,"custom-impl.jar")); assertEquals("Single Classpath Section",expected,extcp); } }