org.libreoffice.ci.gerrit.buildbot.servlets.QueueServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.libreoffice.ci.gerrit.buildbot.servlets.QueueServlet.java

Source

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package org.libreoffice.ci.gerrit.buildbot.servlets;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.joda.time.Instant;
import org.libreoffice.ci.gerrit.buildbot.commands.TaskStatus;
import org.libreoffice.ci.gerrit.buildbot.config.BuildbotConfig;
import org.libreoffice.ci.gerrit.buildbot.logic.BuildbotLogicControl;
import org.libreoffice.ci.gerrit.buildbot.model.BuildbotPlatformJob;
import org.libreoffice.ci.gerrit.buildbot.model.GerritJob;
import org.libreoffice.ci.gerrit.buildbot.model.TbJobResult;
import org.libreoffice.ci.gerrit.buildbot.model.Ticket;
import org.libreoffice.ci.gerrit.buildbot.review.ReviewPublisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.common.net.HttpHeaders;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.template.soy.data.SoyListData;
import com.google.template.soy.data.SoyMapData;

@Singleton
public class QueueServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    static final Logger log = LoggerFactory.getLogger(QueueServlet.class);

    private final BuildbotLogicControl control;
    private final BuildbotConfig config;
    private final ReviewPublisher publisher;
    private final Provider<CurrentUser> cu;

    private final Renderer renderer;

    @Inject
    public QueueServlet(BuildbotLogicControl control, BuildbotConfig config, ReviewPublisher publisher,
            Provider<CurrentUser> cu) {
        this.control = control;
        this.config = config;
        this.publisher = publisher;
        this.cu = cu;
        renderer = new DefaultRenderer(null, "Buildbot Queue");
    }

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse rsp)
            throws IOException, ServletException {
        String action = req.getParameter("action");
        if (!Strings.isNullOrEmpty(action)) {
            try {
                performAction(action);
                rsp.sendRedirect("queue");
            } catch (OrmException exc) {
                log.error(String.format("Can not perform action: %s", action), exc);
            }
        }
        doPost(req, rsp);
    }

    private void performAction(String action) throws OrmException {
        if (action.indexOf("cancel-") != -1) {
            String ticket = action.substring(action.indexOf('-') + 1);
            String id = ticket.substring(0, ticket.indexOf('_'));
            String project = control.findProjectByTicket(ticket);
            if (project != null) {
                GerritJob job = control.findJobById(project, id);
                if (job != null) {
                    BuildbotPlatformJob task = job.getTbJob(ticket);
                    TbJobResult result = control.setResultPossible(ticket, task.getTinderboxId(),
                            TaskStatus.CANCELLED, null);
                    if (result != null) {
                        publisher.postResultToReview(result);
                    }
                }
            }
        }
    }

    /**
     * Render data to HTML using Soy.
     * 
     * @param req in-progress request.
     * @param res in-progress response.
     * @param key key.
     * @param templateName Soy template name; must be in one of the template files
     *        defined in {@link Renderer#SOY_FILENAMES}.
     */
    protected void renderHtml(HttpServletRequest req, HttpServletResponse res, Renderer renderer,
            String templateName, Map<String, ?> soyData) throws IOException {
        try {
            res.setContentType(RenderType.HTML.getMimeType());
            res.setCharacterEncoding(Charsets.UTF_8.name());
            setCacheHeaders(req, res);
            res.setStatus(HttpServletResponse.SC_OK);
            renderer.render(res, templateName, soyData);
        } finally {
            // req.removeAttribute(DATA_ATTRIBUTE);
        }
    }

    protected void setCacheHeaders(HttpServletRequest req, HttpServletResponse res) {
        setNotCacheable(res);
    }

    static void setNotCacheable(HttpServletResponse res) {
        res.setHeader(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, max-age=0, must-revalidate");
        res.setHeader(HttpHeaders.PRAGMA, "no-cache");
        res.setHeader(HttpHeaders.EXPIRES, "Fri, 01 Jan 1990 00:00:00 GMT");
        res.setDateHeader(HttpHeaders.DATE, new Instant().getMillis());
    }

    @Override
    protected void doPost(final HttpServletRequest req, final HttpServletResponse rsp)
            throws IOException, ServletException {
        Map<String, Object> allData = getData();
        renderHtml(req, rsp, renderer, "buildbot.queue", allData);
    }

    private Map<String, Object> getData() {
        final Map<String, Object> allData = Maps.newHashMapWithExpectedSize(8);
        allData.put("title", "Buildbot Queue");
        final SoyListData soyListData = new SoyListData();
        for (String project : control.getAllProjects()) {
            List<GerritJob> gerritJobs = control.getGerritJobs(project);
            synchronized (gerritJobs) {
                for (GerritJob job : gerritJobs) {
                    boolean userIsAdmin = false;
                    CurrentUser user = cu.get();
                    if (user instanceof IdentifiedUser) {
                        if (user.getEffectiveGroups()
                                .contains(config.findProject(job.getGerritProject()).getBuildbotAdminGroupId())) {
                            userIsAdmin = true;
                        }
                    }

                    List<BuildbotPlatformJob> list = job.getBuildbotList();
                    synchronized (list) {
                        addTasks(soyListData, list, userIsAdmin);
                    }
                }
            }
        }
        allData.put("jobs", soyListData);
        return allData;
    }

    // private void addDummyTask(SoyListData soyListData) {
    // SoyMapData task = new SoyMapData();
    // String status = "INIT";
    // String startTime = "-";
    // String endTime = "-";
    // task.put("href", new SoyListData());
    // task.put("taskid", "4711_Linux");
    // task.put("start", startTime);
    // task.put("end", endTime);
    // task.put("ref", "ref");
    // task.put("bot", "TB");
    // task.put("branch", "branch");
    // task.put("status", status);
    // task.put("actionUrl", "queue");
    // soyListData.add(task);
    // }

    private void addTasks(SoyListData soyListData, List<BuildbotPlatformJob> list, boolean userIsAdmin) {
        // check if the user has the ACL
        for (BuildbotPlatformJob job : list) {
            SoyMapData task = new SoyMapData();
            String jobId = job.getParent().getId() + "_" + job.getPlatformString();
            String startTime = "-";
            String endTime = "-";
            Ticket t = job.getTicket();
            String status;
            task.put("href", new SoyListData());
            SoyListData actions = new SoyListData();
            if (job.getResult() != null && job.getResult().getStatus().isDiscarded()) {
                status = "DISCARDED";
            } else if (!job.isStarted()) {
                status = "INIT";
            } else if (job.isReady()) {
                status = job.getResult().getStatus().name();
                startTime = time(t.getStartTime());
                endTime = time(job.getResult().getEndTime());
                if (!Strings.isNullOrEmpty(job.getResult().getLog())) {
                    final SoyListData hrefData = new SoyListData();
                    hrefData.add(job.getResult().getLog());
                    task.put("href", hrefData);
                }
            } else {
                status = "STARTED";
                startTime = time(t.getStartTime());
                if (userIsAdmin) {
                    addStartActions(actions);
                }
            }
            task.put("taskid", jobId);
            task.put("start", startTime);
            task.put("end", endTime);
            task.put("ref", job.getParent().getGerritRef());
            task.put("bot", job.getTinderboxId() == null ? "-" : job.getTinderboxId());
            task.put("branch", job.getParent().getGerritBranch());
            task.put("status", status);
            task.put("actions", actions);
            soyListData.add(task);
        }
    }

    private void addStartActions(SoyListData actions) {
        SoyMapData data = new SoyMapData();
        data.put("name", "Cancel");
        data.put("action", "cancel");
        data.put("img", "/plugins/buildbot/static/redNot.png");
        actions.add(data);
    }

    private static String time(final long now) {
        final Date when = new Date(now);
        return new SimpleDateFormat("MMM-dd HH:mm").format(when);
    }

}