Java tutorial
/* * The MIT License * * Copyright (c) 2010, Manufacture Franaise des Pneumatiques Michelin, Thomas Maurel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.michelin.cio.hudson.plugins.qc.client; import com.michelin.cio.hudson.plugins.qc.Messages; import com.michelin.cio.hudson.plugins.qc.QualityCenterUtils; import hudson.AbortException; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.Hudson; import hudson.model.Node; import hudson.model.TaskListener; import hudson.tools.ToolInstallation; import hudson.tools.ToolInstaller; import hudson.tools.ToolInstallerDescriptor; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.net.URL; import org.apache.commons.io.IOUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; /** * @author Thomas Maurel */ public class QualityCenterClientInstaller extends ToolInstaller { private final String qcServerURL; private final String localPathToQCClient; public static final String INSTALLER_PATH_ON_SERVER = "PlugIns/ClientSideInstallation/"; public static final String DLL_PATH_ON_NODE = "MERCURY INTERACTIVE\\Quality Center"; public static final String INSTALLLER_FILE_NAME = "QCClient.msi"; public static final String DLL_NAME = "OTAClient.dll"; @DataBoundConstructor public QualityCenterClientInstaller(String qcServerURL, String localPathToQCClient) { super(null); this.qcServerURL = qcServerURL; this.localPathToQCClient = localPathToQCClient; } public String getLocalPathToQCClient() { return localPathToQCClient; } public String getQcServerURL() { return qcServerURL; } @Override public FilePath performInstallation(ToolInstallation tool, Node node, TaskListener log) throws IOException, InterruptedException { FilePath expectedLocation = preferredLocation(tool, node); PrintStream out = log.getLogger(); FilePath qcFolder = expectedLocation.child(DLL_PATH_ON_NODE); // Check if it has been installed by Hudson or manually // Might be in the QC_HOME, or in QC_HOME\MERCURY INTERACTIVE\Quality Center if (expectedLocation.child(".installedByHudson").exists() || expectedLocation.child(DLL_NAME).exists()) { return expectedLocation; } if (qcFolder.child(".installedByHudson").exists() || qcFolder.child(DLL_NAME).exists()) { return qcFolder; } // Create the directory tree expectedLocation.mkdirs(); FilePath file = expectedLocation.child(INSTALLLER_FILE_NAME); // If the installer is stored on the master, copy it from there if (localPathToQCClient != null & localPathToQCClient.length() > 0) { FilePath installerOnMaster = new FilePath(Hudson.MasterComputer.localChannel, localPathToQCClient); if (!installerOnMaster.exists()) { log.fatalError(Messages.QualityCenterClientInstaller_CannotFindInstaller()); throw new AbortException(); } if (installerOnMaster.isDirectory()) { log.fatalError(Messages.QualityCenterClientInstaller_ShouldBeAFile()); throw new AbortException(); } out.println(Messages.QualityCenterClientInstaller_CopyingFromMaster(localPathToQCClient)); file.copyFrom(installerOnMaster); } // Else, download it from Quality Center Server else { String url; // Add a "/" at the end of the URL if it isnt already if (qcServerURL.lastIndexOf("/") == qcServerURL.length() - 1) { url = qcServerURL + INSTALLER_PATH_ON_SERVER + INSTALLLER_FILE_NAME; } else { url = qcServerURL + "/" + INSTALLER_PATH_ON_SERVER + INSTALLLER_FILE_NAME; } URL installURL = new URL(url); out.println(Messages.QualityCenterClientInstaller_Downloading(installURL)); file.copyFrom(installURL); } // Perform installation install(node.createLauncher(log), log, expectedLocation.absolutize().getRemote(), file); // Successfully installed // Remove the installer file.delete(); // Check if the DLL exists after installation if (!qcFolder.child(DLL_NAME).exists()) { log.fatalError(Messages.QualityCenterClientInstaller_CouldntFindDllAfterInstall(DLL_NAME)); throw new AbortException(); } qcFolder.child(".installedByHudson").touch(System.currentTimeMillis()); return qcFolder; } public void install(Launcher launcher, TaskListener log, String expectedLocation, FilePath qcBundle) throws IOException, InterruptedException { PrintStream out = log.getLogger(); String qcBundleName = qcBundle.getName(); String qcBundlePath = qcBundle.absolutize().getRemote(); out.println(Messages.QualityCenterClientInstaller_Installing(qcBundleName)); String logFile = qcBundlePath + ".install.log"; StringBuilder cmd = new StringBuilder(); cmd.append('"').append(qcBundlePath).append('"'); cmd.append(" /qn /norestart TARGETDIR="); cmd.append('"').append(expectedLocation).append('"'); cmd.append(" /l "); cmd.append('"').append(logFile).append('"'); // Run the install on the node // The result must be 0 ArgumentListBuilder args = new ArgumentListBuilder().add("cmd.exe", "/C").addQuoted(cmd.toString()); if (launcher.launch().cmds(args).stdout(out).pwd(expectedLocation).join() != 0) { log.fatalError(Messages.QualityCenterClientInstaller_AbortedInstall()); // log file is in UTF-16 InputStream is = new FileInputStream(logFile); InputStreamReader in = new InputStreamReader(is, "UTF-16"); try { IOUtils.copy(in, new OutputStreamWriter(out)); } finally { in.close(); is.close(); } throw new AbortException(); } out.println(Messages.QualityCenterClientInstaller_InstallationSuccessfull()); } @Extension public static final class DescriptorImpl extends ToolInstallerDescriptor<QualityCenterClientInstaller> { public String getDisplayName() { return Messages.QualityCenterClientInstaller_DescriptorImpl_DisplayName(); } @Override public boolean isApplicable(Class<? extends ToolInstallation> toolType) { return toolType == QualityCenterClientInstallation.class; } public FormValidation doCheckQcServerURL(@QueryParameter String value) { // this can be used to check the existence of a file on the server, so needs to be protected Hudson.getInstance().checkPermission(Hudson.ADMINISTER); return QualityCenterUtils.checkQcServerURL(value, true); } public FormValidation doCheckLocalPathToQCClient(@QueryParameter String value) { // this can be used to check the existence of a file on the server, so needs to be protected Hudson.getInstance().checkPermission(Hudson.ADMINISTER); return QualityCenterUtils.checkLocalPathToInstaller(value, true); } } }