Newer
Older
ServerTester / src / main / java / info / istlab / ServerTester / WebServer.java
package info.istlab.ServerTester;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class WebServer extends Server {

    public WebServer() {
        this(8081, "127.0.0.1");
    }

    public WebServer(int port) {
        this(port, "127.0.0.1");
    }

    public WebServer(String bindaddress) {
        this(8081, bindaddress);
    }

    public WebServer(int port, String bindaddress) {
        super(port, bindaddress);
        start();
    }

    File rootdir;

    public void handleRequest() {
        rootdir = new File(System.getProperty("user.dir"));

        // boolean askDocRoot = true; // ドキュメントルートをユーザが選べるようにする
        boolean askDocRoot = false; // ドキュメントルートは固定
        if (askDocRoot) {
            askDocRoot();
        } else {
            System.out.println(
                    "[Web] ドキュメントルートは " + rootdir.getAbsolutePath()
                            + " です。起動時に変更する場合は、WebServer.java のソースコードを編集し、askDocRootをtrueにしてください。");
            File[] files = rootdir.listFiles();
            System.out.println("[Web] ドキュメントルートのファイル一覧");
            for (File file : files) {
                System.out.println("[Web] " + file.getName());
            }
        }

        while (thread != null) {
            try {
                Socket socket = serverSocket.accept();
                // System.out.println("---\nConnection Requst from: " +
                // (socket.getInetAddress()));
                new RequestHandler(socket, rootdir);
            } catch (SocketException sx) {
                thread = null;
            } catch (IOException e) {
                thread = null;
            }
        }
    }

    public void askDocRoot() {
        SwingUtilities.invokeLater(() -> {
            JOptionPane.showMessageDialog(Host.mainhost,
                    "ドキュメントルートとなるフォルダを、次の画面で選択してください。\n\n選択しなかった場合、以下のフォルダがドキュメントルートとなります。\n"
                            + System.getProperty("user.dir"),
                    "WebServer - ドキュメントルートの選択", JOptionPane.INFORMATION_MESSAGE);
            JFileChooser chooser = new JFileChooser(rootdir.getParentFile());
            // フォルダのみを選択できるように設定
            chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            // ダイアログを表示して、ユーザーの操作を待つ
            chooser.setDialogTitle("WebServer ドキュメントルートの選択");
            int returnValue = chooser.showOpenDialog(Host.mainhost);

            // ユーザーが「OK」をクリックした場合
            if (returnValue == JFileChooser.APPROVE_OPTION) {
                rootdir = chooser.getSelectedFile();
            } else {
                rootdir = new File(System.getProperty("user.dir"));
            }
            JOptionPane.showMessageDialog(Host.mainhost, "ドキュメントルートを " + rootdir.getAbsolutePath()
                    + " に設定しました。");

            File[] files = rootdir.listFiles();
            System.out.println("[Web] ドキュメントルートのファイル一覧");
            for (File file : files) {
                System.out.println("[Web] " + file.getName());
            }
        });
    }

    public static void main(String[] args) {
        invokeMain(args, "WebServer");
    }
}

class RequestHandler implements Runnable {
    Socket sock;
    Thread thread;

    // 入出力
    File rootDir;
    DataOutputStream dostr;
    BufferedReader in;
    FileInputStream infile = null;
    byte[] buff = new byte[1024];
    String filename;

    RequestHandler(Socket s, File dir) {
        sock = s;
        rootDir = dir;
        // this.file = "/"dir.getName() + "/index.html";
        thread = new Thread(this);
        thread.start();
    }

    public void run() {
        try {
            process();
        } catch (IOException e) {
            e.printStackTrace();
        }
        thread = null;
    }

