import * as fse from "fs-extra" ; import * as http from "http" ; import * as https from "https" ; import * as md5 from "md5" ; import * as path from "path" ; import * as url from "url" ; import { commands , Progress , ProgressLocation , RelativePattern , Uri , window , workspace , WorkspaceFolder } from "vscode" ; import { createUuid , setUserError } from "vscode-extension-telemetry-wrapper" ; import * as xml2js from "xml2js" ; import { mavenExplorerProvider } from "../explorer/mavenExplorerProvider" ; import { LifecyclePhase } from "../explorer/model/LifecyclePhase" ; import { MavenProject } from "../explorer/model/MavenProject" ; import { Settings } from "../Settings" ; import { getExtensionVersion , getPathToTempFolder , getPathToWorkspaceStorage } from "./contextUtils" ; import { MavenNotFoundError } from "./errorUtils" ; import { getLRUCommands , ICommandHistoryEntry } from "./historyUtils" ; import { executeInTerminal , getMaven , pluginDescription , rawEffectivePom } from "./mavenUtils" ; import { effectivePomContentUri , selectProjectIfNecessary } from "./uiUtils" ; export namespace Utils { export async function parseXmlFile ( xmlFilePath , options ? ) { if ( await fse . pathExists ( xmlFilePath ) ) { const xmlString = await fse . readFile ( xmlFilePath , "utf8" ) ; return parseXmlContent ( xmlString , options ) ; } else { return undefined ; } } export async function parseXmlContent ( xmlString , options ? ) { const opts = Object . assign ( { explicitArray : true } , options ) ; return new Promise < { } > ( ( resolve , reject ) : void => { xml2js . parseString ( xmlString , opts , ( err , res ) => { if ( err !== null ) { reject ( err ) ; } else { resolve ( res ) ; } } ) ; } ) ; } function getTempOutputPath ( key ) { const pathInWorkspaceFolder = getPathToWorkspaceStorage ( md5 ( key ) , createUuid ( ) ) ; if ( pathInWorkspaceFolder !== undefined ) { return pathInWorkspaceFolder ; } else { return getPathToTempFolder ( md5 ( key ) , createUuid ( ) ) ; } } export async function downloadFile ( targetUrl , readContent ? , customHeaders ? ) { const tempFilePath = getTempOutputPath ( targetUrl ) ; await fse . ensureFile ( tempFilePath ) ; return await new Promise ( ( resolve , reject ) : void => { const urlObj = url . parse ( targetUrl ) ; const options = Object . assign ( { headers : Object . assign ( { } , customHeaders , { "User-Agent" : `vscode/${ getExtensionVersion ( ) }` } ) } , urlObj ) ; let client ; if ( urlObj . protocol === "https:" ) { client = https ; } else if ( urlObj . protocol === "http:" ) { client = http ; } else { reject ( new Error ( "Unsupported protocol." ) ) ; return ; } client . get ( options , ( res ) => { let rawData ; let ws ; if ( readContent ) { rawData = "" ; } else { ws = fse . createWriteStream ( tempFilePath ) ; } res . on ( "data" , ( chunk ) => { if ( readContent ) { rawData += chunk ; } else { ws . write ( chunk ) ; } } ) ; res . on ( "end" , ( ) => { if ( readContent ) { resolve ( rawData ) ; } else { ws . end ( ) ; resolve ( tempFilePath ) ; } } ) ; } ) . on ( "error" , ( err ) => { reject ( err ) ; } ) ; } ) ; } export async function getAllPomPaths ( workspaceFolder ? ) { if ( ! workspaceFolder ) { if ( workspace . workspaceFolders ) { const arrayOfPoms = await Promise . all ( workspace . workspaceFolders . map ( getAllPomPaths ) ) ; return [ ] . concat . apply ( [ ] , arrayOfPoms ) ; } else { return [ ] ; } } const exclusions = Settings . excludedFolders ( workspaceFolder . uri ) ; const pattern = Settings . Pomfile . globPattern ( ) ; const pomFileUris = await workspace . findFiles ( new RelativePattern ( workspaceFolder , pattern ) , `{${ exclusions . join ( "," ) }}` ) ; return pomFileUris . map ( _uri => _uri . fsPath ) ; } export async function showEffectivePom ( param ) { let pomPath ; if ( typeof param === "string" ) { pomPath = param ; } else if ( typeof param === "object" && param instanceof MavenProject ) { pomPath = param . pomPath ; } else if ( typeof param === "object" && param instanceof Uri ) { pomPath = param . fsPath ; } if ( ! pomPath ) { throw new Error ( "Corresponding pom.xml file not found." ) ; } const mvn = await getMaven ( pomPath ) ; if ( mvn === undefined ) { throw new MavenNotFoundError ( ) ; } const uri = effectivePomContentUri ( pomPath ) ; await window . showTextDocument ( uri ) ; } export async function getEffectivePom ( pomPathOrMavenProject ) { let pomPath ; let name ; if ( typeof pomPathOrMavenProject === "object" && pomPathOrMavenProject instanceof MavenProject ) { const mavenProject = pomPathOrMavenProject ; pomPath = mavenProject . pomPath ; name = mavenProject . name ; } else if ( typeof pomPathOrMavenProject === "string" ) { pomPath = pomPathOrMavenProject ; name = pomPath ; } else { return undefined ; } return await window . withProgress ( { location : ProgressLocation . Notification } , async ( p ) => new Promise < string > ( async ( resolve , reject ) : Promise < void > => { p . report ( { message : `Generating Effective POM: ${ name }` } ) ; try { const ret = await rawEffectivePom ( pomPath ) ; resolve ( ret ? ret : "" ) ; } catch ( error ) { setUserError ( error ) ; reject ( error ) ; } } ) ) ; } export async function getPluginDescription ( pluginId , pomPath ) { return await window . withProgress ( { location : ProgressLocation . Window } , async ( p ) => new Promise < string > ( async ( resolve , reject ) : Promise < void > => { p . report ( { message : `Retrieving Plugin Info: ${ pluginId }` } ) ; try { const ret = await pluginDescription ( pluginId , pomPath ) ; resolve ( ret ? ret : "" ) ; } catch ( error ) { setUserError ( error ) ; reject ( error ) ; } } ) ) ; } export async function executeCustomGoal ( pomOrProject ) { let pomPath ; if ( typeof pomOrProject === "string" ) { pomPath = pomOrProject ; } else if ( typeof pomOrProject === "object" && pomOrProject instanceof MavenProject ) { pomPath = pomOrProject . pomPath ; } if ( ! pomPath ) { return ; } const inputGoals = await window . showInputBox ( { placeHolder : "e.g. clean package -DskipTests" , ignoreFocusOut : true } ) ; const trimmedGoals = inputGoals ? inputGoals . trim ( ) : undefined ; if ( trimmedGoals ) { await executeInTerminal ( { command : trimmedGoals , pomfile : pomPath } ) ; } } export async function executeHistoricalGoals ( projectPomPaths ) { const candidates = Array . prototype . concat . apply ( [ ] , await Promise . all ( projectPomPaths . map ( getLRUCommands ) ) ) as ICommandHistoryEntry [ ] ; candidates . sort ( ( a , b ) => b . timestamp - a . timestamp ) ; const selected = await window . showQuickPick ( candidates . map ( item => ( { value : item , label : item . command , description : undefined , detail : item . pomPath } ) ) , { placeHolder : "Select from history ..." , ignoreFocusOut : true } ) . then ( item => item ? item . value : undefined ) ; if ( selected ) { await executeInTerminal ( { command : selected . command , pomfile : selected . pomPath } ) ; } } export async function executeMavenCommand ( node ? ) { let selectedProject ; let selectedCommand ; if ( node instanceof LifecyclePhase ) { selectedProject = node . project ; selectedCommand = node . phase ; } else if ( node && node . uri ) { const pomPath = path . join ( Uri . parse ( node . uri ) . fsPath , "pom.xml" ) ; selectedProject = mavenExplorerProvider . mavenProjectNodes . find ( project => project . pomPath . toLowerCase ( ) === pomPath . toLowerCase ( ) ) ; } if ( ! selectedProject ) { selectedProject = await selectProjectIfNecessary ( ) ; } if ( ! selectedProject ) { return ; } if ( ! selectedCommand ) { const LABEL_CUSTOM = "Custom ..." ; const LABEL_FAVORITES = "Favorites ..." ; selectedCommand = await window . showQuickPick ( [ LABEL_FAVORITES , LABEL_CUSTOM , "clean" , "validate" , "compile" , "test" , "package" , "verify" , "install" , "site" , "deploy" ] , { placeHolder : "Select the goal to execute ..." , ignoreFocusOut : true } ) ; if ( ! selectedCommand ) { return ; } switch ( selectedCommand ) { case LABEL_CUSTOM : await commands . executeCommand ( "maven.goal.custom" , selectedProject ) ; return ; case LABEL_FAVORITES : await commands . executeCommand ( "maven.favorites" , selectedProject ) ; return ; default : break ; } } await commands . executeCommand ( `maven.goal.${ selectedCommand }` , selectedProject ) ; } export function settingsFilePath ( ) { return Settings . getSettingsFilePath ( ) ; } }