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 * @since 1.69 */ 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); } }