/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.ogt.http.localserver; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.Locale; import org.apache.ogt.http.HttpException; import org.apache.ogt.http.HttpRequest; import org.apache.ogt.http.HttpResponse; import org.apache.ogt.http.HttpStatus; import org.apache.ogt.http.MethodNotSupportedException; import org.apache.ogt.http.entity.AbstractHttpEntity; import org.apache.ogt.http.protocol.HttpContext; import org.apache.ogt.http.protocol.HttpRequestHandler; /** * A handler that generates random data. * * * * <!-- empty lines to avoid 'svn diff' problems --> */ public class RandomHandler implements HttpRequestHandler { // public default constructor /** * Handles a request by generating random data. * The length of the response can be specified in the request URI * as a number after the last /. For example /random/whatever/20 * will generate 20 random bytes in the printable ASCII range. * If the request URI ends with /, a random number of random bytes * is generated, but at least one. * * @param request the request * @param response the response * @param context the context * * @throws HttpException in case of a problem * @throws IOException in case of an IO problem */ public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException { String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH); if (!"GET".equals(method) && !"HEAD".equals(method)) { throw new MethodNotSupportedException (method + " not supported by " + getClass().getName()); } String uri = request.getRequestLine().getUri(); int slash = uri.lastIndexOf('/'); int length = -1; if (slash < uri.length()-1) { try { // no more than Integer, 2 GB ought to be enough for anybody length = Integer.parseInt(uri.substring(slash+1)); if (length < 0) { response.setStatusCode(HttpStatus.SC_BAD_REQUEST); response.setReasonPhrase("LENGTH " + length); } } catch (NumberFormatException nfx) { response.setStatusCode(HttpStatus.SC_BAD_REQUEST); response.setReasonPhrase(nfx.toString()); } } else { // random length, but make sure at least something is sent length = 1 + (int)(Math.random() * 79.0); } if (length >= 0) { response.setStatusCode(HttpStatus.SC_OK); if (!"HEAD".equals(method)) { RandomEntity entity = new RandomEntity(length); entity.setContentType("text/plain; charset=US-ASCII"); response.setEntity(entity); } else { response.setHeader("Content-Type", "text/plain; charset=US-ASCII"); response.setHeader("Content-Length", String.valueOf(length)); } } } // handle /** * An entity that generates random data. * This is an outgoing entity, it supports {@link #writeTo writeTo} * but not {@link #getContent getContent}. */ public static class RandomEntity extends AbstractHttpEntity { /** The range from which to generate random data. */ private final static byte[] RANGE; static { byte[] range = null; try { range = ("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" ).getBytes("US-ASCII"); } catch (UnsupportedEncodingException uex) { // never, US-ASCII is guaranteed } RANGE = range; } /** The length of the random data to generate. */ protected final long length; /** * Creates a new entity generating the given amount of data. * * @param len the number of random bytes to generate, * 0 to maxint */ public RandomEntity(long len) { if (len < 0L) throw new IllegalArgumentException ("Length must not be negative"); if (len > Integer.MAX_VALUE) throw new IllegalArgumentException ("Length must not exceed Integer.MAX_VALUE"); length = len; } /** * Tells that this entity is not streaming. * * @return false */ public final boolean isStreaming() { return false; } /** * Tells that this entity is repeatable, in a way. * Repetitions will generate different random data, * unless perchance the same random data is generated twice. * * @return <code>true</code> */ public boolean isRepeatable() { return true; } /** * Obtains the size of the random data. * * @return the number of random bytes to generate */ public long getContentLength() { return length; } /** * Not supported. * This method throws an exception. * * @return never anything */ public InputStream getContent() { throw new UnsupportedOperationException(); } /** * Generates the random content. * * @param out where to write the content to */ public void writeTo(OutputStream out) throws IOException { final int blocksize = 2048; int remaining = (int) length; // range checked in constructor byte[] data = new byte[Math.min(remaining, blocksize)]; while (remaining > 0) { final int end = Math.min(remaining, data.length); double value = 0.0; for (int i = 0; i < end; i++) { // we get 5 random characters out of one random value if (i%5 == 0) { value = Math.random(); } value = value * RANGE.length; int d = (int) value; value = value - d; data[i] = RANGE[d]; } out.write(data, 0, end); out.flush(); remaining = remaining - end; } out.close(); } // writeTo } // class RandomEntity } // class RandomHandler