quicksilver-cli
Version:
Cli tool for Quicksilver
290 lines (289 loc) • 12 kB
JavaScript
;
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const system_1 = require("./system");
const placeholder_1 = require("./placeholder");
const environment_1 = require("./environment");
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const http = __importStar(require("http"));
const fs = __importStar(require("fs"));
const unzip = require("unzip");
const { spawn } = require('child_process');
const log4js = require("log4js");
const glob = require("glob");
const targz = require('targz');
const tomcat = require("../resources/tomcat/tomcat.json");
async function initTomcat(projectPath, tomcatHome) {
const tomcatPath = tomcatHome != null && tomcatHome.trim() != "" ? path.resolve(projectPath, tomcatHome) : projectPath;
try {
return getTomcatHome(tomcatPath);
}
catch (_) {
const extractPath = /tomcat/.test(path.basename(tomcatPath)) ? path.dirname(tomcatPath) : tomcatPath;
return await extractTomcatFromCacheOrRemote(extractPath);
}
}
exports.initTomcat = initTomcat;
async function extractTomcatFromCacheOrRemote(extractPath) {
const tomcatExtName = getTomcatExtName(tomcat.url);
const tomcatZips = glob.sync(path.join(os.tmpdir(), `@(apache-tomcat*${tomcatExtName})`), { "nodir": true });
let localTomcatZip;
if (tomcatZips.length == 0) {
const version = await getTomcatVersionFromRemote();
localTomcatZip = await downloadTomcatZip(version);
}
else {
localTomcatZip = tomcatZips[tomcatZips.length - 1];
}
return await unpackTomcatZip(localTomcatZip, extractPath);
}
exports.extractTomcatFromCacheOrRemote = extractTomcatFromCacheOrRemote;
function getTomcatExtName(tomcat) {
return /(\.|[a-z])+$/.exec(tomcat)[0];
}
exports.getTomcatExtName = getTomcatExtName;
async function getTomcatVersionFromRemote() {
const logger = log4js.getLogger("tomcat");
return new Promise((resolve, reject) => {
logger.info("Getting tomcat latest version.");
http.get(tomcat.versionUrl, (res) => {
const { statusCode } = res;
if (statusCode !== 200) {
reject(`Get tomcat latest version error, statusCode=${statusCode}`);
return;
}
let rawData = '';
res.on("data", (data) => {
rawData += data;
});
res.on("end", () => {
logger.debug(`Latest tomcat version xml:\n ${rawData}`);
const version = /v(\d+\.)+\d+/.exec(rawData)[0];
logger.info(`Latest tomcat version : ${version}`);
resolve(version.substring(1));
});
}).on('error', (err) => {
reject(err);
});
});
}
exports.getTomcatVersionFromRemote = getTomcatVersionFromRemote;
async function downloadTomcatZip(version) {
const logger = log4js.getLogger("tomcat");
return new Promise((resolve, reject) => {
let tomcatUrl = /^http/.test(tomcat.url) ? tomcat.url : tomcat.versionUrl + tomcat.url;
if (version != null) {
tomcatUrl = placeholder_1.replace(tomcatUrl, { "version": version });
}
logger.info(`Downloading tomcat: tomcatUrl=${tomcatUrl}`);
http.get(tomcatUrl, (res) => {
const { statusCode } = res;
if (statusCode !== 200) {
reject(`Downloaded tomcat zip error, statusCode=${statusCode}`);
return;
}
const tomcatName = path.basename(tomcatUrl);
const tomcatZip = path.join(os.tmpdir(), tomcatName);
const stream = fs.createWriteStream(tomcatZip);
res.on("data", (data) => {
stream.write(data);
});
res.on("end", () => {
logger.info(`Downloaded tomcat '${tomcatZip}'.\n`);
resolve(tomcatZip);
});
}).on('error', (err) => {
reject(err);
});
});
}
exports.downloadTomcatZip = downloadTomcatZip;
async function unpackTomcatZip(from, to) {
const logger = log4js.getLogger("tomcat");
const tomcatExtName = getTomcatExtName(from);
const tomcatDir = path.basename(from, tomcatExtName);
const tomcatHome = path.join(to, tomcatDir);
return new Promise((resolve, reject) => {
logger.info(`Unpacking tomcat from '${from}' to '${to}' ...`);
if (/\.tar\.gz/.test(from)) {
targz.decompress({ src: from, dest: to }, err => {
if (err) {
reject(`Unpack tomcat Error: ${err.message}`);
}
else {
logger.info(`Has Unpacked tomcat.`);
resolve(tomcatHome);
}
});
}
else if (/\.zip/.test(from)) {
const stream = fs.createReadStream(from);
stream.pipe(unzip.Extract({ path: to }));
stream.on("end", () => {
logger.info(`Has Unpacked tomcat.`);
resolve(tomcatHome);
});
stream.on('error', (e) => {
reject(`Unpacked tomcat Error: ${e.message}`);
});
}
});
}
exports.unpackTomcatZip = unpackTomcatZip;
async function clearAppDir(tomcatHome, ignores) {
const logger = log4js.getLogger("tomcat");
ignores = ignores || [];
const appDir = path.join(tomcatHome, "webapps");
let ignoreFiles = ["docs", "examples", "host-manager", "manager", "ROOT", ...ignores];
const deleteFiles = fs.readdirSync(appDir)
.filter(file => !ignoreFiles.includes(file))
.map(file => path.join(appDir, file));
for (let file of deleteFiles) {
try {
remove(file);
}
catch (e) {
logger.error(`Deleted ${file} failed.`);
}
}
}
exports.clearAppDir = clearAppDir;
function remove(fileOrDir) {
if (fs.existsSync(fileOrDir)) {
if (fs.lstatSync(fileOrDir).isDirectory()) {
fs.readdirSync(fileOrDir).forEach(file => remove(path.join(fileOrDir, file)));
fs.rmdirSync(fileOrDir);
}
else {
fs.unlinkSync(fileOrDir);
}
}
}
async function addCommentsToLoggingEncoding(tomcatHome) {
const filePath = path.join(tomcatHome, "conf", "logging.properties");
const items = [
"1catalina.org.apache.juli.AsyncFileHandler.encoding",
"2localhost.org.apache.juli.AsyncFileHandler.encoding",
"3manager.org.apache.juli.AsyncFileHandler.encoding",
"4host-manager.org.apache.juli.AsyncFileHandler.encoding",
"java.util.logging.ConsoleHandler.encoding"
];
const properties = fs.readFileSync(filePath, { encoding: "utf8" });
const regExp = new RegExp(items.map(item => item.replace(/\./g, "\\.")).join("|"));
const newProperties = properties
.split("\n")
.map(item => item.startsWith("#") ? item : regExp.test(item) ? `#${item}` : item)
.join("\n");
if (newProperties != properties) {
fs.writeFileSync(filePath, newProperties);
}
}
exports.addCommentsToLoggingEncoding = addCommentsToLoggingEncoding;
function getTomcatHome(dir) {
const catalinaFiles = glob.sync(path.join(dir, '**/bin/catalina.*'));
if (catalinaFiles.length > 0) {
return path.dirname(path.dirname(catalinaFiles[0]));
}
throw new Error(`can not find tomcat home from ${dir}`);
}
exports.getTomcatHome = getTomcatHome;
async function copyWar(runProjectPath, tomcatHome) {
const logger = log4js.getLogger("tomcat");
logger.info("Copying war...");
const runProjectName = path.basename(runProjectPath);
const rootProjectPath = path.dirname(runProjectPath);
const rootProjectName = path.basename(rootProjectPath);
const prefix = `${rootProjectName}-run-`;
const contextPath = runProjectName.startsWith(prefix) ? runProjectName.substring(prefix.length) : rootProjectName;
const warDir = path.join(runProjectPath, "build", "libs");
const files = fs.readdirSync(warDir);
const runWarRegExp = new RegExp(`${runProjectName}.*\.war`);
const warFile = files.filter(file => runWarRegExp.test(file))[0];
const dest = path.join(tomcatHome, "webapps", `${contextPath}.war`);
fs.copyFileSync(path.join(warDir, warFile), dest);
logger.info(`Copied war to ${dest}. `);
return dest;
}
exports.copyWar = copyWar;
async function runCommand(tomcatHome, command, args, options) {
const logger = log4js.getLogger(`tomcat-${command}`);
return new Promise((resolve, reject) => {
logger.info(`Executing tomcat command '${command}'...`);
const commandName = system_1.isWindows ? `${command}.bat` : `./${command}.sh`;
options = Object.assign({ cwd: path.join(tomcatHome, "bin") }, options);
if (args == null) {
args = [];
}
const runCommand = spawn(commandName, args, options);
if (runCommand.stdout) {
runCommand.stdout.on(data => logger.debug(`${data}`));
}
if (runCommand.stderr) {
runCommand.stderr.on(data => logger.error(`${data}`));
}
runCommand.on('close', (code) => {
if (code == 0) {
logger.info(`Completed tomcat command '${command}'...`);
resolve("success");
}
else {
reject(`Executing tomcat command '${command}' with errors: Code=${code}`);
}
});
runCommand.on("error", err => {
reject(err);
});
});
}
exports.runCommand = runCommand;
async function shutdown(tomcatHome) {
try {
await runCommand(tomcatHome, "shutdown", [], { stdio: ["inherit", "inherit", "ignore"] });
}
catch (e) {
}
}
exports.shutdown = shutdown;
async function modifyPort(tomcatHome, port) {
const logger = log4js.getLogger("tomcat");
logger.info(`Modifying tomcat port, tomcatHome=${tomcatHome}, port=${port}.`);
const serverXml = path.join(tomcatHome, "/conf/server.xml");
const data = fs.readFileSync(serverXml, 'utf8');
let regExp = /<Connector[^>]*HTTP\/1\.1[^>]*>/;
let result = regExp.exec(data);
if (result != null) {
let input = result[0];
let rInput = input.replace(/port[\s]*=[\s]*"[0-9]+"/, `port="${port}"`);
let newData = data.replace(input, rInput);
fs.writeFileSync(serverXml, newData);
logger.info("Modified tomcat port success.");
}
}
exports.modifyPort = modifyPort;
async function addCommentToAjpConnector(tomcatHome) {
const serverXml = path.join(tomcatHome, "/conf/server.xml");
const data = fs.readFileSync(serverXml, 'utf8');
let regExp = /<!--[^(-->)]+<Connector[^>]*AJP\/1\.3[^>]*>/;
if (!regExp.test(data)) {
regExp = /<Connector[^>]*AJP\/1\.3[^>]*>/;
const result = regExp.exec(data);
if (result != null) {
let input = result[0];
const newData = data.replace(input, `<!-- ${input} -->`);
fs.writeFileSync(serverXml, newData);
}
}
}
exports.addCommentToAjpConnector = addCommentToAjpConnector;
async function runCatalina(rootProjectPath, tomcatHome) {
const env = await environment_1.getEnv(rootProjectPath, "tomcat", { "TomcatHome": tomcatHome });
return await runCommand(tomcatHome, "catalina", ["run"], { env: env, stdio: "inherit" });
}
exports.runCatalina = runCatalina;