com.sun.faban.harness.agent.Download.java Source code

Java tutorial

Introduction

Here is the source code for com.sun.faban.harness.agent.Download.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
 * http://www.sun.com/cddl/cddl.html or
 * install_dir/legal/LICENSE
 * 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 install_dir/legal/LICENSE.
 * 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.agent;

import com.sun.faban.harness.common.Config;
import com.sun.faban.harness.util.FileHelper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Logger;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;

/**
 * The benchmark loader is called by the command agent to download benchmarks
 * to the agent machine in order to drive the workload without manually having
 * to cope with distributing benchmark code.
 *
 * @author Akara Sucharitakul
 */
public class Download {

    static Logger logger = Logger.getLogger(Download.class.getName());
    byte[] buffer = new byte[8192];

    /**
     * Downloads benchmark.
     * @param benchmarkName
     * @param context
     * @throws java.io.IOException
     */
    public void loadBenchmark(String benchmarkName, String context) throws IOException {
        download(Config.BENCHMARK_DOWNLOAD_PATH, benchmarkName, Config.BENCHMARK_DIR, context);
    }

    /**
     * Downloads service.
     * @param serviceLocation
     * @param context
     * @throws java.io.IOException
     */
    public void loadService(String serviceLocation, String context) throws IOException {
        download(Config.SERVICE_DOWNLOAD_PATH, serviceLocation, Config.SERVICE_DIR, context);
    }

    private void download(String src, String name, String dest, String context) throws IOException {
        logger.fine("faban.download = " + context);
        if (context == null)
            return; // We are on the master. Just don't download
        if (!context.endsWith("/")) {
            context += '/';
        }

        File dir = new File(dest);
        if (dir.exists()) {
            if (!dir.isDirectory()) {
                String msg = dir.getName() + " is not a directory. Download terminated";
                logger.severe(msg);
                throw new IOException(msg);
            }
        } else {
            dir.mkdir();
        }
        dir = new File(dir, name);
        if (dir.exists()) {
            File runIdFile = new File(dir, "META-INF");
            runIdFile = new File(runIdFile, "RunID");
            if (runIdFile.exists() && (System.currentTimeMillis() - runIdFile.lastModified()) <= 60000)
                return; // Recent RunID file means the directory is shared.
                        // Don't download.

            FileHelper.recursiveDelete(dir);
        }
        URL url = new URL(context + src + name + '/');
        downloadDir(url, dir);
    }

    private void downloadDir(URL url, File dir) throws IOException {
        String dirName = dir.getName();
        logger.finer("Creating directory " + dirName + " from " + url.toString());
        dir.mkdir();

        GetMethod get = new GetMethod(url.toString());
        HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(2000);
        int status = client.executeMethod(get);
        if (status != HttpStatus.SC_OK)
            throw new IOException(
                    "Download request for " + url + " returned " + HttpStatus.getStatusText(status) + '.');
        InputStream stream = get.getResponseBodyAsStream();
        DirectoryParser parser = new DirectoryParser();

        int length = 0;
        int bufEnd = 0;
        while (length != -1) {
            length = stream.read(buffer, bufEnd, buffer.length - bufEnd);
            if (length != -1)
                bufEnd += length;
            if (bufEnd > buffer.length / 4 * 3 || length == -1) {
                if (!parser.parse(buffer, bufEnd)) {
                    String msg = "URL " + url.toString() + " is not a directory!";
                    logger.severe(msg);
                    throw new IOException(msg);
                }
                bufEnd = 0;
            }
        }
        stream.close();

        String[] entries = parser.getEntries();
        for (int i = 0; i < entries.length; i++) {
            String entry = entries[i];
            if ("META-INF/".equals(entry))
                continue;
            String name = entry.substring(0, entry.length() - 1);
            if (entry.endsWith("/")) { // Directory
                downloadDir(new URL(url, entry), new File(dir, name));
            } else {
                downloadFile(new URL(url, name), new File(dir, name));
            }
        }

    }

    private void downloadFile(URL url, File file) throws IOException {
        logger.finer("Downloading file " + url.toString());
        GetMethod get = new GetMethod(url.toString());
        HttpClient client = new HttpClient();
        client.getHttpConnectionManager().getParams().setConnectionTimeout(2000);
        int status = client.executeMethod(get);
        if (status != HttpStatus.SC_OK)
            throw new IOException(
                    "Download request for " + url + " returned " + HttpStatus.getStatusText(status) + '.');
        InputStream in = get.getResponseBodyAsStream();
        FileOutputStream out = new FileOutputStream(file);

        int length = in.read(buffer);
        while (length != -1) {
            out.write(buffer, 0, length);
            length = in.read(buffer);
        }
        out.flush();
        out.close();
        in.close();
    }

    static class DirectoryParser {
        static final byte[] HEADER = " Directory: ".getBytes();
        boolean headerRead = false;
        ArrayList entryList = new ArrayList();
        byte[] pending;
        int pendingLength = -1;

        boolean parse(byte[] buffer, int length) {
            int idx = 0;

            // Check the directory header
            if (!headerRead) {
                if (length <= HEADER.length)
                    return false;
                idx = 0;
                for (; idx < HEADER.length; idx++)
                    if (HEADER[idx] != buffer[idx])
                        return false;
                for (; buffer[idx] != '\n' && idx < length; idx++)
                    ; // Advance
                headerRead = true;
            } else if (pendingLength > 0) {
                for (; buffer[idx] != '\n' && idx < length; idx++)
                    ;
                System.arraycopy(buffer, 0, pending, pendingLength, idx);
                if (buffer[idx] == '\n') {
                    String entry = new String(pending, 0, pendingLength + idx);
                    entryList.add(entry);
                    logger.finest("Adding pending entry: " + entry);
                    pendingLength = -1;
                } else {
                    return true;
                }
            }
            for (;;) {
                int oldIdx = ++idx;
                for (; buffer[idx] != '\n' && idx < length; idx++)
                    ;
                if (buffer[idx] == '\n') {
                    if (idx == oldIdx)
                        break;
                    String entry = new String(buffer, oldIdx, idx - oldIdx);
                    entryList.add(entry);
                    logger.finest("Adding entry: " + entry);
                } else if (idx > oldIdx) {
                    if (pending == null)
                        pending = new byte[512];
                    pendingLength = idx - oldIdx - 1;
                    System.arraycopy(buffer, oldIdx, pending, 0, pendingLength);
                    break;
                } else {
                    break;
                }
            }
            return true;
        }

        String[] getEntries() {
            String[] entries = new String[entryList.size()];
            return (String[]) entryList.toArray(entries);
        }
    }
}