Skip to content
This repository has been archived by the owner on Apr 6, 2022. It is now read-only.

Commit

Permalink
[FIXED JENKINS-21102] Use same code to copy files from slave to master.
Browse files Browse the repository at this point in the history
Moved code to copy files with warnings to build folder to new class Files.
This class is used by Freestyle and Maven projects to copy affected files.
  • Loading branch information
uhafner committed Feb 4, 2015
1 parent 54244a7 commit 3e382e2
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 104 deletions.
@@ -1,10 +1,11 @@
package hudson.plugins.analysis.core; // NOPMD

import javax.annotation.CheckForNull;
import java.io.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import hudson.FilePath;
Expand All @@ -15,9 +16,11 @@
import hudson.model.Project;
import hudson.model.Result;
import hudson.plugins.analysis.util.EncodingValidator;
import hudson.plugins.analysis.util.Files;
import hudson.plugins.analysis.util.LoggerFactory;
import hudson.plugins.analysis.util.PluginLogger;
import hudson.plugins.analysis.util.model.*;
import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;
import hudson.remoting.VirtualChannel;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Builder;
Expand All @@ -42,7 +45,6 @@
@SuppressWarnings("PMD.TooManyFields")
public abstract class HealthAwareRecorder extends Recorder implements HealthDescriptor, MatrixAggregatable {
private static final long serialVersionUID = 8892994325541840827L;
private static final String SLASH = "/";

/** Default threshold priority limit. */
private static final String DEFAULT_PRIORITY_THRESHOLD_LIMIT = "low";
Expand Down Expand Up @@ -396,83 +398,8 @@ public PluginDescriptor getDescriptor() {
protected void copyFilesWithAnnotationsToBuildFolder(final File rootDir,
final VirtualChannel channel, final Collection<FileAnnotation> annotations)
throws IOException, FileNotFoundException, InterruptedException {
File directory = new File(rootDir, AbstractAnnotation.WORKSPACE_FILES);
if (!directory.exists() && !directory.mkdir()) {
throw new IOException(
"Can't create directory for workspace files that contain annotations: "
+ directory.getAbsolutePath());
}
AnnotationContainer container = new DefaultAnnotationContainer(annotations);
for (WorkspaceFile file : container.getFiles()) {
File masterFile = new File(directory, file.getTempName());
if (!masterFile.exists()) {
try {
FileOutputStream outputStream = new FileOutputStream(masterFile);

new FilePath(channel, file.getName()).copyTo(outputStream);
}
catch (IOException exception) {
logExceptionToFile(exception, masterFile, file.getName());
}
}
}
}

/**
* Logs the specified exception in the specified file.
*
* @param exception
* the exception
* @param masterFile
* the file on the master
* @param slaveFileName
* the file name of the slave
*/
private void logExceptionToFile(final IOException exception, final File masterFile,
final String slaveFileName) {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(masterFile);
print(outputStream,
"Copying the source file '%s' from the workspace to the build folder '%s' on the Jenkins master failed.%n",
slaveFileName, masterFile.getAbsolutePath());
if (!slaveFileName.startsWith(SLASH) && !slaveFileName.contains(":")) {
print(outputStream,
"Seems that the path is relative, however an absolute path is required when copying the sources.%n");
String base;
if (slaveFileName.contains(SLASH)) {
base = StringUtils.substringAfterLast(slaveFileName, SLASH);
}
else {
base = slaveFileName;
}
print(outputStream,
"Is the file '%s' contained more than once in your workspace?%n", base);
}
print(outputStream, "Is the file '%s' a valid filename?%n", slaveFileName);
print(outputStream,
"If you are building on a slave: please check if the file is accessible under '$JENKINS_HOME/[job-name]/%s'%n",
slaveFileName);
print(outputStream,
"If you are building on the master: please check if the file is accessible under '$JENKINS_HOME/[job-name]/workspace/%s'%n",
slaveFileName);
exception.printStackTrace(new PrintStream(outputStream, false, getEncoding()));
}
catch (IOException error) {
// ignore
}
finally {
IOUtils.closeQuietly(outputStream);
}
}

private void print(final FileOutputStream outputStream, final String message,
final Object... arguments) throws IOException {
IOUtils.write(String.format(message, arguments), outputStream, getEncoding());
}

private String getEncoding() {
return EncodingValidator.getEncoding(getDefaultEncoding());
new Files().copyFilesWithAnnotationsToBuildFolder(channel, new FilePath(rootDir), annotations,
EncodingValidator.getEncoding(getDefaultEncoding()));
}

/**
Expand Down
38 changes: 15 additions & 23 deletions src/main/java/hudson/plugins/analysis/core/HealthAwareReporter.java
Expand Up @@ -10,17 +10,24 @@

import hudson.FilePath;
import hudson.Launcher;
import hudson.maven.*;
import hudson.maven.MavenAggregatedReport;
import hudson.maven.MavenBuild;
import hudson.maven.MavenBuildProxy;
import hudson.maven.MavenBuildProxy.BuildCallable;
import hudson.maven.MavenModuleSetBuild;
import hudson.maven.MavenReporter;
import hudson.maven.MojoInfo;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.plugins.analysis.Messages;
import hudson.plugins.analysis.util.EncodingValidator;
import hudson.plugins.analysis.util.Files;
import hudson.plugins.analysis.util.LoggerFactory;
import hudson.plugins.analysis.util.PluginLogger;
import hudson.plugins.analysis.util.StringPluginLogger;
import hudson.plugins.analysis.util.model.*;
import hudson.remoting.Channel;
import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.Priority;
import hudson.remoting.VirtualChannel;
import hudson.tasks.BuildStep;

Expand Down Expand Up @@ -385,7 +392,7 @@ private String registerResults(final ParserResult result, final MavenBuild maven
String baseUrl = getDescriptor().getPluginResultUrlName();
buildResult.evaluateStatus(thresholds, useDeltaValues, canComputeNew(), pluginLogger, baseUrl);
}
mavenBuild.getActions().add(createMavenAggregatedReport(mavenBuild, buildResult));
mavenBuild.addAction(createMavenAggregatedReport(mavenBuild, buildResult));
mavenBuild.registerAsProjectAction(HealthAwareReporter.this);
AbstractBuild<?, ?> referenceBuild = buildResult.getHistory().getReferenceBuild();
if (referenceBuild != null) {
Expand Down Expand Up @@ -483,26 +490,11 @@ protected boolean canContinue(final Result result) {
* @throws InterruptedException
* if the user cancels the processing
*/
private void copyFilesWithAnnotationsToBuildFolder(final PluginLogger logger, final FilePath buildRoot, final Collection<FileAnnotation> annotations) throws IOException,
private void copyFilesWithAnnotationsToBuildFolder(final PluginLogger logger, final FilePath buildRoot,
final Collection<FileAnnotation> annotations) throws IOException,
FileNotFoundException, InterruptedException {
FilePath directory = new FilePath(buildRoot, AbstractAnnotation.WORKSPACE_FILES);
if (!directory.exists()) {
directory.mkdirs();
}
AnnotationContainer container = new DefaultAnnotationContainer(annotations);
for (WorkspaceFile file : container.getFiles()) {
FilePath masterFile = new FilePath(directory, file.getTempName());
if (!masterFile.exists()) {
try {
new FilePath((Channel)null, file.getName()).copyTo(masterFile);
}
catch (IOException exception) {
String message = "Can't copy source file: source=" + file.getName() + ", destination=" + masterFile.getName();
logger.log(message);
logger.printStackTrace(exception);
}
}
}
new Files().copyFilesWithAnnotationsToBuildFolder(null, buildRoot, annotations,
EncodingValidator.getEncoding(getDefaultEncoding()));
}

/**
Expand Down
130 changes: 130 additions & 0 deletions src/main/java/hudson/plugins/analysis/util/Files.java
@@ -0,0 +1,130 @@
package hudson.plugins.analysis.util;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Collection;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import hudson.FilePath;
import hudson.plugins.analysis.util.model.AbstractAnnotation;
import hudson.plugins.analysis.util.model.AnnotationContainer;
import hudson.plugins.analysis.util.model.DefaultAnnotationContainer;
import hudson.plugins.analysis.util.model.FileAnnotation;
import hudson.plugins.analysis.util.model.WorkspaceFile;
import hudson.remoting.VirtualChannel;

/**
* Provides a method to copy all files affected by warnings to the build folder.
*
* @author Ullrich Hafner
*/
public class Files {
private static final String SLASH = "/";

/**
* Copies all files with annotations from the workspace to the build folder.
*
* @param rootDir
* directory to store the copied files in
* @param annotations
* annotations determining the actual files to copy
* @param defaultEncoding
* @throws IOException
* if the files could not be written
* @throws InterruptedException
* if the user cancels the processing
*/
public void copyFilesWithAnnotationsToBuildFolder(final FilePath rootDir,
final Collection<FileAnnotation> annotations, final String defaultEncoding) throws IOException, InterruptedException {
copyFilesWithAnnotationsToBuildFolder(null, rootDir, annotations, defaultEncoding);
}

/**
* Copies all files with annotations from the workspace to the build folder.
*
* @param channel
* channel to get the files from
* @param rootDir
* directory to store the copied files in
* @param annotations
* annotations determining the actual files to copy
* @param defaultEncoding
* @throws IOException
* if the files could not be written
* @throws InterruptedException
* if the user cancels the processing
*/
public void copyFilesWithAnnotationsToBuildFolder(final VirtualChannel channel, final FilePath rootDir,
final Collection<FileAnnotation> annotations, final String defaultEncoding)
throws IOException, InterruptedException {
FilePath directory = rootDir.child(AbstractAnnotation.WORKSPACE_FILES);
if (!directory.exists()) {
try {
directory.mkdirs();
}
catch (IOException exception) {
throw new IOException("Can't create directory for workspace files that contain annotations: "
+ directory.getName(), exception);
}
}

AnnotationContainer container = new DefaultAnnotationContainer(annotations);
for (WorkspaceFile file : container.getFiles()) {
FilePath masterFile = directory.child(file.getTempName());
if (!masterFile.exists()) {
try {
new FilePath(channel, file.getName()).copyTo(masterFile);
}
catch (IOException exception) {
logExceptionToFile(exception, masterFile, file.getName(), defaultEncoding);
}
}
}
}

private void logExceptionToFile(final IOException exception, final FilePath masterFile,
final String slaveFileName, final String defaultEncoding) throws InterruptedException {
OutputStream outputStream = null;
try {
outputStream = masterFile.write();
print(outputStream,
defaultEncoding, "Copying the source file '%s' from the workspace to the build folder '%s' on the Jenkins master failed.%n",
slaveFileName, masterFile.getName());
if (!slaveFileName.startsWith(SLASH) && !slaveFileName.contains(":")) {
print(outputStream,
defaultEncoding, "Seems that the path is relative, however an absolute path is required when copying the sources.%n");
String base;
if (slaveFileName.contains(SLASH)) {
base = StringUtils.substringAfterLast(slaveFileName, SLASH);
}
else {
base = slaveFileName;
}
print(outputStream,
defaultEncoding, "Is the file '%s' contained more than once in your workspace?%n", base);
}
print(outputStream, defaultEncoding, "Is the file '%s' a valid filename?%n", slaveFileName);
print(outputStream,
defaultEncoding, "If you are building on a slave: please check if the file is accessible under '$JENKINS_HOME/[job-name]/%s'%n",
slaveFileName);
print(outputStream,
defaultEncoding, "If you are building on the master: please check if the file is accessible under '$JENKINS_HOME/[job-name]/workspace/%s'%n",
slaveFileName);
exception.printStackTrace(new PrintStream(outputStream, false, defaultEncoding));
}
catch (IOException error) {
// ignore
}
finally {
IOUtils.closeQuietly(outputStream);
}
}

private void print(final OutputStream outputStream, final String defaultEncoding, final String message,
final Object... arguments) throws IOException {
IOUtils.write(String.format(message, arguments), outputStream, defaultEncoding);
}
}

0 comments on commit 3e382e2

Please sign in to comment.