package io.eguan.vold.rest.resources;
/*
* #%L
* Project eguan
* %%
* Copyright (C) 2012 - 2017 Oodrive
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import io.eguan.configuration.MetaConfiguration;
import io.eguan.rest.container.JettyConfigurationContext;
import io.eguan.rest.container.RestContextPathConfigKey;
import io.eguan.rest.container.ServerAddressConfigKey;
import io.eguan.rest.container.ServerPortConfigKey;
import io.eguan.rest.container.ServletServer;
import io.eguan.rest.jaxrs.JaxRsAppContext;
import io.eguan.vold.adm.RestLauncher;
import io.eguan.vold.rest.generated.model.ObjectFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URI;
import javax.ws.rs.core.UriBuilder;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runners.model.InitializationError;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.xml.sax.SAXException;
/**
* Abstract superclass for fixture common to all resource tests.
*
* This includes all JMX-client configuration and starting the {@link ServletServer}.
*
* @author oodrive
* @author pwehrle
* @author ebredzinski
*
*/
public abstract class AbstractResourceTest extends AbstractJmxRemoteTest {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractResourceTest.class);
/**
* The JAXB-generated {@link ObjectFactory}.
*/
protected static ObjectFactory objectFactory;
protected static MetaConfiguration jettyConfig;
private static RestLauncher testLauncher;
private static final String DEFAULT_JETTY_CONFIG_RES = "/RestLauncher.properties";
private static final String DEFAULT_JAXRS_APP_RES = "/vold-adm.xml";
static String SERVER_BASE_URI = "http://localhost:8888/storage";
/**
* Sets up common static fixture.
*/
@BeforeClass
public static final void setUpClass() throws InitializationError {
objectFactory = new ObjectFactory();
try {
configureJaxRsXml(AbstractResourceTest.class.getResourceAsStream(DEFAULT_JAXRS_APP_RES), getJmxTestHelper()
.getServerUrl(), new File(AbstractResourceTest.class.getResource(DEFAULT_JAXRS_APP_RES).toURI()));
testLauncher = new RestLauncher();
assertNotNull(testLauncher);
assertFalse(testLauncher.isInitialized());
assertFalse(testLauncher.isStarted());
testLauncher.init();
assertTrue(testLauncher.isInitialized());
testLauncher.start();
assertTrue(testLauncher.isStarted());
final InputStream configInputStream = AbstractResourceTest.class
.getResourceAsStream(DEFAULT_JETTY_CONFIG_RES);
jettyConfig = MetaConfiguration
.newConfiguration(configInputStream, JettyConfigurationContext.getInstance());
final InetAddress host = ServerAddressConfigKey.getInstance().getTypedValue(jettyConfig);
final Integer port = ServerPortConfigKey.getInstance().getTypedValue(jettyConfig);
final String servletRoot = RestContextPathConfigKey.getInstance().getTypedValue(jettyConfig)
.replace("/*", "");
SERVER_BASE_URI = UriBuilder
.fromUri(new URI("http://" + host.getHostAddress() + ":" + port.toString() + "/"))
.path(servletRoot).build().toString();
}
catch (final Exception e) {
LOGGER.error("Setup threw exception", e);
throw new InitializationError(e);
}
}
/**
* Tears down common static fixture.
*
* @throws InitializationError
*/
@AfterClass
public static final void tearDownClass() throws InitializationError {
assert testLauncher != null;
try {
testLauncher.stop();
assert !testLauncher.isStarted();
}
catch (final Exception e) {
throw new InitializationError(e);
}
finally {
testLauncher.fini();
}
}
/**
* Injects the provided server URL as constructor parameter into an existing {@link XmlConfiguration} resource
* describing a {@link JaxRsAppContext} which includes a {@link VvrsResourceJmxImpl}.
*
* @param originalResource
* the original configuration
* @param serverUrl
* the URL to inject
* @return the altered configuration
* @throws InitializationError
* if anything goes wrong
*/
private static final void configureJaxRsXml(final InputStream originalResource, final String serverUrl,
final File destination) throws InitializationError {
try {
// parses the XML document
final DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document configDoc = docBuilder.parse(originalResource);
// selects and alters the node containing the server URL
final String xPathExpr = "//*/New[@class='" + VvrsResourceJmxImpl.class.getCanonicalName() + "']/Arg";
final XPath xpath = XPathFactory.newInstance().newXPath();
final Node target = (Node) xpath.evaluate(xPathExpr, configDoc, XPathConstants.NODE);
target.setTextContent(serverUrl);
// re-serializes the XML document and returns the result
final DOMImplementationLS domImpl = (DOMImplementationLS) DOMImplementationRegistry.newInstance()
.getDOMImplementation("LS");
final LSOutput lsOut = domImpl.createLSOutput();
lsOut.setEncoding(configDoc.getInputEncoding() == null ? configDoc.getInputEncoding() : "UTF-8");
final FileOutputStream outStream = new FileOutputStream(destination);
lsOut.setByteStream(outStream);
domImpl.createLSSerializer().write(configDoc, lsOut);
// TODO: make a nice little XSLT that keeps all the exceptions at bay!
}
catch (SAXException | ParserConfigurationException | IOException | XPathExpressionException
| ClassNotFoundException | InstantiationException | IllegalAccessException | ClassCastException e) {
throw new InitializationError(e);
}
}
}