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