/*
 * $Header: /home/cvspublic/jakarta-slide/proposals/tamino/testsuite/junit/store/org/apache/slide/store/tamino/testtools/sniffer/SnifferProxyServer.java,v 1.1 2004/03/25 16:18:15 juergen Exp $
 * $Revision: 1.1 $
 * $Date: 2004/03/25 16:18:15 $
 *
 * ====================================================================
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.
 */

package org.apache.slide.store.tamino.testtools.sniffer;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.slide.store.tamino.testtools.logger.Logger;


public final class SnifferProxyServer extends Thread{
    
    
    protected String     host;
    protected String     fileName;
    protected int        remoteport;
    protected int        localport;
    private ServerSocket ss;
    private int          maxClient = 250;
    protected int        counterClient = 0;
    private boolean      bStop = false;
    private String       setup = "ProxyConfig";
    private SnifferAdmin admin;
    
    private String filePath = null;
    private boolean fileOpen = false;
    SnifferProxyClient client = null;
    private Logger logger;
    
    
    /********************************************************************************
     ** HTTPProxyServer
     ** @pre
     ** @post
     ** @param       admin
     ** @param       host
     ** @param       remoteport
     ** @param       localport
     ********************************************************************************/
    public SnifferProxyServer(SnifferAdmin admin, String host, int remoteport, int localport, Logger logger, String fileName) {
        set(host, remoteport, localport, fileName);
        this.admin = admin;
        this.logger = logger;
    }
    
    
    /********************************************************************************
     ** HTTPProxyServer
     ** @pre
     ** @post
     ** @param       admin
     ** @param       filename
     ********************************************************************************/
    public SnifferProxyServer(SnifferAdmin admin, String filename) {
        this.admin = admin;
        if ( filename != null ) setup = filename;
        try {
            FileInputStream fis = new FileInputStream(setup);
            GZIPInputStream gzis = new GZIPInputStream(fis);
            ObjectInputStream in = new ObjectInputStream(gzis);
            host = (String)in.readObject();
            remoteport = ((Integer)in.readObject()).intValue();
            localport = ((Integer)in.readObject()).intValue();
            fileName = (String)in.readObject();
            in.close();
        }
        catch (Exception e) {
            host       = "localhost";
            remoteport = 7575;
            localport  = 5555;
            fileName = "";
        }
    }
    
    
    /********************************************************************************
     ** set
     ** @pre
     ** @post
     ** @param       host
     ** @param       remoteport
     ** @param       localport
     ********************************************************************************/
    public void set(String host, int remoteport, int localport,String fileName){
        this.host = host;
        this.remoteport = remoteport;
        this.localport  = localport;
        this.fileName = fileName;
    }
    
    
    /********************************************************************************
     ** save
     ** @pre
     ** @post
     ********************************************************************************/
    private void save(){
        try {
            FileOutputStream fos = new FileOutputStream(setup);
            GZIPOutputStream gzos = new GZIPOutputStream(fos);
            ObjectOutputStream out = new ObjectOutputStream(gzos);
            out.writeObject(host);
            out.writeObject(new Integer(remoteport));
            out.writeObject(new Integer(localport));
            out.writeObject(fileName);
            out.flush();
            out.close();
        }
        catch (IOException e) {}
    }
    
    /********************************************************************************
     ** run
     ** @pre
     ** @post
     ********************************************************************************/
    public void run(){
        try {
            ss = new ServerSocket (localport);
            ss.setSoTimeout(600000);
        }
        catch (Exception e) {
            admin.httpStop();
            e.printStackTrace();
            return;
        }
        
        Socket socket = null;
        try{
            while(true){                //wait clients
                if(!bStop && counterClient < maxClient){
                    for ( socket = null; !bStop && socket == null; ){
                        try {
                            socket = ss.accept();
                        }
                        catch (java.io.InterruptedIOException e) {}
                    }
                    if (!bStop){
                        InputStream in = socket.getInputStream();
                        OutputStream out = socket.getOutputStream();
                        client = new SnifferProxyClient( in, out, socket, host, remoteport, fileOpen, logger );
                        setCounterClient(true);
                        admin.refresh();
                        Thread  proxy = new Thread() {
                            public void run() {
                                client.job();
                                setCounterClient(false);
                            }
                        };
                        
                        proxy.start();
                        
                    }
                    else
                        try {
                            socket.close();
                        }
                    catch (Exception e){
                    }
                }//end of if
                else{
                    try{
                        sleep(3000);
                    }
                    catch(Exception e){}
                }
            }//end of true-loop
        }
        catch(Exception ex){
            if(!bStop){
                shutdown();
            }
        }
        save();
    }//end of run()
    
    
    /********************************************************************************
     ** setCounterClient
     ** @pre
     ** @post
     ** @param       add
     ********************************************************************************/
    private synchronized void setCounterClient(boolean add){
        if (add)
            counterClient++;
        else counterClient--;
    }
    
    
    /********************************************************************************
     ** shutdown
     ** @pre
     ** @post
     ********************************************************************************/
    public void shutdown(){
        bStop = true;
        try {
            ss.close();
        }
        catch(Exception ee){
        }
    }
}
