All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.offbytwo.jenkins.model.BuildWithDetails Maven / Gradle / Ivy

There is a newer version: 0.3.8
Show newest version
/*
 * Copyright (c) 2013 Cosmin Stejerean, Karl Heinz Marbaise, and contributors.
 *
 * Distributed under the MIT license: http://opensource.org/licenses/MIT
 */

package com.offbytwo.jenkins.model;

import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;

import static com.google.common.collect.Collections2.filter;

/**
 * This class represents build information with details about what has been done
 * like duration start and of course the build result.
 *
 */
public class BuildWithDetails extends Build {

    /**
     * This will be returned by the API in cases where the build has never run.
     * For example {@link Build#BUILD_HAS_NEVER_RUN}
     */
    public static final BuildWithDetails BUILD_HAS_NEVER_RUN = new BuildWithDetails() {

        @Override
        public List getActions() {
            return Collections.emptyList();
        }

        @Override
        public List getArtifacts() {
            return Collections.emptyList();
        }

        @Override
        public List getCauses() {
            return Collections.emptyList();
        }

        @Override
        public List getCulprits() {
            return Collections.emptyList();
        }

        @Override
        public BuildResult getResult() {
            return BuildResult.NOT_BUILT;
        }

    };

    /**
     * This will be returned by the API in cases where the build has been
     * cancelled. For example {@link Build#BUILD_HAS_BEEN_CANCELLED}
     */
    public static final BuildWithDetails BUILD_HAS_BEEN_CANCELLED = new BuildWithDetails() {

        @Override
        public List getActions() {
            return Collections.emptyList();
        }

        @Override
        public List getArtifacts() {
            return Collections.emptyList();
        }

        @Override
        public List getCauses() {
            return Collections.emptyList();
        }

        @Override
        public List getCulprits() {
            return Collections.emptyList();
        }

        @Override
        public BuildResult getResult() {
            return BuildResult.CANCELLED;
        }

    };

    private List actions; // TODO: Should be improved.
    private boolean building;
    private String description;
    private String displayName;
    private long duration;
    private long estimatedDuration;
    private String fullDisplayName;
    private String id;
    private long timestamp;
    private BuildResult result;
    private List artifacts;
    private String consoleOutputText;
    private String consoleOutputHtml;
    private BuildChangeSet changeSet;
    private String builtOn;
    private List culprits;

    public BuildWithDetails() {
        // Default ctor is needed to jackson.
    }

    public BuildWithDetails(BuildWithDetails details) {
        this.actions = details.actions;
        this.description = details.description;
        this.displayName = details.displayName;
        this.building = details.building;
        this.duration = details.duration;
        this.estimatedDuration = details.estimatedDuration;
        this.fullDisplayName = details.fullDisplayName;
        this.id = details.id;
        this.timestamp = details.timestamp;
        this.result = details.result;
        this.artifacts = details.artifacts;
        this.consoleOutputHtml = details.consoleOutputHtml;
        this.consoleOutputText = details.consoleOutputText;
        this.changeSet = details.changeSet;
        this.builtOn = details.builtOn;
        this.culprits = details.culprits;
        this.setClient(details.getClient());
    }

    public List getArtifacts() {
        return artifacts;
    }

    public boolean isBuilding() {
        return building;
    }

    public List getCauses() {
        // actions is a List List[BuildCause]
        Collection causes = filter(actions, new Predicate>() {
            @Override
            public boolean apply(Map action) {
                return action.containsKey("causes");
            }
        });

        List result = new ArrayList();

        if (causes != null && !causes.isEmpty()) {
            // The underlying key-value can be either a  or a
            // .
            List> causes_blob = ((Map>>) causes.toArray()[0])
                    .get("causes");
            for (Map cause : causes_blob) {

                BuildCause convertToBuildCause = convertToBuildCause(cause);

                result.add(convertToBuildCause);
            }
        }

        return result;
    }

    /**
     * Update displayName and the description of a
     * build.
     * 
     * @param displayName The new displayName which should be set.
     * @param description The description which should be set.
     * @param crumbFlag true or false.
     * @throws IOException in case of errors.
     */
    public void updateDisplayNameAndDescription(String displayName, String description, boolean crumbFlag)
            throws IOException {
        Objects.requireNonNull(displayName, "displayName is not allowed to be null.");
        Objects.requireNonNull(description, "description is not allowed to be null.");
        // TODO: Check what the "core:apply" means?
        ImmutableMap params = ImmutableMap.of("displayName", displayName, "description", description,
                "core:apply", "", "Submit", "Save");
        client.post_form(this.getUrl() + "/configSubmit?", params, crumbFlag);
    }

