net.fenyo.gnetwatch.actions.ActionHTTP.java Source code

Java tutorial

Introduction

Here is the source code for net.fenyo.gnetwatch.actions.ActionHTTP.java

Source

/*
 * GNetWatch
 * Copyright 2006, 2007, 2008 Alexandre Fenyo
 * gnetwatch@fenyo.net
 *
 * This file is part of GNetWatch.
 *
 * GNetWatch is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * GNetWatch is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNetWatch; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package net.fenyo.gnetwatch.actions;

import net.fenyo.gnetwatch.*;
import net.fenyo.gnetwatch.actions.Action.InterruptCause;
import net.fenyo.gnetwatch.activities.Background;
import net.fenyo.gnetwatch.data.*;
import net.fenyo.gnetwatch.targets.*;

import java.io.*;
import java.net.*;
import javax.net.ssl.*;
import java.util.Arrays;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;

/**
 * Instances of this action class can load any HTTP server
 * and create events of type EventHTTP to log the throughput.
 * @author Alexandre Fenyo
 * @version $Id: ActionHTTP.java,v 1.14 2008/04/27 21:44:21 fenyo Exp $
 */

public class ActionHTTP extends Action {
    private static Log log = LogFactory.getLog(ActionHTTP.class);

    private boolean interrupted = false;

    private String error_string = "";

    /**
     * Constructor.
     * @param target target this action works on.
     * @param background queue manager by which this action will add events.
     */
    // GUI thread
    // supports any thread
    public ActionHTTP(final Target target, final Background background) {
        super(target, background);
        setItem("http");
    }

    /**
     * Default constructor.
     * @param none.
     */
    // GUI thread
    // supports any thread
    public ActionHTTP() {
        setItem("http");
    }

    /**
     * Returns the preferred queue.
     * @param none.
     * @return String preferred queue.
     */
    // any thread
    public String getQueueName() {
        return "http";
    }

    /**
     * Returns the timeout associated with this action.
     * @param none.
     * @return long timeout.
     */
    // any thread
    // bug : au bout de ce tps en ms ca s'arrete
    public long getMaxDelay() {
        return 30000000;
    }

    /**
     * Asks this action to stop rapidely.
     * @param cause cause.
     * @return void.
     * @throws IOException IO exception.
     */
    // main & Background threads
    // supports any thread
    public void interrupt(final InterruptCause reason) {
        interrupted = true;
    }

    /**
     * Establishes the connections to the server.
     * @param idx number of connections to establish.
     * @param querier http/ftp parameters.
     * @param connections array of connections established.
     * @param streams streams associated to the connections.
     * @param sizes data sizes ready to be read on the connections.
     * @param url url to connect to.
     * @param proxy proxy to use.
     * @return number of bytes received.
     * @throws IOException IO exception.
     */
    private int connect(final int idx, final IPQuerier querier, final URLConnection[] connections,
            final InputStream[] streams, final int[] sizes, final URL url, final Proxy proxy) throws IOException {
        error_string = "";
        try {
            connections[idx] = querier.getUseProxy() ? url.openConnection(proxy) : url.openConnection();
            connections[idx].setUseCaches(false);
            connections[idx].connect();
            streams[idx] = connections[idx].getInputStream();
            sizes[idx] = connections[idx].getContentLength();

        } catch (final IOException ex) {

            streams[idx] = null;
            sizes[idx] = 0;

            int response_code = 0;
            try {
                response_code = ((HttpURLConnection) connections[idx]).getResponseCode();
            } catch (final ConnectException ex2) {
                getGUI().appendConsole(ex2.toString() + "<BR/>");
                try {
                    Thread.sleep(1000);
                } catch (final InterruptedException ex3) {
                }

                throw ex2;
            }

            error_string = "(http error " + response_code + ")";
            final InputStream error_stream = ((HttpURLConnection) connections[idx]).getErrorStream();
            if (error_stream == null)
                return 0;
            int nread, nread_tot = 0;
            String error_str = "";
            final byte[] error_buf = new byte[65536];
            while ((nread = error_stream.read(error_buf)) > 0) {
                //        log.debug("error: " + new String(error_buf).substring(0, nread - 1));
                error_str += new String(error_buf);
                nread_tot += nread;
            }
            error_stream.close();
            return nread_tot;
        }
        return 0;
    }

