001/*
002 * This file is part of McIDAS-V
003 *
004 * Copyright 2007-2015
005 * Space Science and Engineering Center (SSEC)
006 * University of Wisconsin - Madison
007 * 1225 W. Dayton Street, Madison, WI 53706, USA
008 * https://www.ssec.wisc.edu/mcidas
009 * 
010 * All Rights Reserved
011 * 
012 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
013 * some McIDAS-V source code is based on IDV and VisAD source code.  
014 * 
015 * McIDAS-V is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU Lesser Public License as published by
017 * the Free Software Foundation; either version 3 of the License, or
018 * (at your option) any later version.
019 * 
020 * McIDAS-V is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU Lesser Public License for more details.
024 * 
025 * You should have received a copy of the GNU Lesser Public License
026 * along with this program.  If not, see http://www.gnu.org/licenses.
027 */
028
029package edu.wisc.ssec.mcidasv;
030
031import ucar.unidata.idv.IntegratedDataViewer;
032import ucar.unidata.util.HttpServer;
033import ucar.unidata.util.LogUtil;
034
035import java.util.Hashtable;
036
037
038import java.net.InetAddress;
039import java.net.Socket;
040
041
042
043/**
044 * This provides http based access to a stack trace and enables the user to shut down McIDAS-V.
045 * This only is responsive to incoming requests from localhost
046 * the urls this provides are:
047 * http://localhost:<port>/stack.html
048 * http://localhost:<port>/info.html
049 * http://localhost:<port>/shutdown.html
050 *
051 * @author IDV development team
052 */
053public class McIDASVMonitor extends HttpServer {
054
055    private IntegratedDataViewer idv;
056
057    /** The localhost */
058    private InetAddress localHost;
059
060    public McIDASVMonitor(IntegratedDataViewer idv, int port) {
061        super(port);
062        this.idv = idv;
063    }
064
065    /**
066     * Make the handler for this request. Check if the client is coming from localhost
067     * if not then return null.
068     *
069     * @param socket incoming socket
070     * @return handler or null
071     */
072    protected RequestHandler doMakeRequestHandler(Socket socket)
073            throws Exception {
074        if (localHost == null) {
075            localHost = InetAddress.getLocalHost();
076        }
077        InetAddress inet = socket.getInetAddress();
078        if (! (inet.getHostAddress().equals("127.0.0.1") || inet.getHostName().equals("localhost"))) {
079            return null;
080        }
081        return new MonitorRequestHandler(idv, this, socket);
082    }
083
084    /**
085     * Class OneInstanceRequestHandler the handler
086     *
087     *
088     * @author IDV Development Team
089     * @version $Revision$
090     */
091    public class MonitorRequestHandler extends HttpServer.RequestHandler {
092
093        /** The idv */
094        IntegratedDataViewer idv;
095        
096        /** The socket */
097        Socket mysocket;
098
099        /**
100         * ctor
101         *
102         * @param idv the idv
103         * @param server the server
104         * @param socket the socket we handle the connection of
105         *
106         * @throws Exception On badness
107         */
108        public MonitorRequestHandler(IntegratedDataViewer idv,
109                                         HttpServer server, Socket socket)
110                throws Exception {
111            super(server, socket);
112            this.idv = idv;
113            this.mysocket = socket;
114        }
115
116        /**
117         * Try to trap the case where the socket doesn't contain any bytes
118         * This can happen when mcservl connects to ping
119         * Prevents an infinite loop in HttpServer
120         */
121        public void run() {
122            try {
123                int availableBytes = mysocket.getInputStream().available();
124                if (availableBytes != 0) {
125                        super.run();
126                }
127                mysocket.close();
128            } catch (Exception e) {
129                System.err.println("HTTP server error");
130            }
131        }
132        
133        private void decorateHtml(StringBuffer sb) throws Exception {
134            String header = "<h1>McIDAS-V HTTP monitor</h1><hr>" +
135                "<a href=stack.html>Stack Trace</a>&nbsp;|&nbsp;" +
136                "<a href=info.html>System Information</a>&nbsp;|&nbsp;" +
137                "<a href=shutdown.html>Shut Down</a><hr>";
138            writeResult(true,  header+sb.toString(),"text/html");
139        }
140
141        /**
142         *
143         * @param path url path. ignored.
144         * @param formArgs form args
145         * @param httpArgs http args
146         * @param content content. unused.
147         *
148         * @throws Exception On badness
149         */
150        protected void handleRequest(String path, Hashtable formArgs,
151                                     Hashtable httpArgs, String content)
152                throws Exception {
153                if (path.equals("/stack.html")) {
154                        StringBuffer stack = LogUtil.getStackDump(true);
155                        decorateHtml(stack);
156                }
157                else if (path.equals("/info.html")) {
158                        StringBuffer extra   = idv.getIdvUIManager().getSystemInfo();
159                        extra.append("<H3>Data Sources</H3>");
160                        extra.append("<div style=\"margin-left:20px;\">");
161                        extra.append(idv.getDataManager().getDataSourceHtml());
162                        extra.append("</div>");
163                        extra.append(idv.getPluginManager().getPluginHtml());
164                        extra.append(idv.getResourceManager().getHtmlView());
165                        decorateHtml(extra);
166                }
167                else if (path.equals("/shutdown.html")) {
168                        decorateHtml(new StringBuffer("<a href=\"reallyshutdown.html\">Shut down McIDAS-V</a>"));
169                }
170                else if (path.equals("/reallyshutdown.html")) {
171                        writeResult(true, "McIDAS-V is shutting down","text/html");
172                        System.exit(0);
173                }
174                else if (path.equals("/") || path.equals("/index.html")) {
175                        decorateHtml(new StringBuffer(""));
176                }
177                else {
178                        decorateHtml(new StringBuffer("Unknown url:" + path));
179                }
180        }
181    }
182
183}