From ecb44f8efbc8967d11af1d4f9d61d7ddbbbeab4b Mon Sep 17 00:00:00 2001 From: Yan Zhang Date: Wed, 22 Nov 2017 16:55:43 +0800 Subject: [PATCH] support to generate project from maven archetype --- CHANGELOG.md | 6 +++++- package.json | 17 ++++++++++++++-- src/extension.ts | 23 +++++++++++++++++++++ src/mavenArchetype.ts | 16 +++++++++++++++ src/utils.ts | 47 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 src/mavenArchetype.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index c65234d..9426e66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ All notable changes to the "vscode-maven" extension will be documented in this f Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. -## [Unreleased] +## Unreleased +- Add context menu on `pom.xml`. +- Support maven archetype generate. + +## Released ### 0.0.6 - Run command in dedicated terminals for each maven project. diff --git a/package.json b/package.json index 0de30ad..cdfa0ee 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,16 @@ "command": "mavenProject.openPom", "title": "Open POM file", "category": "Maven" + }, + { + "command": "mavenArchetype.generate", + "title": "Generate from Maven Archetype", + "category": "Maven" + }, + { + "command": "mavenArchetype.updateCache", + "title": "Update Maven Archetype Catalog", + "category": "Maven" } ], "views": { @@ -111,7 +121,10 @@ "menus": { "explorer/context": [ { - "command": "mavenArchetype.generate" + "command": "mavenArchetype.generate" + }, + { + "command": "mavenArchetype.updateCache" }, { "command": "mavenProject.effectivePom", @@ -225,4 +238,4 @@ "readdirp": "^2.1.0", "xml2js": "^0.4.19" } -} +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index cdd6598..a02c3ce 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -87,6 +87,27 @@ export function activate(context: vscode.ExtensionContext) { }); }); + let commandMavenArchetypeGenerate = vscode.commands.registerCommand("mavenArchetype.generate", () => { + vscode.window.showWorkspaceFolderPick().then(ret => { console.log(ret); }); + const archetypeList = Utils.getArchetypeList(); + vscode.window.showQuickPick(archetypeList, { matchOnDescription: true }).then(selected => { + if (selected) { + const { artifactId, groupId } = selected; + vscode.window.showQuickPick(selected.versions).then(version => { + if (version) { + Utils.runInTerminal(`mvn archetype:generate -DarchetypeArtifactId=${artifactId} -DarchetypeGroupId=${groupId} -DarchetypeVersion=${version}`, true, 'Maven'); + } + }); + } + }); + }); + + let commandMavenArchetypeUpdateCache = vscode.commands.registerCommand("mavenArchetype.updateCache", () => { + vscode.window.showInputBox({ value: "http://repo.maven.apache.org/maven2/archetype-catalog.xml" }).then(url => { + vscode.window.setStatusBarMessage("Updating archetype catalog ... ", Utils.updateArchetypeCache(url)); + }); + }); + ['clean', 'validate', 'compile', 'test', 'package', 'verify', 'install', 'site', 'deploy'].forEach(goal => { let commandMavenGoal = vscode.commands.registerCommand(`mavenGoal.${goal}`, (goalItem) => { const item = goalItem as MavenProjectTreeItem; @@ -99,6 +120,8 @@ export function activate(context: vscode.ExtensionContext) { context.subscriptions.push(commandMavenGoalExecute); context.subscriptions.push(commandMavenProjectEffectivePom); context.subscriptions.push(commandMavenProjectOpenPom); + context.subscriptions.push(commandMavenArchetypeGenerate); + context.subscriptions.push(commandMavenArchetypeUpdateCache); } // this method is called when your extension is deactivated diff --git a/src/mavenArchetype.ts b/src/mavenArchetype.ts new file mode 100644 index 0000000..87e69be --- /dev/null +++ b/src/mavenArchetype.ts @@ -0,0 +1,16 @@ +import * as vscode from "vscode"; +import { QuickPickItem } from "vscode"; +export class MavenArchetype implements QuickPickItem { + label: string; + description: string; + artifactId: string; + groupId: string; + versions: string[]; + constructor(aid: string, gid: string, desc?: string) { + this.artifactId = aid; + this.groupId = gid; + this.versions = []; + this.label = `${gid}:${aid}`; + this.description = desc; + } +} \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index fe9f721..cc4ead2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,11 +1,14 @@ import * as vscode from "vscode"; import { execSync } from 'child_process'; import * as fs from 'fs'; +import * as http from 'http'; import * as os from 'os'; import * as md5 from "md5"; import * as path from 'path'; import * as xml2js from 'xml2js'; import { MavenProjectTreeItem } from "./mavenProjectTreeItem"; +import { MavenArchetype } from "./mavenArchetype"; +import { existsSync } from "fs"; @@ -105,6 +108,50 @@ export class Utils { return path.join(os.tmpdir(), "vscode-maven", md5(pomXmlFilePath), 'commandHistory.txt'); } + static getArchetypeList(): MavenArchetype[] { + const localArchetypeXmlFilePath = this.getLocalArchetypeCatalogFilePath(); + if (existsSync(localArchetypeXmlFilePath)) { + const xml = fs.readFileSync(localArchetypeXmlFilePath, 'utf8'); + let catalog = null; + xml2js.parseString(xml, { explicitArray: false }, (err, res) => { catalog = res; }); + if (catalog && catalog['archetype-catalog'] && catalog['archetype-catalog'].archetypes) { + let dict: { [key: string]: MavenArchetype } = {}; + catalog['archetype-catalog'].archetypes.archetype.forEach(archetype => { + const identifier = `${archetype.groupId}:${archetype.artifactId}`; + if (!dict[identifier]) { + dict[identifier] = new MavenArchetype(archetype.artifactId, archetype.groupId, archetype.description); + } + if (dict[identifier].versions.indexOf(archetype.version) < 0) { + dict[identifier].versions.push(archetype.version); + } + }); + return Object.keys(dict).map(k => dict[k]); + } + } + return []; + } + public static getLocalArchetypeCatalogFilePath(): string { + return path.join(os.homedir(), ".m2", "repository", "archetype-catalog.xml"); + } + + public static updateArchetypeCache(url: string): Promise { + const filepath = this.getLocalArchetypeCatalogFilePath(); + this.mkdirp(path.dirname(filepath)); + const file = fs.createWriteStream(filepath); + let ret = new Promise((resolve, reject) => { + const request = http.get(url, (response) => { + response.pipe(file); + response.on("end", () => { + resolve(); + }); + }); + request.on("error", e => { + reject(); + }); + }); + return ret; + } + private static mkdirp(filepath) { if (fs.existsSync(filepath)) { return;