RequestHandler.java revision 3356:b99518745035
1231990Smp/*
259243Sobrien * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
359243Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
459243Sobrien *
559243Sobrien * This code is free software; you can redistribute it and/or modify it
659243Sobrien * under the terms of the GNU General Public License version 2 only, as
7231990Smp * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.tools.sjavac.server;
27
28import com.sun.tools.javac.main.Main;
29import com.sun.tools.sjavac.Log;
30import com.sun.tools.sjavac.Util;
31
32import java.io.BufferedReader;
33import java.io.InputStreamReader;
34import java.io.PrintWriter;
35import java.net.Socket;
36import java.nio.file.Path;
37
38import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC;
39
40
41/**
42 * A RequestHandler handles requests performed over a socket. Specifically it
43 *  - Reads the command string specifying which method is to be invoked
44 *  - Reads the appropriate arguments
45 *  - Delegates the actual invocation to the given sjavac implementation
46 *  - Writes the result back to the socket output stream
47 *
48 * None of the work performed by this class is really bound by the CPU. It
49 * should be completely fine to have a large number of RequestHandlers active.
50 * To limit the number of concurrent compilations, use PooledSjavac.
51 *
52 *  <p><b>This is NOT part of any supported API.
53 *  If you write code that depends on this, you do so at your own risk.
54 *  This code and its internal interfaces are subject to change or
55 *  deletion without notice.</b>
56 */
57public class RequestHandler extends Thread {
58
59    private final Socket socket;
60    private final Sjavac sjavac;
61
62    public RequestHandler(Socket socket, Sjavac sjavac) {
63        this.socket = socket;
64        this.sjavac = sjavac;
65    }
66
67    @Override
68    public void run() {
69
70        try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
71             PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
72
73            // Set up logging for this thread. Stream back logging messages to
74            // client on the format format "level:msg".
75            Log.setLogForCurrentThread(new Log(out, out) {
76                @Override
77                protected boolean isLevelLogged(Level l) {
78                    // Make sure it is up to the client to decide whether or
79                    // not this message should be displayed.
80                    return true;
81                }
82
83                @Override
84                protected void printLogMsg(Level msgLevel, String msg) {
85                    // Follow sjavac server/client protocol: Send one line
86                    // at a time and prefix with message with "level:".
87                    Util.getLines(msg)
88                        .map(line -> msgLevel + ":" + line)
89                        .forEach(line -> super.printLogMsg(msgLevel, line));
90                }
91            });
92
93            // Read argument array
94            int n = Integer.parseInt(in.readLine());
95            String[] args = new String[n];
96            for (int i = 0; i < n; i++) {
97                args[i] = in.readLine();
98            }
99
100            // If there has been any internal errors, notify client
101            checkInternalErrorLog();
102
103            // Perform compilation
104            Main.Result rc = sjavac.compile(args);
105
106            // Send return code back to client
107            out.println(LINE_TYPE_RC + ":" + rc.name());
108
109            // Check for internal errors again.
110            checkInternalErrorLog();
111        } catch (Exception ex) {
112            // Not much to be done at this point. The client side request
113            // code will most likely throw an IOException and the
114            // compilation will fail.
115            Log.error(ex);
116        } finally {
117            Log.setLogForCurrentThread(null);
118        }
119    }
120
121    private void checkInternalErrorLog() {
122        Path errorLog = ServerMain.getErrorLog().getLogDestination();
123        if (errorLog != null) {
124            Log.error("Server has encountered an internal error. See " + errorLog.toAbsolutePath()
125                    + " for details.");
126        }
127    }
128}
129