junit
diff --git a/src/assembly/aio.xml b/src/assembly/aio.xml
new file mode 100644
index 0000000..c5e5c72
--- /dev/null
+++ b/src/assembly/aio.xml
@@ -0,0 +1,20 @@
+
+
+
+ aio
+
+ jar
+
+ false
+
+
+ /
+ true
+ true
+ runtime
+
+ com.sun.jersey:jersey-server
+
+
+
+
diff --git a/src/assembly/deps.xml b/src/assembly/deps.xml
new file mode 100644
index 0000000..b1ab6b2
--- /dev/null
+++ b/src/assembly/deps.xml
@@ -0,0 +1,25 @@
+
+
+ deps
+
+ zip
+ tar.gz
+
+ false
+
+
+ true
+
+ org.opengis.cite.teamengine:teamengine-spi-ctl
+
+ /
+ false
+ runtime
+ true
+ true
+
+
+
diff --git a/src/main/java/org/opengis/cite/csw20/CSW20.java b/src/main/java/org/opengis/cite/csw20/CSW20.java
new file mode 100644
index 0000000..27cbd01
--- /dev/null
+++ b/src/main/java/org/opengis/cite/csw20/CSW20.java
@@ -0,0 +1,17 @@
+package org.opengis.cite.csw20;
+
+/**
+ * Contains various constants defined in the CSW 2.0.2 specification, such as test
+ * run parameters.
+ *
+ * @see "OGC 07-006r1: OGC Catalog Service for the Web Implementation Specification, Version 2.0.2"
+ */
+public class CSW20 {
+
+ private CSW20() {
+ }
+
+ /** Supplies reference to CSW capabilities document (URI). */
+ public static final String CAPABILITIES_URL = "capabilities.url";
+
+}
diff --git a/src/main/java/org/opengis/cite/csw20/CtlController.java b/src/main/java/org/opengis/cite/csw20/CtlController.java
new file mode 100644
index 0000000..753e4ac
--- /dev/null
+++ b/src/main/java/org/opengis/cite/csw20/CtlController.java
@@ -0,0 +1,127 @@
+package org.opengis.cite.csw20;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Source;
+
+import org.w3c.dom.Document;
+
+import com.occamlab.te.SetupOptions;
+import com.occamlab.te.spi.ctl.CtlExecutor;
+import com.occamlab.te.spi.executors.TestRunExecutor;
+import com.occamlab.te.spi.jaxrs.TestSuiteController;
+
+public class CtlController implements TestSuiteController {
+
+ private TestRunExecutor executor;
+ private Properties etsProperties = new Properties();
+
+ /**
+ * Constructs a controller object for this test suite. The location of the
+ * main CTL script is read from the "main-script" property in the
+ * ets.properties file (a classpath resource).
+ */
+ public CtlController() {
+ SetupOptions setupOpts = new SetupOptions();
+ try (InputStream is = getClass().getResourceAsStream("ets.properties")) {
+ this.etsProperties.load(is);
+ String mainScriptPath = etsProperties.getProperty("main-script");
+ File ctlFile = findScriptFile(URI.create(mainScriptPath));
+ setupOpts.addSource(ctlFile);
+ this.executor = new CtlExecutor(setupOpts);
+ } catch (IOException ex) {
+ Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Failed to initialize CtlController. {0}",
+ ex.getMessage());
+ }
+ }
+
+ /**
+ * A convenience method for running the test suite using a command-line
+ * interface.
+ *
+ * @param args
+ * Test run arguments (optional). The first argument must refer
+ * to a local XML properties file containing the expected set of
+ * test run arguments. If no argument is supplied, the file
+ * located at ${user.home}/test-run-props.xml will be used.
+ * @throws Exception
+ * If an error errors during the test run.
+ */
+ public static void main(String[] args) throws Exception {
+ File propsFile;
+ if (args.length == 0) {
+ propsFile = new File(System.getProperty("user.home"), "test-run-props.xml");
+ } else {
+ String xmlProps = args[0];
+ propsFile = (xmlProps.startsWith("file:")) ? new File(URI.create(xmlProps)) : new File(xmlProps);
+ }
+ if (!propsFile.isFile()) {
+ throw new IllegalArgumentException("Test run arguments not found at " + propsFile);
+ }
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document testRunArgs = db.parse(propsFile);
+ TestSuiteController controller = new CtlController();
+ Source results = controller.doTestRun(testRunArgs);
+ Logger.getLogger(CtlController.class.getName()).log(Level.INFO, "Test results: {0}", results.getSystemId());
+ }
+
+ public String getCode() {
+ return etsProperties.getProperty("ets-code");
+ }
+
+ public String getVersion() {
+ return etsProperties.getProperty("ets-version");
+ }
+
+ public String getTitle() {
+ return etsProperties.getProperty("ets-title");
+ }
+
+ public Source doTestRun(Document testRunArgs) throws Exception {
+ Properties validArgs = TestRunArguments.validateArguments(testRunArgs);
+
+ return executor.execute(TestRunArguments.propertiesAsDocument(validArgs));
+ }
+
+ /**
+ * Creates a File from the given URI reference. If the URI is not absolute,
+ * is is resolved against the location of the TE_BASE/scripts directory; if
+ * a file does not exist at this location the URI is assumed to be a
+ * classpath reference.
+ *
+ * @param uri
+ * An absolute or relative URI.
+ * @return A File object, or null if one could not be created.
+ */
+ final File findScriptFile(URI uri) {
+ File ctlFile = null;
+ File baseDir = SetupOptions.getBaseConfigDirectory();
+ if (!uri.isAbsolute()) {
+ File scriptsDir = new File(baseDir, "scripts");
+ ctlFile = new File(scriptsDir, uri.getPath());
+ }
+ if (null == ctlFile || !ctlFile.isFile()) {
+ URL resource = getClass().getResource(uri.getPath());
+ try {
+ ctlFile = new File(resource.toURI());
+ } catch (URISyntaxException ex) {
+ Logger.getLogger(getClass().getName()).log(Level.INFO, "Invalid URI: {0}", ex);
+ }
+ }
+ Logger.getLogger(getClass().getName()).log(Level.CONFIG, "Created File object: {0}", ctlFile);
+ return ctlFile;
+ }
+
+}
+
\ No newline at end of file
diff --git a/src/main/java/org/opengis/cite/csw20/TestRunArguments.java b/src/main/java/org/opengis/cite/csw20/TestRunArguments.java
new file mode 100644
index 0000000..4a9f878
--- /dev/null
+++ b/src/main/java/org/opengis/cite/csw20/TestRunArguments.java
@@ -0,0 +1,85 @@
+package org.opengis.cite.csw20;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Properties;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Provides utility methods that assist with the handling of test run arguments.
+ */
+public class TestRunArguments {
+
+ /**
+ * Validates the given test run arguments. An
+ * IllegalArgumentException
is thrown if a required argument is
+ * missing or invalid. The recognized arguments are listed below.
+ *
+ * - {@value org.opengis.cite.csw20.CSW20#CAPABILITIES_URL}
+ * (required)
+ *
+ *
+ * @param testRunArgs
+ * A Document containing a set of XML properties; each entry
+ * (key-value pair) is a test run argument.
+ * @return A valid set of test run arguments.
+ */
+ public static Properties validateArguments(Document testRunArgs) {
+ NodeList entries = testRunArgs.getDocumentElement().getElementsByTagName("entry");
+ if (entries.getLength() == 0) {
+ throw new IllegalArgumentException("No test run arguments.");
+ }
+ // load defaults?
+ Properties args = new Properties();
+ for (int i = 0; i < entries.getLength(); i++) {
+ Element entry = (Element) entries.item(i);
+ args.setProperty(entry.getAttribute("key"), entry.getTextContent().trim());
+ }
+ String capabilitiesUrl = args.getProperty(CSW20.CAPABILITIES_URL);
+ try {
+ URI uriRef = new URI(capabilitiesUrl);
+ if (!uriRef.isAbsolute()) {
+ throw new IllegalArgumentException(String.format("Not an absolute URI: %s", uriRef));
+ }
+ } catch (URISyntaxException e1) {
+ throw new IllegalArgumentException(String.format("Invalid URI reference: %s", capabilitiesUrl));
+ } catch (NullPointerException e2) {
+ throw new IllegalArgumentException(String.format("Missing required argument: %s", CSW20.CAPABILITIES_URL));
+ }
+ return args;
+ }
+
+ /**
+ * Creates a document that contains a simple XML representation of the given
+ * set of properties.
+ *
+ * @param props
+ * A set of properties (key-value pairs).
+ * @return A Document node, wherein each property is represented by an
+ * entry[@key] element.
+ */
+ public static Document propertiesAsDocument(Properties props) {
+ Document doc = null;
+ try {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ props.storeToXML(outStream, "Test run arguments");
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ doc = builder.parse(new ByteArrayInputStream(outStream.toByteArray()));
+ } catch (Exception e) { // very unlikely
+ Logger.getLogger(TestRunArguments.class.getName()).log(Level.WARNING, "Failed to create Document node. {0}",
+ e.getMessage());
+ }
+ return doc;
+ }
+
+}
diff --git a/src/main/javadoc/index.html b/src/main/javadoc/index.html
new file mode 100644
index 0000000..0204851
--- /dev/null
+++ b/src/main/javadoc/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html
new file mode 100644
index 0000000..1b362eb
--- /dev/null
+++ b/src/main/javadoc/overview.html
@@ -0,0 +1,92 @@
+
+
+
+ CSW 2.0.2 Conformance Test Suite
+
+
+
+
+ CSW 2.0.2 Conformance Test Suite
+ Verifies that OGC Catalog Service for the Web (CSW) 2.0.2 Test-Suite implementation is based on the following OGC specifications:
+
+ - OGC Catalogue Services Specification - 2.0.2 [ OGC 07-006r1]
+
+
+ The test run arguments are summarized in the following table. The Obligation
+ descriptor can have the following values: M (mandatory), O (optional), or C
+ (conditional).
+
+
+
+
+
diff --git a/src/main/resources/META-INF/services/com.occamlab.te.spi.jaxrs.TestSuiteController b/src/main/resources/META-INF/services/com.occamlab.te.spi.jaxrs.TestSuiteController
new file mode 100644
index 0000000..c386443
--- /dev/null
+++ b/src/main/resources/META-INF/services/com.occamlab.te.spi.jaxrs.TestSuiteController
@@ -0,0 +1 @@
+org.opengis.cite.csw20.CtlController
\ No newline at end of file
diff --git a/src/main/resources/org/opengis/cite/csw20/ets.properties b/src/main/resources/org/opengis/cite/csw20/ets.properties
new file mode 100644
index 0000000..f7fd30d
--- /dev/null
+++ b/src/main/resources/org/opengis/cite/csw20/ets.properties
@@ -0,0 +1,4 @@
+ets-title = ${project.name}
+ets-version = ${project.version}
+ets-code = ${ets-code}
+main-script = /${ets-code}/${spec-version}/ctl/main-auto.xml
diff --git a/src/main/resources/org/opengis/cite/csw20/test-run-props.xml b/src/main/resources/org/opengis/cite/csw20/test-run-props.xml
new file mode 100644
index 0000000..b37c7ba
--- /dev/null
+++ b/src/main/resources/org/opengis/cite/csw20/test-run-props.xml
@@ -0,0 +1,6 @@
+
+
+
+ Test run arguments for ets-csw20
+
+
diff --git a/src/main/scripts/ctl/main-auto.xml b/src/main/scripts/ctl/main-auto.xml
new file mode 100644
index 0000000..197a306
--- /dev/null
+++ b/src/main/scripts/ctl/main-auto.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+ CSW 2.0.2 Compliance Test Suite
+
+ Verifies a CSW 2.0.2 catalogue implementation against all applicable
+ abstract test suites. No specific CSW application profile is presumed.
+ These tests are intended to be incorporated into profile-specific test
+ suites.
+
+ data/csw-2.0.2-data.zip
+ docs/csw/2.0.2/
+ csw:Main-auto
+
+
+
+
+ The implementation under test minimally conforms to the CSW
+ part (Clause 10) of Catalogue 2.0.2 (OGC 07-006r1).
+
+
+
+
+
+
+ GET
+
+
+
+
+
+ [FAILURE] Did not obtain a csw:Capabilities document! Skipping remaining tests.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Confirm that the IUT is ready to undergo testing.
+
+
+ Check all of the following conditions:
+ (1) the service is available;
+ (2) the capabilities document is valid;
+ (3) test data have been loaded.
+ If any of these checks fail, the test run is aborted.
+
+
+
+ Check that the capabilities document is valid against
+ the schema.
+
+
+ /sch/csw/2.0.2/Capabilities.sch
+ RequiredElementsPhase
+
+
+
+
+
+
+
+
+