com.sun.faban.harness.webclient.RunUploader.java Source code

Java tutorial

Introduction

Here is the source code for com.sun.faban.harness.webclient.RunUploader.java

Source

/* The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at
 * https://faban.dev.java.net/public/CDDLv1.0.html or
 * install_dir/license.txt
 * See the License for the specific language governing
 * permission and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at faban/src/legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * $Id$
 *
 * Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved
 */
package com.sun.faban.harness.webclient;

import com.sun.faban.harness.common.Config;
import com.sun.faban.harness.common.RunId;
import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import static com.sun.faban.harness.util.FileHelper.*;

/**
 * The RunUploader represents the upload servlet as well as an upload client
 * maintained in a single class.
 *
 * @author Akara Sucharitakul
 */
public class RunUploader extends HttpServlet {

    static Logger logger = Logger.getLogger(Deployer.class.getName());

    /**
     * Post method to upload the run.
     * @param request The servlet request
     * @param response The servlet response
     * @throws ServletException If the servlet fails
     * @throws IOException If there is an I/O error
     */
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String host = null;
        String key = null;
        boolean origin = false; // Whether the upload is to the original
        // run requestor. If so, key is needed.

        DiskFileUpload fu = new DiskFileUpload();
        // No maximum size
        fu.setSizeMax(-1);
        // maximum size that will be stored in memory
        fu.setSizeThreshold(4096);
        // the location for saving data that is larger than getSizeThreshold()
        fu.setRepositoryPath(Config.TMP_DIR);

        List fileItems = null;
        try {
            fileItems = fu.parseRequest(request);
        } catch (FileUploadException e) {
            throw new ServletException(e);
        }
        // assume we know there are two files. The first file is a small
        // text file, the second is unknown and is written to a file on
        // the server
        for (Iterator i = fileItems.iterator(); i.hasNext();) {
            FileItem item = (FileItem) i.next();
            String fieldName = item.getFieldName();
            if (item.isFormField()) {
                if ("host".equals(fieldName)) {
                    host = item.getString();
                } else if ("key".equals(fieldName)) {
                    key = item.getString();
                } else if ("origin".equals(fieldName)) {
                    String value = item.getString();
                    origin = Boolean.parseBoolean(value);
                }
                continue;
            }

            if (host == null) {
                logger.warning("Host not received on upload request!");
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
                break;
            }

            // The host, origin, key info must be here before we receive
            // any file.
            if (origin) {
                if (Config.daemonMode != Config.DaemonModes.POLLEE) {
                    logger.warning("Origin upload requested. Not pollee!");
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    break;
                }
                if (key == null) {
                    logger.warning("Origin upload requested. No key!");
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    break;
                }
                if (!RunRetriever.authenticate(host, key)) {
                    logger.warning("Origin upload requested. " + "Host/key mismatch: " + host + '/' + key + "!");
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    break;
                }
            }

            if (!"jarfile".equals(fieldName)) // ignore
                continue;

            String fileName = item.getName();

            if (fileName == null) // We don't process files without names
                continue;

            // Now, this name may have a path attached, dependent on the
            // source browser. We need to cover all possible clients...
            char[] pathSeparators = { '/', '\\' };
            // Well, if there is another separator we did not account for,
            // just add it above.

            for (int j = 0; j < pathSeparators.length; j++) {
                int idx = fileName.lastIndexOf(pathSeparators[j]);
                if (idx != -1) {
                    fileName = fileName.substring(idx + 1);
                    break;
                }
            }

            // Ignore all non-jarfiles.
            if (!fileName.toLowerCase().endsWith(".jar"))
                continue;
            File uploadFile = new File(Config.TMP_DIR, host + '.' + fileName);
            try {
                item.write(uploadFile);
            } catch (Exception e) {
                throw new ServletException(e);
            }
            File runTmp = unjarTmp(uploadFile);

            String runId = null;

            if (origin) {
                // Change origin file to know where this run came from.
                File metaInf = new File(runTmp, "META-INF");
                File originFile = new File(metaInf, "origin");
                if (!originFile.exists()) {
                    logger.warning("Origin upload requested. Origin file" + "does not exist!");
                    response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "Origin file does not exist!");
                    break;
                }

                RunId origRun;
                try {
                    origRun = new RunId(readStringFromFile(originFile).trim());
                } catch (IndexOutOfBoundsException e) {
                    response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE,
                            "Origin file error. " + e.getMessage());
                    break;
                }

