/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.opensearch.eo;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.servlet.Filter;
import javax.xml.XMLConstants;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.apache.commons.io.FileUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.opensearch.eo.store.OpenSearchAccess;
import org.geoserver.test.GeoServerSystemTestSupport;
import org.geotools.jdbc.JDBCDataStore;
import org.geotools.jdbc.JDBCDataStoreFactory;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.util.xml.SimpleNamespaceContext;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* Base class for OpenSeach tests
*
* @author Andrea Aime - GeoSolutions
*/
public class OSEOTestSupport extends GeoServerSystemTestSupport {
private static Schema OS_SCHEMA;
private static Schema ATOM_SCHEMA;
protected SimpleNamespaceContext namespaceContext;
static {
final SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
OS_SCHEMA = factory
.newSchema(OSEOTestSupport.class.getResource("/schemas/OpenSearch.xsd"));
ATOM_SCHEMA = factory
.newSchema(OSEOTestSupport.class.getResource("/schemas/searchResults.xsd"));
} catch (Exception e) {
throw new RuntimeException("Could not parse the OpenSearch schemas", e);
}
}
protected List<Filter> getFilters() {
return Collections.singletonList(new OSEOFilter());
}
@Override
protected void setUpTestData(SystemTestData testData) throws Exception {
// no data to setup
}
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
setupBasicOpenSearch(testData, getCatalog(), getGeoServer());
}
/**
* Sets up a H2 based OpenSearchAccess and configures OpenSearch for EO to use it
*
* @param testData
* @param cat
* @param gs
* @throws IOException
* @throws SQLException
*/
public static void setupBasicOpenSearch(SystemTestData testData, Catalog cat, GeoServer gs)
throws IOException, SQLException {
// create the plain database
DataStoreInfo jdbcDs = cat.getFactory().createDataStore();
jdbcDs.setName("oseo_jdbc");
WorkspaceInfo ws = cat.getDefaultWorkspace();
jdbcDs.setWorkspace(ws);
jdbcDs.setEnabled(true);
Map params = jdbcDs.getConnectionParameters();
params.put("dbtype", "h2");
File dbFolder = new File(testData.getDataDirectoryRoot(), "oseo_db");
FileUtils.deleteQuietly(dbFolder);
dbFolder.mkdir();
File dbFile = new File(dbFolder, "oseo_db");
params.put("database", dbFile.getAbsolutePath());
params.put(JDBCDataStoreFactory.EXPOSE_PK.key, "true");
cat.add(jdbcDs);
JDBCDataStore h2 = (JDBCDataStore) jdbcDs.getDataStore(null);
JDBCOpenSearchAccessTest.populateTestDatabase(h2);
// create the OpenSeach wrapper store
DataStoreInfo osDs = cat.getFactory().createDataStore();
osDs.setName("oseo");
osDs.setWorkspace(ws);
osDs.setEnabled(true);
params = osDs.getConnectionParameters();
params.put("dbtype", "opensearch-eo-jdbc");
params.put("database", jdbcDs.getWorkspace().getName() + ":" + jdbcDs.getName());
params.put("store", jdbcDs.getWorkspace().getName() + ":" + jdbcDs.getName());
params.put("repository", null);
cat.add(osDs);
// configure opensearch for EO to use it
OSEOInfo service = gs.getService(OSEOInfo.class);
service.setOpenSearchAccessStoreId(osDs.getId());
gs.save(service);
// configure contact info
GeoServerInfo global = gs.getGlobal();
global.getSettings().getContact().setContactOrganization("GeoServer");
gs.save(global);
}
@Before
public void setupNamespaces() {
this.namespaceContext = new SimpleNamespaceContext();
namespaceContext.bindNamespaceUri("os", "http://a9.com/-/spec/opensearch/1.1/");
namespaceContext.bindNamespaceUri("param",
"http://a9.com/-/spec/opensearch/extensions/parameters/1.0/");
namespaceContext.bindNamespaceUri("at", "http://www.w3.org/2005/Atom");
namespaceContext.bindNamespaceUri("gml", "http://www.opengis.net/gml");
namespaceContext.bindNamespaceUri("georss", "http://www.georss.org/georss");
namespaceContext.bindNamespaceUri("eo", OpenSearchAccess.EO_NAMESPACE);
namespaceContext.bindNamespaceUri("geo", OpenSearchAccess.GEO_NAMESPACE);
namespaceContext.bindNamespaceUri("gmi", "http://www.isotc211.org/2005/gmi");
namespaceContext.bindNamespaceUri("gmd", "http://www.isotc211.org/2005/gmd");
namespaceContext.bindNamespaceUri("gco", "http://www.isotc211.org/2005/gco");
namespaceContext.bindNamespaceUri("time", "http://a9.com/-/opensearch/extensions/time/1.0");
namespaceContext.bindNamespaceUri("owc", "http://www.opengis.net/owc/1.0");
namespaceContext.bindNamespaceUri("dc", "http://purl.org/dc/elements/1.1/");
namespaceContext.bindNamespaceUri("media", "http://search.yahoo.com/mrss/");
for (OpenSearchAccess.ProductClass pc : OpenSearchAccess.ProductClass.values()) {
namespaceContext.bindNamespaceUri(pc.getPrefix(), pc.getNamespace());
}
}
protected Matcher<Node> hasXPath(String xPath) {
return Matchers.hasXPath(xPath, namespaceContext);
}
protected Matcher<Node> hasXPath(String xPath, Matcher<String> valueMatcher) {
return Matchers.hasXPath(xPath, namespaceContext, valueMatcher);
}
protected void checkValidOSDD(Document d) throws SAXException, IOException {
checkValidationErrors(d, OS_SCHEMA);
}
protected void checkValidAtomFeed(Document d) throws SAXException, IOException {
// TODO: we probably need to enrich this with EO specific elements check
checkValidationErrors(d, ATOM_SCHEMA);
}
/**
* Checks the response is a RSS and
*
* @param path
* @param i
* @return
* @throws Exception
*/
protected Document getAsOpenSearchException(String path, int expectedStatus) throws Exception {
return getAsDOM(path, expectedStatus, "application/xml"); // OSEOExceptionHandler.RSS_MIME);
}
/**
* Returns the DOM after checking the status code is 200 and the returned mime type is the expected one
*
* @param path
* @param expectedMimeType
* @return
* @throws Exception
*/
protected Document getAsDOM(String path, int expectedStatusCode, String expectedMimeType) throws Exception {
MockHttpServletResponse response = getAsServletResponse(path);
assertEquals(expectedMimeType, response.getContentType());
assertEquals(expectedStatusCode, response.getStatus());
Document dom = dom(new ByteArrayInputStream(response.getContentAsByteArray()));
return dom;
}
}