/******************************************************************************* * * Copyright (c) 2004-2009 Oracle Corporation. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Kohsuke Kawaguchi * * *******************************************************************************/ 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.FileItemHeaders; import org.apache.commons.fileupload.disk.DiskFileItem; import org.apache.commons.lang3.StringUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import hudson.tasks.BuildWrapper; import hudson.Launcher; import hudson.FilePath; import java.io.IOException; import java.io.File; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.io.OutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Iterator; import java.util.NoSuchElementException; import javax.servlet.ServletException; /** * {@link ParameterValue} for {@link FileParameterDefinition}. * * <h2>Persistence</h2> <p> {@link DiskFileItem} is persistable via * serialization, (although the data may get very large in XML) so this object * as a whole is persistable. * * @author Kohsuke Kawaguchi */ 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, FilenameUtils.getName(file.getName())); } public FileParameterValue(String name, File file, String originalFileName) { this(name, new FileItemImpl(file), originalFileName); } private FileParameterValue(String name, FileItem file, String originalFileName) { super(name); this.file = file; this.originalFileName = originalFileName; } // post initialization hook /*package*/ void setLocation(String location) { 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); FilePath locationFilePath = build.getWorkspace().child(location); locationFilePath.getParent().mkdirs(); locationFilePath.copyFrom(file); file = null; locationFilePath.copyTo(new FilePath(getLocationUnderBuild(build))); } return new Environment() { }; } }; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((location == null) ? 0 : location.hashCode()); return result; } /** * In practice this will always be false, since location should be unique. */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } FileParameterValue other = (FileParameterValue) obj; if (location == null) { if (other.location != null) { return false; } } else if (!location.equals(other.location)) { return false; } return true; } @Override public String getShortDescription() { 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 { private final File file; /** FileItemHeaders with dummy initial value */ private FileItemHeaders headers = new FileItemHeaders() { public String getHeader(String name) { return null; } public Iterator<String> getHeaderNames() { return new Iterator<String>() { public boolean hasNext() { return false; } public String next() { throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }; } public Iterator<String> getHeaders(String name) { return getHeaderNames(); } }; public FileItemImpl(File file) { if (file == null) { throw new NullPointerException("file"); } this.file = file; } public InputStream getInputStream() throws IOException { return new FileInputStream(file); } public String getContentType() { return null; } public String getName() { return file.getName(); } public boolean isInMemory() { return false; } public long getSize() { return file.length(); } public byte[] get() { try { return IOUtils.toByteArray(new FileInputStream(file)); } catch (IOException e) { throw new Error(e); } } public String getString(String encoding) throws UnsupportedEncodingException { return new String(get(), encoding); } public String getString() { return new String(get()); } public void write(File to) throws Exception { new FilePath(file).copyTo(new FilePath(to)); } public void delete() { file.delete(); } public String getFieldName() { return null; } public void setFieldName(String name) { } public boolean isFormField() { return false; } public void setFormField(boolean state) { } public OutputStream getOutputStream() throws IOException { return new FileOutputStream(file); } public FileItemHeaders getHeaders() { return headers; } public void setHeaders(FileItemHeaders headers) { this.headers = headers; } } }