    /**
     * Update displayName and the description of a
     * build.
     * 
     * @param displayName The new displayName which should be set.
     * @param description The description which should be set.
     * @throws IOException in case of errors.
     */
    public void updateDisplayNameAndDescription(String displayName, String description) throws IOException {
        updateDisplayNameAndDescription(displayName, description, false);
    }

    /**
     * Update displayName of a build.
     * 
     * @param displayName The new displayName which should be set.
     * @param crumbFlag true or false.
     * @throws IOException in case of errors.
     */
    public void updateDisplayName(String displayName, boolean crumbFlag) throws IOException {
        Objects.requireNonNull(displayName, "displayName is not allowed to be null.");
        String description = getDescription() == null ? "" : getDescription();
        // TODO: Check what the "core:apply" means?
        ImmutableMap params = ImmutableMap.of("displayName", displayName, "description", description,
                "core:apply", "", "Submit", "Save");
        client.post_form(this.getUrl() + "/configSubmit?", params, crumbFlag);
    }

    /**
     * Update displayName of a build.
     * 
     * @param displayName The new displayName which should be set.
     * @throws IOException in case of errors.
     */
    public void updateDisplayName(String displayName) throws IOException {
        updateDisplayName(displayName, false);
    }

    /**
     * Update the description of a build.
     * 
     * @param description The description which should be set.
     * @param crumbFlag true or false.
     * @throws IOException in case of errors.
     */
    public void updateDescription(String description, boolean crumbFlag) throws IOException {
        Objects.requireNonNull(description, "description is not allowed to be null.");
        String displayName = getDisplayName() == null ? "" : getDisplayName();
        // TODO: Check what the "core:apply" means?
        ImmutableMap params = ImmutableMap.of("displayName", displayName, "description", description,
                "core:apply", "", "Submit", "Save");
        client.post_form(this.getUrl() + "/configSubmit?", params, crumbFlag);
    }

    /**
     * Update the description of a build.
     * 
     * @param description The description which should be set.
     * @throws IOException in case of errors.
     */
    public void updateDescription(String description) throws IOException {
        updateDescription(description, false);
    }

    private BuildCause convertToBuildCause(Map cause) {
        BuildCause cause_object = new BuildCause();

        // TODO: Think about it. Can this be done more simpler?
        String description = (String) cause.get("shortDescription");
        if (!Strings.isNullOrEmpty(description)) {
            cause_object.setShortDescription(description);
        }

        Integer upstreamBuild = (Integer) cause.get("upstreamBuild");
        if (upstreamBuild != null) {
            cause_object.setUpstreamBuild(upstreamBuild);
        }

        String upstreamProject = (String) cause.get("upstreamProject");
        if (!Strings.isNullOrEmpty(upstreamProject)) {
            cause_object.setUpstreamProject(upstreamProject);
        }

        String upstreamUrl = (String) cause.get("upstreamUrl");
        if (!Strings.isNullOrEmpty(upstreamProject)) {
            cause_object.setUpstreamUrl(upstreamUrl);
        }

        String userId = (String) cause.get("userId");
        if (!Strings.isNullOrEmpty(userId)) {
            cause_object.setUserId(userId);
        }

        String userName = (String) cause.get("userName");
        if (!Strings.isNullOrEmpty(userName)) {
            cause_object.setUserName(userName);
        }
        return cause_object;
    }

    public String getDescription() {
        return description;
    }

    public long getDuration() {
        return duration;
    }

    public long getEstimatedDuration() {
        return estimatedDuration;
    }

    public String getFullDisplayName() {
        return fullDisplayName;
    }

    public String getDisplayName() {
        return displayName;
    }

