package app; import static org.gcube.smartgears.Constants.configuration_file_path; import static org.gcube.smartgears.Constants.extensions_file_path; import static org.gcube.smartgears.Constants.ghn_home_property; import static org.gcube.smartgears.Constants.handlers_file_path; import static utils.TestUtils.context_root; import static utils.TestUtils.context_root_path; import static utils.TestUtils.location; import static utils.TestUtils.servlet_name; import java.io.File; import java.io.InputStream; import org.apache.catalina.Wrapper; import org.apache.catalina.core.StandardContext; import org.apache.catalina.startup.Tomcat; import org.apache.commons.io.FileUtils; import org.apache.tomcat.util.scan.StandardJarScanner; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.managers.ContainerManager; import org.gcube.smartgears.provider.ProviderFactory; import org.glassfish.jersey.client.ClientResponse; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.impl.base.path.BasicPath; import utils.TestProvider; import utils.TestUtils; /** * Simulates a single-servlet application to be transformed into a gCube resource. *
*
* Use only within a single test! */ public void dirtyRun() { this.clean = false; } /** * Returns the configuration of the application. *
* The initial configuration is based on defaults, but can be changed and extended. * * @return the configuration */ public ApplicationConfiguration configuration() { return configuration; } /** * Returns the configuration of the containerConfiguration. *
* The initial configuration is based on defaults, but can be changed and extended. * * @return the configuration */ public ContainerConfiguration containerConfiguration() { return containerConfiguration; } /** * Returns the handlers that manage the application, none by default. * * @return the handlers */ public ApplicationHandlers handlers() { return handlers; } /** * Avoids deployment of the configured handlers in the application's WAR. *
* The handlers will instead be directly available at runtime. */ public void bypassHandlerDeployment() { provider.use(handlers()); deployHandlers = false; } /** * Avoids resource configuration deployment. */ public void asExternal() { configuration.context(context_root_path); containerConfiguration.app(configuration); bypassConfigurationDeployment(); bypassExtensionsDeployment(); bypassHandlerDeployment(); } /** * Avoids resource configuration deployment. */ public void withExternal(ApplicationConfiguration config) { config.context(context_root_path); containerConfiguration.app(config.context()).merge(config); } public void bypassConfigurationDeployment() { deployConfiguration = false; } public void usePublisher(ScopedPublisher publisher) { provider.use(publisher); } /** * Uses default handlers. */ public void useDefaultHandlers() { deployHandlers = false; } /** * Returns the extensions of the application, none by default. * * @return the handlers */ public ApplicationExtensions extensions() { return extensions; } /** * Uses default extensions. */ public void useDefaultExtensions() { deployExtensions = false; } /** * Avoids deployment of the configured extensions in the application's WAR. *
* The extensions will instead be directly available at runtime.
*/
public void bypassExtensionsDeployment() {
provider.use(extensions());
deployExtensions = false;
}
/**
* Starts the application.
*
* @return the context of the application
*/
public ApplicationContext start() {
return startWith(new Runnable() {
@Override
public void run() {
System.err.println("test servlet invoked with no particular task");
}
});
}
/**
* Starts the application, injecting test logic in its single servlet
*
* @param test test logic
* @return the context of the application
*/
public ApplicationContext startWith(Runnable test) {
// install provider
ProviderFactory.testProvider(provider);
if (clean)
cleanupInstallation();
if (deployConfiguration)
deployConfiguration();
if (deployHandlers)
deployHandlers();
if (deployExtensions)
deployExtensions();
try {
System.err.println("deploying with " + war.toString(true));
StandardContext ctx = (StandardContext) tomcat.addWebapp(context_root_path, warFile().getAbsolutePath());
// tells tomcat to look also for exploded directories such as this project's (finds initializer)
((StandardJarScanner) ctx.getJarScanner()).setScanAllDirectories(true);
//this starts webapp and always comes back
tomcat.start();
ApplicationContext context = provider.context;
if (context==null)
throw new RuntimeException("app failed @ startup");
Wrapper webapp = (Wrapper) tomcat.getHost().findChild(context_root_path).findChild(servlet_name);
if (webapp!=null) {
webapp.setServlet(new TestServlet(test));
//context.container().configuration().port(port());
containerConfiguration = context.container().configuration();
}
return context;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Retuens true
if the application was successfully start in the container.
*
* @return true
if the application was successfully start in the container
*/
public boolean isActive() {
return tomcat.getHost().findChild("/" + context_root).findChild(servlet_name) != null;
}
/**
* Makes a request to the application.
*/
public String send(Request call) {
return (String) call.make(port()).getEntity();
}
/**
* Makes a request to the application.
*/
public ClientResponse httpSend(Request call) {
return call.make(port());
}
/**
* Stops the application
*/
public void stop() {
try {
tomcat.stop();
tomcat.destroy();
} catch (Exception e) {
System.err.println("WARNING: could not clearly stop container:");
e.printStackTrace();
}
}
public File containerConfigurationFile() {
return new File(location,Constants.container_configuraton_file_path);
}
// helpers
/**
* Includes the configuration in the application's WAR.
*/
private void deployConfiguration() {
String xml = TestUtils.bind(configuration());
System.err.println("deploying with configuration:\n" + xml);
war.addAsWebResource(new StringAsset(xml), new BasicPath(configuration_file_path));
}
/**
* Includes the handlers in the application's WAR.
*/
private void deployHandlers() {
String xml = TestUtils.bind(handlers());
System.err.println("deploying with handlers:\n" + xml);
war.addAsWebResource(new StringAsset(xml), new BasicPath(handlers_file_path));
}
/**
* Includes the extensions in the application's WAR.
*/
private void deployExtensions() {
String xml = TestUtils.bind(extensions());
System.err.println("deploying with extensions:\n" + xml);
war.addAsWebResource(new StringAsset(xml), new BasicPath(extensions_file_path));
}
private File warFile() {
File warFile = new File(location, "test.war");
if (warFile.exists() && !warFile.delete())
System.out.println("could not delete old deployment");; // seems safer than plain overwrite to avoid war corruption
war.as(ZipExporter.class).exportTo(warFile, true);
return warFile;
}
private WebArchive defaultWar() {
WebArchive war = ShrinkWrap.create(WebArchive.class);
war.setWebXML(new File("src/test/java/app/web.xml"));
return war;
}
private ApplicationConfiguration defaultConfiguration() {
return new DefaultApplicationConfiguration().serviceClass("test-class").name("test-app").version("1.0");
}
private ContainerConfiguration defaultContainerConfiguration() {
InputStream is = SomeApp.class.getResourceAsStream("/test-configuration.ini");
return ContainerConfiguration.load(is);
}
public int port() {
return tomcat.getConnector().getLocalPort();
}
private void cleanupInstallation() {
System.out.println("cleaning installation in location "+location);
File installation = new File(location);
if (installation.exists())
try {
FileUtils.deleteDirectory(installation);
}
catch(Exception e) {
throw new RuntimeException(e);
}
installation.mkdirs();
}
}