
/* Author: Josh Holtrop
 * GVSU, CS654, Project 1
 * Date: 2008-03-11
 */

import java.io.*;
import java.net.*;
import java.util.*;

/* FileServer implements a multithreaded file server. The listening
 * server itself can be run in a thread, and each incoming connection
 * request to download a file is handled in its own thread, so that
 * multiple files can be downloaded at the same time, and so that
 * the entire server can run asynchronously from the main application.
 */
public class FileServer implements Runnable
{
    private int m_port;
    private String m_rootPath;
    private ServerSocket m_serverSocket;

    public FileServer(int port, String rootPath)
    {
        m_port = port;
        m_rootPath = rootPath;
    }

    public void run()
    {
        try {
            m_serverSocket = new ServerSocket(m_port);

            /* porcess connection requests */
            for (;;)
            {
                Socket clientSocket = m_serverSocket.accept();

                Thread thread = new Thread(new FileHandler(clientSocket));
                thread.start();
            }
        } catch (IOException ioe) {
            System.out.println("KaZaClient: IO Exception!");
            ioe.printStackTrace();
            return;
        }
    }

    /* a class to handle a single file upload */
    private class FileHandler implements Runnable
    {
        private Socket m_socket;

        public FileHandler(Socket socket)
        {
            m_socket = socket;
        }

        public void run()
        {
            try {
                processRequest();
            } catch (Exception e) { }
        }

        private void processRequest() throws Exception
        {
            DataOutputStream os = new DataOutputStream(
                                      m_socket.getOutputStream());
            BufferedReader br = new BufferedReader(
                                    new InputStreamReader(
                                        m_socket.getInputStream()));

            /* read the file name the client is requesting */
            String fileName = br.readLine();
            String absFileName = m_rootPath + File.separator + fileName;

            FileInputStream fis = null;
            try {
                fis = new FileInputStream(absFileName);
            } catch (Exception e) { }

            if (fis != null)
            {
                sendBytes(fis, os);
            }

            os.close();
            br.close();
            m_socket.close();
        }

        private void sendBytes(FileInputStream fis, OutputStream os)
            throws Exception
        {
            byte[] buff = new byte[1024];
            int bytes = 0;

            while ((bytes = fis.read(buff)) != -1)
            {
                os.write(buff, 0, bytes);
            }
        }
    }
}
