StevenGBrown
added a comment - -
edited Implemented by the following patch. In detail:
The file parameter is copied into a directory under the build's root directory.
FileParameterValue serves this file in response to a Stapler request.
FileParameterValue 's jelly.xml includes a link to this file, replacing the "TODO".
When a file parameter is not provided, or the build was created prior to applying this patch, no link will be displayed.
The file parameter is already copied into the workspace, but this is not sufficient, since it will most likely be overridden by future builds. Therefore the file parameter is also copied under the build's root directory.
Alternatively, it would be possible to store the file parameter within the build.xml file. I chose to store it as a separate file instead, which gives Hudson administrators the option of deleting file parameters which contain sensitive information or which use up too much disk space. Additionally, I do not want to reduce the readability of the build.xml file by including this data within it.
Index: trunk/hudson/main/core/src/main/java/hudson/model/FileParameterValue.java
===================================================================
--- trunk/hudson/main/core/src/main/java/hudson/model/FileParameterValue.java (revision 31581)
+++ trunk/hudson/main/core/src/main/java/hudson/model/FileParameterValue.java (working copy)
@@ -24,9 +24,12 @@
package hudson.model;
import org.kohsuke.stapler.DataBoundConstructor;
+import org.kohsuke.stapler.StaplerRequest;
+import org.kohsuke.stapler.StaplerResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import hudson.tasks.BuildWrapper;
@@ -40,6 +43,7 @@
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
+import javax.servlet.ServletException;
/**
* {@link ParameterValue} for {@link FileParameterDefinition}.
@@ -55,16 +59,23 @@
public class FileParameterValue extends ParameterValue {
private FileItem file;
+ /**
+ * The name of the originally uploaded file.
+ */
+ private final String originalFileName;
+
private String location;
@DataBoundConstructor
public FileParameterValue(String name, FileItem file) {
this(name, file, null);
}
+
public FileParameterValue(String name, FileItem file, String description) {
super(name, description);
assert file!=null;
this.file = file;
+ this.originalFileName = FilenameUtils.getName(file.getName());
}
public FileParameterValue(String name, File file, String desc) {
@@ -76,14 +87,28 @@
this.location = location;
}
+ /**
+ * Get the name of the originally uploaded file. If this
+ * {@link FileParameterValue} was created prior to 1.362, this method will
+ * return {@code null}.
+ *
+ * @return the name of the originally uploaded file
+ */
+ public String getOriginalFileName() {
+ return originalFileName;
+ }
+
@Override
public BuildWrapper createBuildWrapper(AbstractBuild<?,?> build) {
return new BuildWrapper() {
+ @Override
public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
if (!StringUtils.isEmpty(file.getName())) {
- listener.getLogger().println("Copying file to "+location);
- build.getWorkspace().child(location).copyFrom(file);
- file = null;
+ listener.getLogger().println("Copying file to "+location);
+ FilePath locationFilePath = build.getWorkspace().child(location);
+ locationFilePath.copyFrom(file);
+ file = null;
+ locationFilePath.copyTo(new FilePath(getLocationUnderBuild(build)));
}
return new Environment() {};
}
@@ -121,10 +146,38 @@
@Override
public String getShortDescription() {
- return "(FileParameterValue) " + getName() + "='" + file.getName() + "'";
+ return "(FileParameterValue) " + getName() + "='" + originalFileName + "'";
}
/**
+ * Serve this file parameter in response to a {@link StaplerRequest}.
+ *
+ * @param request
+ * @param response
+ * @throws ServletException
+ * @throws IOException
+ */
+ public void doDynamic(StaplerRequest request, StaplerResponse response) throws ServletException, IOException {
+ if (("/" + originalFileName).equals(request.getRestOfPath())) {
+ AbstractBuild build = (AbstractBuild)request.findAncestor(AbstractBuild.class).getObject();
+ File fileParameter = getLocationUnderBuild(build);
+ if (fileParameter.isFile()) {
+ response.serveFile(request, fileParameter.toURI().toURL());
+ }
+ }
+ }
+
+ /**
+ * Get the location under the build directory to store the file parameter.
+ *
+ * @param build the build
+ * @return the location to store the file parameter
+ */
+ private File getLocationUnderBuild(AbstractBuild build) {
+ return new File(build.getRootDir(), "fileParameters/" + location);
+ }
+
+ /**
* Default implementation from {@link File}.
*/
public static final class FileItemImpl implements FileItem {
Index: trunk/hudson/main/core/src/main/resources/hudson/model/FileParameterValue/value.jelly
===================================================================
--- trunk/hudson/main/core/src/main/resources/hudson/model/FileParameterValue/value.jelly (revision 31581)
+++ trunk/hudson/main/core/src/main/resources/hudson/model/FileParameterValue/value.jelly (working copy)
@@ -25,7 +25,9 @@
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define"
xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"
xmlns:i="jelly:fmt" xmlns:p="/lib/hudson/project">
- <f:entry title="${it.name}">
- TODO
- </f:entry>
+ <f:entry title="${it.name}">
+ <j:if test="${it.originalFileName != null}">
+ <a href="parameter/${it.name}/${it.originalFileName}">${it.originalFileName}</a>
+ </j:if>
+ </f:entry>
</j:jelly>
\ No newline at end of file
Implemented by the following patch. In detail:
The file parameter is already copied into the workspace, but this is not sufficient, since it will most likely be overridden by future builds. Therefore the file parameter is also copied under the build's root directory.
Alternatively, it would be possible to store the file parameter within the build.xml file. I chose to store it as a separate file instead, which gives Hudson administrators the option of deleting file parameters which contain sensitive information or which use up too much disk space. Additionally, I do not want to reduce the readability of the build.xml file by including this data within it.