blob: 0032906fe0288df91db172249956e259136c3232 [file]
/**
* 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.
*/
package org.apache.pulsar.manager;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.servlet.ServletException;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Context;
import org.apache.catalina.loader.WebappLoader;
import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* Customize Tomcat Service
*/
@Component
@Slf4j
public class EmbeddedTomcatCustomizer implements
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
log.info("Starting Tomcat Customizer");
}
@Bean
public ServletWebServerFactory servletContainer() {
log.info("Starting servletContainer");
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
try {
log.info("Catalina base is " + tomcat.getServer().getCatalinaBase().getAbsolutePath());
File lib = new File("lib").getAbsoluteFile();
if (lib.isDirectory()) {
File bkvmWar = searchWar(lib, "bkvm", ".war");
if (bkvmWar != null) {
File configFile = new File("bkvm.conf");
log.info("looking for BKVM configuration file at " + configFile.getAbsolutePath());
if (configFile.isFile()) {
Properties props = new Properties();
try (FileReader reader = new FileReader(configFile)) {
props.load(reader);
}
boolean bkvmEnabled = Boolean.parseBoolean(props.getProperty("bkvm.enabled", "false"));
log.info("Read bkvm.enabled = {}", bkvmEnabled);
if (bkvmEnabled) {
System.setProperty("bookkeeper.visual.manager.config.path", configFile.getAbsolutePath());
File file = new File(tomcat.getServer().getCatalinaBase(), "/webapps");
log.info("Tomcat Webapps directory is " + file.getAbsolutePath());
file.mkdirs();
File bkvmDirectory = new File(file, "bkvm");
log.info("Deploying BKVM to " + bkvmDirectory.getAbsolutePath());
unZip(bkvmWar, bkvmDirectory);
Context context = tomcat.addWebapp("/bkvm", bkvmDirectory.getAbsolutePath());
WebappLoader loader = new WebappLoader(Thread.currentThread().getContextClassLoader());
context.setLoader(loader);
}
}
}
}
return super.getTomcatWebServer(tomcat);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
};
}
private static File searchWar(File directory, String prefix, String ext) throws IOException {
log.info("looking for " + prefix + " into " + directory.getAbsolutePath());
Path path = directory.toPath();
try (DirectoryStream<Path> list = Files.newDirectoryStream(path);) {
for (Path o : list) {
if (o.getFileName().toString().startsWith(prefix) && o.getFileName().toString().endsWith(ext)) {
return o.toFile();
}
}
}
log.info("Cannot find any file whose name starts with " + prefix + " into " + directory.getAbsolutePath());
return null;
}
public static List<File> unZip(File war, File outDir) throws IOException {
log.info("Unzipping " + war.getAbsolutePath() + " to " + outDir);
try (ZipInputStream zipStream = new ZipInputStream(new FileInputStream(war), StandardCharsets.UTF_8);) {
ZipEntry entry = zipStream.getNextEntry();
List<File> listFiles = new ArrayList<>();
while (entry != null) {
if (entry.isDirectory()) {
entry = zipStream.getNextEntry();
continue;
}
String normalized = entry.getName();
File outFile = new File(outDir, normalized);
File parentDir = outFile.getParentFile();
if (parentDir != null && !parentDir.isDirectory()) {
Files.createDirectories(parentDir.toPath());
}
listFiles.add(outFile);
try (FileOutputStream out = new FileOutputStream(outFile);
BufferedOutputStream oo = new BufferedOutputStream(out)) {
copyStream(zipStream, oo);
}
entry = zipStream.getNextEntry();
}
return listFiles;
} catch (IllegalArgumentException ex) {
throw new IOException(ex);
}
}
private static long copyStream(InputStream input, OutputStream output) throws IOException {
long count = 0;
int n = 0;
byte[] buffer = new byte[64 * 1024];
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
}