/******************************************************************************* * Copyright (c) 2009, Cloudsmith Inc and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cloudsmith Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.equinox.p2.testserver.servlets; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URI; import java.net.URLConnection; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.equinox.p2.testserver.LinearChange; /** * The ChopAndDelay deliver the content chopped up in smaller packets and adds delay * between packets. * */ public class ChopAndDelay extends BasicResourceDelivery { int chopFactor; private LinearChange delayFunction; private long msDelay; private int fastPercent; /** * Create a file molester that turns content into gibberish. * * @param theAlias the path this servlet is registered under * @param thePath the path to use as root for the alias * @param chopFactor - a value between 1 and 12 where 1 is one byte, and 12 is 4k bytes at a time. * @param delayFunction - function returning a series of delay values */ public ChopAndDelay(String theAlias, URI thePath, int chopFactor, int fastPercent, LinearChange delayFunction) { super(theAlias, thePath); if (chopFactor < 1 || chopFactor > 12) throw new IllegalArgumentException("chopFactor must be between 1 and 12 (inclusive) - was:" + Integer.valueOf(chopFactor)); //$NON-NLS-1$ this.chopFactor = chopFactor; if (fastPercent < 0 || fastPercent > 100) throw new IllegalArgumentException("fastPercent must be 0-100 - was:" + Integer.valueOf(fastPercent)); //$NON-NLS-1$ this.fastPercent = fastPercent; this.delayFunction = delayFunction; msDelay = 0L; this.delayFunction = delayFunction; if (this.delayFunction.hasNext()) msDelay = delayFunction.next(); } private static final long serialVersionUID = 1L; protected void deliver(URLConnection conn, InputStream in, String filename, HttpServletRequest request, HttpServletResponse response) throws IOException { // chop up all files doChop(conn, in, filename, request, response); } protected void doChop(URLConnection conn, InputStream in, String filename, HttpServletRequest request, HttpServletResponse response) throws IOException { LinearChange delayer = delayFunction.fork(); int contentlength = conn.getContentLength(); if (contentlength >= 0) { response.setContentLength(contentlength); String mimeType = computeMimeType(filename, conn); response.setContentType(mimeType); // We want to use a writer if we are sending text if (mimeType.startsWith("text/")) //$NON-NLS-1$ { PrintWriter writer = response.getWriter(); writer.flush(); /* write the headers and unbuffer the output */ BufferedReader reader = new BufferedReader(new InputStreamReader(in)); int chunksize = 1 << chopFactor; char buffer[] = new char[4096]; int read; int totalRead = 0; boolean delay = fastPercent == 0 ? true : false; while ((read = reader.read(buffer, 0, buffer.length)) != -1) { int nChunks = read / chunksize + (read % chunksize > 0 ? 1 : 0); for (int i = 0; i < nChunks; i++) { writer.write(buffer, i * chunksize, Math.min(chunksize, read - i * chunksize)); writer.flush(); if (delay && msDelay > 0) try { Thread.sleep(msDelay); } catch (InterruptedException e) { // ignore } if (delay && delayer.hasNext()) msDelay = delayer.next(); } totalRead += read; if (totalRead > contentlength * fastPercent / 100) delay = true; } } else { ServletOutputStream out = response.getOutputStream(); out.flush(); /* write the headers and unbuffer the output */ int chunksize = 1 << chopFactor; byte buffer[] = new byte[4096]; int read; int totalRead = 0; boolean delay = fastPercent == 0 ? true : false; while ((read = in.read(buffer, 0, buffer.length)) != -1) { int nChunks = read / chunksize + (read % chunksize > 0 ? 1 : 0); for (int i = 0; i < nChunks; i++) { out.write(buffer, i * chunksize, Math.min(chunksize, read - i * chunksize)); out.flush(); if (delay && msDelay > 0) try { Thread.sleep(msDelay); } catch (InterruptedException e) { // ignore } if (delay && delayer.hasNext()) msDelay = delayer.next(); } totalRead += read; if (totalRead > contentlength * fastPercent / 100) delay = true; } } } } }