                runId = origRun.getBenchName() + '.' + origRun.getRunSeq();
                String localHost = origRun.getHostName();
                if (!localHost.equals(Config.FABAN_HOST)) {
                    logger.warning("Origin upload requested. Origin host " + localHost
                            + " does not match this host " + Config.FABAN_HOST + '!');
                    response.sendError(HttpServletResponse.SC_FORBIDDEN);
                    break;
                }
                writeStringToFile(runTmp.getName(), originFile);
            } else {
                runId = runTmp.getName();
            }

            if (recursiveCopy(runTmp, new File(Config.OUT_DIR, runId))) {
                uploadFile.delete();
                recursiveDelete(runTmp);
            } else {
                logger.warning("Origin upload requested. Copy error!");
                response.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE);
                break;
            }

            response.setStatus(HttpServletResponse.SC_CREATED);
            break;
        }
    }

    /**
     * Client call to upload the run back to the originating server.
     * This method does nothing if the run is local.
     * @param runId The id of the run
     * @throws IOException If the upload fails
     */
    public static void uploadIfOrigin(String runId) throws IOException {

        // 1. Check origin
        File originFile = new File(
                Config.OUT_DIR + File.separator + runId + File.separator + "META-INF" + File.separator + "origin");

        if (!originFile.isFile())
            return; // Is local run, do nothing.

        String originSpec = readStringFromFile(originFile);
        int idx = originSpec.lastIndexOf('.');
        if (idx == -1) { // This is wrong, we do not accept this.
            logger.severe("Bad origin spec.");
            return;
        }
        idx = originSpec.lastIndexOf('.', idx - 1);
        if (idx == -1) {
            logger.severe("Bad origin spec.");
            return;
        }

        String host = originSpec.substring(0, idx);
        String key = null;
        URL target = null;
        String proxyHost = null;
        int proxyPort = -1;

        // Search the poll hosts for this origin.
        for (int i = 0; i < Config.pollHosts.length; i++) {
            Config.HostInfo pollHost = Config.pollHosts[i];
            if (host.equals(pollHost.name)) {
                key = pollHost.key;
                target = new URL(pollHost.url, "upload");
                proxyHost = pollHost.proxyHost;
                proxyPort = pollHost.proxyPort;
                break;
            }
        }

        if (key == null) {
            logger.severe("Origin host/url/key not found!");
            return;
        }

        // 2. Jar up the run
        String[] files = new File(Config.OUT_DIR, runId).list();
        File jarFile = new File(Config.TMP_DIR, runId + ".jar");
        jar(Config.OUT_DIR + runId, files, jarFile.getAbsolutePath());

        // 3. Upload the run
        ArrayList<Part> params = new ArrayList<Part>();
        //MultipartPostMethod post = new MultipartPostMethod(target.toString());
        params.add(new StringPart("host", Config.FABAN_HOST));
        params.add(new StringPart("key", key));
        params.add(new StringPart("origin", "true"));
        params.add(new FilePart("jarfile", jarFile));
        Part[] parts = new Part[params.size()];
        parts = params.toArray(parts);
        PostMethod post = new PostMethod(target.toString());
        post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
        HttpClient client = new HttpClient();
        if (proxyHost != null)
            client.getHostConfiguration().setProxy(proxyHost, proxyPort);
        client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        int status = client.executeMethod(post);
        if (status == HttpStatus.SC_FORBIDDEN)
            logger.severe("Server " + host + " denied permission to upload run " + runId + '!');
        else if (status == HttpStatus.SC_NOT_ACCEPTABLE)
            logger.severe("Run " + runId + " origin error!");
        else if (status != HttpStatus.SC_CREATED)
            logger.severe(
                    "Server responded with status code " + status + ". Status code 201 (SC_CREATED) expected.");
        jarFile.delete();
    }
}