Java tutorial
/* 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); } } }