/*******************************************************************************
* Copyright (c) 2012-2015 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.runner.webapps;
import org.eclipse.che.api.core.notification.EventService;
import org.eclipse.che.api.runner.RunnerException;
import org.eclipse.che.api.runner.internal.ApplicationLogger;
import org.eclipse.che.api.runner.internal.DeploymentSources;
import org.eclipse.che.commons.lang.IoUtil;
import org.eclipse.che.commons.lang.ZipUtils;
import com.google.common.io.CharStreams;
import com.google.inject.Singleton;
import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
/**
* Abstract base implementation to deploy application to Apache Tomcat servlet container.
*
* @author Artem Zatsarynnyy
* @author Roman Nikitenko
*/
@Singleton
public abstract class BaseTomcatServer implements ApplicationServer {
public static final String TOMCAT_HOME_PARAMETER = "runner.tomcat.tomcat_home";
public static final String MEM_SIZE_PARAMETER = "runner.tomcat.memory";
protected static final String SERVER_XML =
"<?xml version='1.0' encoding='utf-8'?>\n" +
"<Server port=\"-1\">\n" +
" <Listener className=\"org.apache.catalina.core.AprLifecycleListener\" SSLEngine=\"on\" />\n" +
" <Listener className=\"org.apache.catalina.core.JasperListener\" />\n" +
" <Listener className=\"org.apache.catalina.core.JreMemoryLeakPreventionListener\" />\n" +
" <Listener className=\"org.apache.catalina.mbeans.GlobalResourcesLifecycleListener\" />\n" +
" <Listener className=\"org.apache.catalina.core.ThreadLocalLeakPreventionListener\" />\n" +
" <Service name=\"Catalina\">\n" +
" <Connector port=\"${PORT}\" protocol=\"HTTP/1.1\"\n" +
" connectionTimeout=\"20000\" />\n" +
" <Engine name=\"Catalina\" defaultHost=\"localhost\">\n" +
" <Host name=\"localhost\" appBase=\"webapps\"\n" +
" unpackWARs=\"true\" autoDeploy=\"true\">\n" +
" </Host>\n" +
" </Engine>\n" +
" </Service>\n" +
"</Server>\n";
protected final int memSize;
protected final File tomcatHome;
protected final EventService eventService;
@Inject
public BaseTomcatServer(@Named(MEM_SIZE_PARAMETER) int memSize,
@Named(TOMCAT_HOME_PARAMETER) File tomcatHome,
EventService eventService) {
this.memSize = memSize;
this.tomcatHome = tomcatHome;
this.eventService = eventService;
}
@Override
public final String getName() {
return "tomcat7";
}
@Override
public String getDescription() {
return "Apache Tomcat 7.0 is an implementation of the Java Servlet and JavaServer Pages technologies.\n" +
"Home page: http://tomcat.apache.org/";
}
protected void generateServerXml(File tomcatDir, ApplicationServerRunnerConfiguration runnerConfiguration) throws IOException {
final String cfg = SERVER_XML.replace("${PORT}", Integer.toString(runnerConfiguration.getHttpPort()));
final File serverXmlFile = new File(new File(tomcatDir, "conf"), "server.xml");
Files.write(serverXmlFile.toPath(), cfg.getBytes());
}
public File getTomcatHome() {
return tomcatHome;
}
public int getMemSize() {
return memSize;
}
@Override
public String toString() {
return "Tomcat Server";
}
protected void prepare(File appDir, DeploymentSources toDeploy, ApplicationServerRunnerConfiguration runnerConfiguration)
throws RunnerException {
final File myTomcatHome = getTomcatHome();
try {
final Path tomcatPath = Files.createDirectory(appDir.toPath().resolve("tomcat"));
IoUtil.copy(myTomcatHome, tomcatPath.toFile(), null);
final Path webappsPath = tomcatPath.resolve("webapps");
if (Files.exists(webappsPath)) {
IoUtil.deleteRecursive(webappsPath.toFile());
}
Files.createDirectory(webappsPath);
final Path rootPath = Files.createDirectory(webappsPath.resolve("ROOT"));
if (toDeploy.isZipArchive()) {
ZipUtils.unzip(toDeploy.getFile(), rootPath.toFile());
} else {
IoUtil.copy(toDeploy.getFile(), rootPath.toFile(), null);
}
generateServerXml(tomcatPath.toFile(), runnerConfiguration);
} catch (IOException e) {
throw new RunnerException(e);
}
}
protected static class TomcatLogger implements ApplicationLogger {
final List<File> logFiles;
TomcatLogger(List<File> logFiles) {
this.logFiles = logFiles;
}
@Override
public void getLogs(Appendable output) throws IOException {
for (File logFile : logFiles) {
output.append(String.format("%n====> %1$s <====%n%n", logFile.getName()));
try (FileReader r = new FileReader(logFile)) {
CharStreams.copy(r, output);
}
output.append(System.lineSeparator());
}
}
@Override
public String getContentType() {
return "text/plain";
}
@Override
public void writeLine(String line) throws IOException {
// noop since logs already redirected to the file
}
@Override
public void close() throws IOException {
}
}
}