    public String getId() {
        return id;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public BuildResult getResult() {
        return result;
    }

    public String getBuiltOn() {
        return builtOn;
    }

    public List getActions() {
        return actions;
    }

    public Map getParameters() {
        Collection parameters = filter(actions, new Predicate>() {
            @Override
            public boolean apply(Map action) {
                return action.containsKey("parameters");
            }
        });

        Map params = new HashMap();

        if (parameters != null && !parameters.isEmpty()) {
            for (Map param : ((Map>>) parameters.toArray()[0])
                    .get("parameters")) {
                String key = (String) param.get("name");
                Object value = param.get("value");
                params.put(key, String.valueOf(value));
            }
        }

        return params;
    }

    /**
     * @return The console output of the build. The line separation is done by
     *         {@code CR+LF}.
     * @throws IOException in case of a failure.
     */
    public String getConsoleOutputText() throws IOException {
        return client.get(getUrl() + "/logText/progressiveText");
    }

    /**
     * The console output with HTML.
     * 
     * @return The console output as HTML.
     * @throws IOException in case of an error.
     */
    public String getConsoleOutputHtml() throws IOException {
        return client.get(getUrl() + "/logText/progressiveHtml");
    }

    public BuildChangeSet getChangeSet() {
        return changeSet;
    }

    public void setChangeSet(BuildChangeSet changeSet) {
        this.changeSet = changeSet;
    }

    public List getCulprits() {
        return culprits;
    }

    public void setCulprits(List culprits) {
        this.culprits = culprits;
    }

    public void setResult(BuildResult result) {
        this.result = result;
    }

    public InputStream downloadArtifact(Artifact a) throws IOException, URISyntaxException {
        // We can't just put the artifact's relative path at the end of the url
        // string, as there could be characters that need to be escaped.
        URI uri = new URI(getUrl());
        String artifactPath = uri.getPath() + "artifact/" + a.getRelativePath();
        URI artifactUri = new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), artifactPath, "",
                "");
        return client.getFile(artifactUri);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!super.equals(obj))
            return false;
        if (getClass() != obj.getClass())
            return false;
        BuildWithDetails other = (BuildWithDetails) obj;
        if (actions == null) {
            if (other.actions != null)
                return false;
        } else if (!actions.equals(other.actions))
            return false;
        if (artifacts == null) {
            if (other.artifacts != null)
                return false;
        } else if (!artifacts.equals(other.artifacts))
            return false;
        if (building != other.building)
            return false;
        if (builtOn == null) {
            if (other.builtOn != null)
                return false;
        } else if (!builtOn.equals(other.builtOn))
            return false;
        if (changeSet == null) {
            if (other.changeSet != null)
                return false;
        } else if (!changeSet.equals(other.changeSet))
            return false;
        if (consoleOutputHtml == null) {
            if (other.consoleOutputHtml != null)
                return false;
        } else if (!consoleOutputHtml.equals(other.consoleOutputHtml))
            return false;
        if (consoleOutputText == null) {
            if (other.consoleOutputText != null)
                return false;
        } else if (!consoleOutputText.equals(other.consoleOutputText))
            return false;
        if (culprits == null) {
            if (other.culprits != null)
                return false;
        } else if (!culprits.equals(other.culprits))
            return false;
        if (description == null) {
            if (other.description != null)
                return false;
        } else if (!description.equals(other.description))
            return false;
        if (displayName == null) {
            if (other.displayName != null)
                return false;
        } else if (!displayName.equals(other.displayName))
            return false;
        if (duration != other.duration)
            return false;
        if (estimatedDuration != other.estimatedDuration)
            return false;
        if (fullDisplayName == null) {
            if (other.fullDisplayName != null)
                return false;
        } else if (!fullDisplayName.equals(other.fullDisplayName))
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (result != other.result)
            return false;
        if (timestamp != other.timestamp)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = super.hashCode();
        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
        result = prime * result + ((artifacts == null) ? 0 : artifacts.hashCode());
        result = prime * result + (building ? 1231 : 1237);
        result = prime * result + ((builtOn == null) ? 0 : builtOn.hashCode());
        result = prime * result + ((changeSet == null) ? 0 : changeSet.hashCode());
        result = prime * result + ((consoleOutputHtml == null) ? 0 : consoleOutputHtml.hashCode());
        result = prime * result + ((consoleOutputText == null) ? 0 : consoleOutputText.hashCode());
        result = prime * result + ((culprits == null) ? 0 : culprits.hashCode());
        result = prime * result + ((description == null) ? 0 : description.hashCode());
        result = prime * result + ((displayName == null) ? 0 : displayName.hashCode());
        result = prime * result + (int) (duration ^ (duration >>> 32));
        result = prime * result + (int) (estimatedDuration ^ (estimatedDuration >>> 32));
        result = prime * result + ((fullDisplayName == null) ? 0 : fullDisplayName.hashCode());
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((this.result == null) ? 0 : this.result.hashCode());
        result = prime * result + (int) (timestamp ^ (timestamp >>> 32));
        return result;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy