/******************************************************************************* * 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 { } } }