    void process() throws IOException {
        System.out.println("---[Web start]\n[Web] Connection Requst from: " + (sock.getInetAddress()));
        // 読み書き用オブジェクトの生成
        in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
        dostr = new DataOutputStream(sock.getOutputStream());
        // read headers
        StringBuffer request = new StringBuffer();
        String line;
        String[] get = null; // GETリクエストをスペースで区切った配列
        while ((line = in.readLine()) != null) {
            System.out.println("[Web] " + line);
            // 先頭がGETだったら
            if (line.toLowerCase().startsWith("get ")) {
                get = line.split(" "); // GET / HTTP/1.1 をスペースで区切った配列get を得る
            }
            request.append(line + "\r\n");
            if (line.length() < 1)
                break;
        }

        String CRLF = "\r\n";
        // Response Headerの出力
        String response = "HTTP/1.1 200" + CRLF + "Content-type: text/html; charset=UTF-8" + CRLF + CRLF;
        String content = null;
        if (get == null) { // GETリクエストではない場合
        } else if (get[1].endsWith(".ico")) {
            // もし、リクエストがfaviconだったら
            response = "HTTP/1.1 200" + CRLF + "Content-type: image/x-icon" + CRLF + CRLF;
        } else if (get[1].endsWith(".java")) {
            response = "HTTP/1.1 200" + CRLF + "Content-type: text/plain; charset=UTF-8" + CRLF + CRLF;
        } else if (get[1].endsWith(".jpg")) {
            response = "HTTP/1.1 200" + CRLF + "Content-type: image/jpeg;" + CRLF + CRLF;
        } else if (get[1].endsWith(".png")) {
            response = "HTTP/1.1 200" + CRLF + "Content-type: image/png;" + CRLF + CRLF;
        } else {
        }
        filename = get[1].substring(1);
        // System.out.println(file);
        // オブジェクトinfileを作り,ファイルを準備します
        File target = new File(rootDir, filename);
        if (target.isDirectory()) {
            // ディレクトリインデックスの生成
            File[] files = target.listFiles();
            content = "<h1>Index of " + filename + "/" + "</h1>\n";
            content += "<pre>\n";
            for (File file : files) {
                content += "  <a href=\"" + file.getAbsolutePath().replace(rootDir.getAbsolutePath(), "") + "\">"
                        + file.getName() + "</a>\n";
            }
            // if (filename.indexOf("/") > -1){
            // String parent = filename.substring(0, filename.lastIndexOf("/",
            // filename.length()-1));
            // System.out.println(parent);
            // content += "\n <a href=\"/"+parent+"\" >.. (Parent Directory)</a>\n";
            // }
            content += "</pre>\n";

        } else if (!target.exists()) {
            // ファイル準備の失敗
            System.err.println(filename + " ファイルがありません");
            response = "HTTP/1.1 404" + CRLF + CRLF;
        } else {
            infile = new FileInputStream(rootDir.getAbsolutePath()+File.separator+filename);
        }

        // Response Headerの出力
        dostr.write(response.getBytes());
        // Response Bodyの出力
        if (content != null) {
            dostr.write(content.getBytes());
        } else if (get[1].endsWith(".php")) {
            // PHPの場合
            ProcessBuilder pb = new ProcessBuilder("php", filename);
            Process p = pb.start();
            BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line2;
            while ((line2 = br.readLine()) != null) {
                dostr.write(line2.getBytes());
            }
        } else if (infile != null) {
            boolean cont = true;
            while (cont) {
                // ファイルからの読み込み
                try {
                    int n = infile.read(buff);
                    dostr.write(buff, 0, n);
                } catch (Exception e) { // end of file
                    cont = false;
                }
            }
        }

        // if (file.endsWith("index.html")) {
        // // おまけ:レスポンスヘッダを表示
        // dostr.write(request.toString().getBytes());
        // // おまけ:時刻表示
        // dostr.write("</pre> \n\n <h2>Current DateTime
        // (Thttpdが動的に生成した情報)</h2>".getBytes());
        // dostr.write(LocalDateTime.now().toString().getBytes());
        // }
        System.out.println("---[Web end]");
        // 接続終了
        sock.close();
        if (infile != null)
            infile.close();
    }
}