Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ignore server port change, ignore server state outside vscode #85

Merged
merged 4 commits into from
Jan 23, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ export enum ServerState {
RunningServer = 'runningserver',
IdleServer = 'idleserver'
}

export enum PortKind {
Server = 'Server',
Http = 'Http',
Https = 'Https'
}
59 changes: 31 additions & 28 deletions src/Tomcat/TomcatController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class TomcatController {

if (this._tomcat.deleteServer(tomcatServer)) {
const output: vscode.OutputChannel = this.getOutput(tomcatServer);
this._outputChannels.delete(this.getChannelName(tomcatServer));
this._outputChannels.delete(`Tomcat_${tomcatServer.getName()}`);
output.dispose();
}
vscode.commands.executeCommand('tomcat.tree.refresh');
Expand Down Expand Up @@ -233,7 +233,7 @@ export class TomcatController {
}

private async getServerUri(serverInfo: TomcatServer, appName?: string): Promise<string> {
const serverPort: string = await Utility.getHttpPort(serverInfo.getServerConfigPath());
const serverPort: string = await Utility.getPort(serverInfo.getServerConfigPath(), Constants.PortKind.Http);
if (!serverPort) {
throw new Error('No http port found in server.xml');
}
Expand All @@ -247,6 +247,10 @@ export class TomcatController {
const serverName: string = serverInfo.getName();
let watcher: chokidar.FSWatcher;
const serverUri: string = await this.getServerUri(serverInfo, appName);
const serverConfig: string = serverInfo.getServerConfigPath();
const serverPort: string = await Utility.getPort(serverConfig, Constants.PortKind.Server);
const httpPort: string = await Utility.getPort(serverConfig, Constants.PortKind.Http);
const httpsPort: string = await Utility.getPort(serverConfig, Constants.PortKind.Https);

try {
if (serverUri) {
Expand All @@ -260,57 +264,56 @@ export class TomcatController {
statusBar.show();
}

watcher = chokidar.watch(serverInfo.getServerConfigPath());
watcher = chokidar.watch(serverConfig);
watcher.on('change', async () => {
const promptString: string = localize('tomcatExt.configChanged',
'server.xml of running server {0} has been changed. Would you like to restart it?',
serverName);
const item: vscode.MessageItem = await vscode.window.showInformationMessage(promptString, DialogMessage.yes, DialogMessage.no);
if (item === DialogMessage.yes) {
try {
// Need restart tomcat
await this.stopServer(serverInfo);
serverInfo.needRestart = true;
} catch (err) {
console.error(err.toString());
vscode.window.showErrorMessage(localize('tomcatExt.stopFailure', 'Failed to stop Tomcat Server {0}', serverName));
if (serverPort !== await Utility.getPort(serverConfig, Constants.PortKind.Server)) {
vscode.window.showErrorMessage(localize('tomcatExt.serverPortChangeError', `Changing the server port of a running server will cause errors, please change it back to ${ serverPort} !`));
} else if (httpPort !== await Utility.getPort(serverConfig, Constants.PortKind.Http) ||
httpsPort !== await Utility.getPort(serverConfig, Constants.PortKind.Https)) {
const promptString: string = localize('tomcatExt.configChanged',
'server.xml of running server {0} has been changed. Would you like to restart it?',
serverName);
const item: vscode.MessageItem = await vscode.window.showInformationMessage(promptString, DialogMessage.yes, DialogMessage.no);
if (item === DialogMessage.yes) {
try {
// Need restart tomcat
await this.stopServer(serverInfo);
serverInfo.needRestart = true;
} catch (err) {
console.error(err.toString());
vscode.window.showErrorMessage(localize('tomcatExt.stopFailure', 'Failed to stop Tomcat Server {0}', serverName));
}
}
}
});

const javaProcess: Promise<void> = Utility.executeCMD(output, 'java', { shell: true }, ...this.getJavaArgs(serverInfo, true));
this.setStarted(serverInfo, true);
this.startDebugSession(serverInfo);
setTimeout(() => this.setStarted(serverInfo, true), 500);
await javaProcess;
this.setStarted(serverInfo, false);
this.disposeResource(statusBarCommand);
this.disposeResource(statusBar);
this.disposeResources(statusBarCommand, statusBar);
watcher.close();
if (serverInfo.needRestart) {
serverInfo.needRestart = false;
await this.startTomcat(serverInfo, appName, output);
}
} catch (err) {
this.setStarted(serverInfo, false);
this.disposeResource(statusBarCommand);
this.disposeResource(statusBar);
this.disposeResources(statusBarCommand, statusBar);
if (watcher) { watcher.close(); }
throw new Error(err.toString());
}
}

private disposeResource(resource: vscode.Disposable | undefined): void {
if (resource) {
resource.dispose();
private disposeResources(...resources: vscode.Disposable[]): void {
if (resources) {
resources.forEach((item: vscode.Disposable) => item.dispose());
}
}

private getChannelName(serverInfo: TomcatServer): string {
return `Tomcat_${serverInfo.getName()}`;
}

private getOutput(serverInfo: TomcatServer): vscode.OutputChannel {
const channelName: string = this.getChannelName(serverInfo);
const channelName: string = `Tomcat_${serverInfo.getName()}`;
let output: vscode.OutputChannel = this._outputChannels.get(channelName);
if (!output) {
output = vscode.window.createOutputChannel(channelName);
Expand Down
5 changes: 5 additions & 0 deletions src/TomcatServerTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export class TomcatSeverTreeProvider implements vscode.TreeDataProvider<TomcatSe

public async getTreeItem(element: TomcatServer): Promise<vscode.TreeItem> {
const treeItem: TomcatTreeItem = new TomcatTreeItem(this._context, element);
/* qisun: checking http port is not a valid way to detect the server running or not
// update the logic when finding a proper way to check the server real state
// currently behavior is ignoring the server state outside vscode
// and always stop servers when exiting vscode
try {
const port: string = await Utility.getHttpPort(treeItem.serverConfig);
// tslint:disable-next-line:no-any no-http-string
Expand All @@ -62,6 +66,7 @@ export class TomcatSeverTreeProvider implements vscode.TreeDataProvider<TomcatSe
} catch (err) {
element.setStarted(false);
}
*/
treeItem.iconPath = this._context.asAbsolutePath(path.join('resources', `${element.getState()}.svg`));
return treeItem;
}
Expand Down
29 changes: 24 additions & 5 deletions src/Utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import * as child_process from "child_process";
import * as fse from "fs-extra";
import * as net from "net";
import * as os from "os";
import * as path from "path";
import * as vscode from "vscode";
import * as xml2js from "xml2js";
Expand Down Expand Up @@ -59,7 +60,18 @@ export namespace Utility {
});
}

export async function getHttpPort(serverXml: string): Promise<string> | undefined {
export function getTempStoragePath(): string {
const chars: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
let result: string = '';
for (let i: number = 0; i < 5; i += 1) {
// tslint:disable-next-line:insecure-random
const idx: number = Math.floor(chars.length * Math.random());
result += chars[idx];
}
return path.resolve(os.tmpdir(), `vscodetomcat_${result}`);
}

export async function getPort(serverXml: string, kind: Constants.PortKind): Promise<string> {
if (!await fse.pathExists(serverXml)) {
throw new Error(localize('tomcatExt.noserver', 'No tomcat server.'));
}
Expand All @@ -68,15 +80,22 @@ export namespace Utility {
try {
/* tslint:disable:no-any */
const jsonObj: any = await parseXml(xml);
port = jsonObj.Server.Service.find((item: any) => item.$.name === Constants.CATALINA).Connector.find((item: any) =>
(item.$.protocol === undefined || item.$.protocol.startsWith(Constants.HTTP))).$.port;
if (kind === Constants.PortKind.Server) {
port = jsonObj.Server.$.port;
} else if (kind === Constants.PortKind.Http) {
port = jsonObj.Server.Service.find((item: any) => item.$.name === Constants.CATALINA).Connector.find((item: any) =>
(item.$.protocol === undefined || item.$.protocol.startsWith(Constants.HTTP))).$.port;
} else if (kind === Constants.PortKind.Https) {
port = jsonObj.Server.Service.find((item: any) => item.$.name === Constants.CATALINA).Connector.find((item: any) =>
(item.$.SSLEnabled.toLowerCase() === 'true')).$.port;
}
} catch (err) {
port = undefined;
}
return port;
}/* tslint:enable:no-any */

// tslint:disable-next-line:no-any
/* tslint:disable:no-any */
async function parseXml(xml: string): Promise<any> {
return new Promise((resolve: (obj: {}) => void, reject: (e: Error) => void): void => {
xml2js.parseString(xml, { explicitArray: true }, (err: Error, res: {}) => {
Expand All @@ -86,5 +105,5 @@ export namespace Utility {
return resolve(res);
});
});
}
}/* tslint:enable:no-any */
}
14 changes: 1 addition & 13 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import * as child_process from "child_process";
import * as fse from "fs-extra";
import * as os from "os";
import * as path from "path";
import * as vscode from "vscode";
import { MessageItem } from "vscode";
Expand All @@ -18,7 +17,7 @@ import { PickWithData, VSCodeUI } from "./VSCodeUI";
export function activate(context: vscode.ExtensionContext): void {
let storagePath: string = context.storagePath;
if (!storagePath) {
storagePath = path.resolve(os.tmpdir(), `vscodetomcat_${makeRandomHexString(5)}`);
storagePath = Utility.getTempStoragePath();
}
const outputChannel: vscode.OutputChannel = vscode.window.createOutputChannel('Tomcat');
const tomcatData: Tomcat = new Tomcat(storagePath);
Expand Down Expand Up @@ -196,14 +195,3 @@ async function runOnTomcat(tomcatController: TomcatController, debug: boolean, u

await tomcatController.runOnServer(tomcatController.getTomcatServer(server), packagePath, debug);
}

function makeRandomHexString(length: number): string {
const chars: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
let result: string = '';
for (let i: number = 0; i < length; i += 1) {
// tslint:disable-next-line:insecure-random
const idx: number = Math.floor(chars.length * Math.random());
result += chars[idx];
}
return result;
}
3 changes: 2 additions & 1 deletion test/utility.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as assert from "assert";
import * as path from "path";
import * as Constants from "../src/Constants";
import { TomcatServer } from "../src/Tomcat/TomcatServer";
import { Utility } from "../src/Utility";

Expand All @@ -15,7 +16,7 @@ suite('utility tests', () => {
test('getPort', async () => {
try {
const filePath: string = path.resolve(__dirname, '../../testResources/server.xml');
const port: string = await Utility.getHttpPort(filePath);
const port: string = await Utility.getPort(filePath, Constants.PortKind.Http);
assert.equal(port, '8081');
} catch (error) {
assert.fail('no error', 'error');
Expand Down