    /**
     * Loads the server.
     * @param none.
     * @return void.
     * @throws IOException IO exception.
     * @throws InterruptedException exception.
     * @see http://java.sun.com/j2se/1.5.0/docs/guide/net/http-keepalive.html
     */
    // Queue thread
    // supports any thread
    public void invoke() throws IOException, InterruptedException {
        if (isDisposed() == true)
            return;

        try {
            super.invoke();

            IPQuerier querier;
            synchronized (getGUI().getSynchro()) {
                if (TargetIPv4.class.isInstance(getTarget())) {
                    querier = (IPQuerier) ((TargetIPv4) getTarget()).getIPQuerier().clone();
                } else if (TargetIPv6.class.isInstance(getTarget())) {
                    querier = (IPQuerier) ((TargetIPv6) getTarget()).getIPQuerier().clone();
                } else
                    return;
            }

            final URL url = new URL(querier.getURL());
            final Proxy proxy = querier.getUseProxy()
                    ? new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress(querier.getProxyHost(), querier.getProxyPort()))
                    : null;

            URLConnection[] connections = new URLConnection[querier.getNParallel()];
            InputStream[] streams = new InputStream[querier.getNParallel()];
            int[] sizes = new int[querier.getNParallel()];

            for (int idx = 0; idx < querier.getNParallel(); idx++)
                connect(idx, querier, connections, streams, sizes, url, proxy);

            final byte[] buf = new byte[65536];
            long last_time = System.currentTimeMillis();
            int bytes_received = 0;
            int pages_received = 0;

            while (true) {
                int available_for_every_connections = 0;

                for (int idx = 0; idx < querier.getNParallel(); idx++) {

                    final int available = (streams[idx] != null) ? streams[idx].available() : 0;
                    available_for_every_connections += available;

                    if (available == 0) {
                        if (sizes[idx] == 0) {
                            if (streams[idx] != null)
                                streams[idx].close();
                            bytes_received += connect(idx, querier, connections, streams, sizes, url, proxy);
                            pages_received++;
                        }
                    } else {
                        final int nread = streams[idx].read(buf);
                        switch (nread) {
                        case -1:
                            streams[idx].close();
                            connect(idx, querier, connections, streams, sizes, url, proxy);
                            pages_received++;
                            break;

                        case 0:
                            log.error("0 byte read");
                            for (InputStream foo : streams)
                                if (foo != null)
                                    foo.close();
                            return;

                        default:
                            //              log.debug("read: " + new String(buf).substring(0, nread - 1));
                            bytes_received += nread;
                            sizes[idx] -= nread;
                        }
                    }

                    if (System.currentTimeMillis() - last_time > 1000) {
                        synchronized (getGUI().getSynchro()) {
                            synchronized (getGUI().sync_tree) {
                                final Session session = getGUI().getSynchro().getSessionFactory()
                                        .getCurrentSession();
                                session.beginTransaction();
                                try {
                                    session.update(this);

                                    getTarget()
                                            .addEvent(new EventHTTP(new Double(((double) 8 * 1000 * bytes_received)
                                                    / (System.currentTimeMillis() - last_time)).intValue()));

                                    getTarget()
                                            .addEvent(new EventHTTPPages(new Double(((double) 1000 * pages_received)
                                                    / (System.currentTimeMillis() - last_time)).intValue()));

                                    setDescription(GenericTools.formatNumericString(getGUI().getConfig(),
                                            "" + new Double(((double) 8 * 1000 * bytes_received)
                                                    / (System.currentTimeMillis() - last_time)).intValue())
                                            + " bit/s ("
                                            + GenericTools.formatNumericString(getGUI().getConfig(),
                                                    "" + new Double(((double) 1000 * pages_received)
                                                            / (System.currentTimeMillis() - last_time)).intValue())
                                            + " pages/sec)");
                                    getGUI().setStatus(getGUI().getConfig().getPattern("bytes_http", bytes_received,
                                            querier.getAddress().toString().substring(1)) + " " + error_string);

                                    last_time = System.currentTimeMillis();
                                    bytes_received = 0;
                                    pages_received = 0;

                                    session.getTransaction().commit();
                                } catch (final Exception ex) {
                                    log.error("Exception", ex);
                                    session.getTransaction().rollback();
                                }
                            }
                        }
                    }

                    if (interrupted == true) {
                        for (InputStream foo : streams)
                            if (foo != null)
                                foo.close();
                        return;
                    }
                }
                if (available_for_every_connections == 0)
                    Thread.sleep(10);
            }
        } catch (final InterruptedException ex) {
            log.error("Exception", ex);
        }
    }

    /**
     * Called when this element is being removed.
     * @param none.
     * @return void.
     */
    protected void disposed() {
        // remove us from the flood queue
        super.disposed();

        // interrupt if currently running
        interrupt(InterruptCause.removed);
    }
}