Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-6719

Allow file parameters to be downloaded from the build Parameters page.

    XMLWordPrintable

Details

    • Improvement
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • core
    • None
    • All platforms, Hudson 1.361.

    Description

      For a build created with a file parameter, include a link to download this file on the Parameters page. For example, see screenshot Parameters (After).jpg.

      As of Hudson 1.361, "TODO" is displayed instead. See screenshot Parameters.jpg.

      Attachments

        Activity

          stevengbrown Steven G Brown created issue -
          StevenGBrown 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
          
          StevenGBrown 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
          StevenGBrown StevenGBrown made changes -
          Field Original Value New Value
          Status Open [ 1 ] In Progress [ 3 ]
          StevenGBrown StevenGBrown made changes -
          Attachment Parameters (After).jpg [ 19500 ]
          StevenGBrown StevenGBrown made changes -
          Description For a build created with a file parameter, include a link to download this file on the Parameters page.

          As of Hudson 1.361, "TODO" is displayed instead. See the attached screenshot: {{Parameters.jpg}}.
          For a build created with a file parameter, include a link to download this file on the Parameters page. For example, see screenshot {{Parameters (After).jpg}}.

          As of Hudson 1.361, "TODO" is displayed instead. See screenshot {{Parameters.jpg}}.
          StevenGBrown StevenGBrown made changes -
          Summary Allow file parameters to be downloaded from completed builds. Allow file parameters to be downloaded from the build Parameters page.

          Code changed in hudson
          User: : StevenGBrown
          Path:
          trunk/hudson/main/core/src/main/java/hudson/model/FileParameterValue.java
          trunk/hudson/main/core/src/main/resources/hudson/model/FileParameterValue/value.jelly
          trunk/www/changelog.html
          http://jenkins-ci.org/commit/31852
          Log:
          [FIXED JENKINS-6719] File parameters can now be downloaded from the build Parameters page

          scm_issue_link SCM/JIRA link daemon added a comment - Code changed in hudson User: : StevenGBrown Path: trunk/hudson/main/core/src/main/java/hudson/model/FileParameterValue.java trunk/hudson/main/core/src/main/resources/hudson/model/FileParameterValue/value.jelly trunk/www/changelog.html http://jenkins-ci.org/commit/31852 Log: [FIXED JENKINS-6719] File parameters can now be downloaded from the build Parameters page
          scm_issue_link SCM/JIRA link daemon made changes -
          Resolution Fixed [ 1 ]
          Status In Progress [ 3 ] Resolved [ 5 ]
          abayer Andrew Bayer made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          ircbot Jenkins IRC Bot made changes -
          Component/s core [ 15593 ]
          Component/s parameters [ 15594 ]
          rtyler R. Tyler Croy made changes -
          Workflow JNJira [ 136814 ] JNJira + In-Review [ 204234 ]

          People

            stevengbrown Steven G Brown
            stevengbrown Steven G Brown
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: