package hudson.plugins.buckminster.targetPlatform; import java.io.File; import java.io.IOException; import java.util.List; import net.sf.json.JSONObject; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.Util; import hudson.matrix.MatrixConfiguration; import hudson.matrix.MatrixProject; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.DependecyDeclarer; import hudson.model.DependencyGraph; import hudson.model.FreeStyleProject; import hudson.model.Hudson; import hudson.model.Project; import hudson.model.Result; import hudson.model.DependencyGraph.Dependency; import hudson.plugins.buckminster.EclipseBuckminsterBuilder; import hudson.tasks.ArtifactArchiver; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Messages; import hudson.tasks.Publisher; import hudson.util.FormValidation; /** * A publisher that archives a workspace directory and makes its content available under a certain name to other jobs that have a buckminster build step. * * * @author Johannes Utzig * */ public class TargetPlatformPublisher extends ArtifactArchiver implements DependecyDeclarer { private static final String TARGET_PLATFORM_DIRECTORY = "/targetPlatform"; @DataBoundConstructor public TargetPlatformPublisher(String artifacts, String excludes, boolean latestOnly, String targetPlatformName) { super(artifacts, excludes, latestOnly); this.targetPlatformName = targetPlatformName; } /** * overrides {@link ArtifactArchiver#perform(AbstractBuild, Launcher, BuildListener)} so that * <ul> * <li>the contents of the {@link TargetPlatformPublisher#getArtifacts()} is copied flat instead of preserving the directory structure</li> * <li>file patterns are not allowed</li> * </ul> */ @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException { if (getArtifacts().length() == 0) { listener.error(Messages.ArtifactArchiver_NoIncludes()); build.setResult(Result.FAILURE); return true; } File dir = build.getArtifactsDir(); dir = new File(dir, "targetPlatform"); dir.mkdirs(); listener.getLogger().println( Messages.ArtifactArchiver_ARCHIVING_ARTIFACTS()); try { FilePath ws = build.getWorkspace(); if (ws == null) { // #3330: slave down? return true; } FilePath result = ws.child(getArtifacts()); if (result.copyRecursiveTo(new FilePath(dir)) == 0) { if (build.getResult().isBetterOrEqualTo(Result.UNSTABLE)) { // If the build failed, don't complain that there was no // matching artifact. // The build probably didn't even get to the point where it // produces artifacts. listener.error(Messages .ArtifactArchiver_NoMatchFound(getArtifacts())); String msg = ws.validateAntFileMask(getArtifacts()); if (msg != null) listener.error(msg); } build.setResult(Result.FAILURE); return true; } } catch (IOException e) { Util.displayIOException(e, listener); e.printStackTrace(listener.error(Messages .ArtifactArchiver_FailedToArchive(getArtifacts()))); return true; } return true; } private String targetPlatformName; public TargetPlatformReference getTargetPlatformReference( AbstractProject<?,?> project) { TargetPlatformReference reference = new TargetPlatformReference(); reference.setName(targetPlatformName); reference.setFullName(project.getFullName() + "/" + targetPlatformName); if (project.getLastSuccessfulBuild() != null) { //windows paths need to be converted to unix paths //see: https://hudson.dev.java.net/issues/show_bug.cgi?id=4947 String fullPath = project.getLastSuccessfulBuild() .getArtifactsDir().getAbsoluteFile().toURI().getPath() + TARGET_PLATFORM_DIRECTORY; reference.setPath(fullPath); } return reference; } public String getTargetPlatformName() { return targetPlatformName; } @SuppressWarnings("unchecked") public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) { TargetPlatformReference reference = getTargetPlatformReference(owner); if (reference == null || reference.getFullName() == null) return; List<Project> projects = Hudson.getInstance() .getAllItems(Project.class); for (Project project : projects) { List builds = project.getBuilders(); for (Object object : builds) { if (object instanceof EclipseBuckminsterBuilder) { EclipseBuckminsterBuilder builder = (EclipseBuckminsterBuilder) object; if (builder.getTargetPlatform() != null && reference.getFullName().equals( builder.getTargetPlatform().getFullName())) { if (project instanceof MatrixConfiguration) { //in case of a matrix configuration, the MatrixProject is the actual dependency, not the individual configurations // MatrixConfiguration matrixConfiguration = (MatrixConfiguration) project; MatrixProject matrix = (MatrixProject) project.getParent(); graph.addDependency(new Dependency(owner, matrix)); } else{ graph.addDependency(new Dependency(owner, project)); } } } } } } /** * The descriptor of this publisher. It is annotated as an Extension so * Hudson can automatically register this instance */ @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); /** * The descriptor implementation of this trigger */ public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> { @SuppressWarnings("unchecked") @Override public boolean isApplicable(Class<? extends AbstractProject> jobType) { return FreeStyleProject.class.isAssignableFrom(jobType) || MatrixProject.class.isAssignableFrom(jobType); } @Override public String getDisplayName() { return "Archive and publish an Eclipse Target Platform"; } @Override public Publisher newInstance(StaplerRequest req, JSONObject formData) throws hudson.model.Descriptor.FormException { return req.bindJSON(TargetPlatformPublisher.class, formData); } /** * Performs on-the-fly validation on the relative directory. */ public FormValidation doCheckArtifacts( @AncestorInPath AbstractProject<?,?> project, @QueryParameter String value) throws IOException { FilePath ws = project.getSomeWorkspace(); return ws != null ? ws.validateRelativeDirectory(value) : FormValidation.ok(); } @Override public String getHelpFile() { return "/plugin/buckminster/help-targetPlatformPublisher.html"; } } }