UNPKG

quicksilver-cli

Version:
290 lines (289 loc) 12 kB
"use strict"; 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;