001    /*
002     * $Id: McIDASVMonitor.java,v 1.9 2012/02/19 17:35:53 davep Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
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     */
030    
031    package edu.wisc.ssec.mcidasv;
032    
033    import ucar.unidata.idv.IntegratedDataViewer;
034    import ucar.unidata.util.HttpServer;
035    import ucar.unidata.util.LogUtil;
036    
037    import java.util.Hashtable;
038    
039    
040    import java.net.InetAddress;
041    import java.net.Socket;
042    
043    
044    
045    /**
046     * This provides http based access to a stack trace and enables the user to shut down McIDAS-V.
047     * This only is responsive to incoming requests from localhost
048     * the urls this provides are:
049     * http://localhost:<port>/stack.html
050     * http://localhost:<port>/info.html
051     * http://localhost:<port>/shutdown.html
052     *
053     * @author IDV development team
054     */
055    public class McIDASVMonitor extends HttpServer {
056    
057        private IntegratedDataViewer idv;
058    
059        /** The localhost */
060        private InetAddress localHost;
061    
062        public McIDASVMonitor(IntegratedDataViewer idv, int port) {
063            super(port);
064            this.idv = idv;
065        }
066    
067        /**
068         * Make the handler for this request. Check if the client is coming from localhost
069         * if not then return null.
070         *
071         * @param socket incoming socket
072         * @return handler or null
073         */
074        protected RequestHandler doMakeRequestHandler(Socket socket)
075                throws Exception {
076            if (localHost == null) {
077                localHost = InetAddress.getLocalHost();
078            }
079            InetAddress inet = socket.getInetAddress();
080            if (! (inet.getHostAddress().equals("127.0.0.1") || inet.getHostName().equals("localhost"))) {
081                return null;
082            }
083            return new MonitorRequestHandler(idv, this, socket);
084        }
085    
086        /**
087         * Class OneInstanceRequestHandler the handler
088         *
089         *
090         * @author IDV Development Team
091         * @version $Revision: 1.9 $
092         */
093        public class MonitorRequestHandler extends HttpServer.RequestHandler {
094    
095            /** The idv */
096            IntegratedDataViewer idv;
097            
098            /** The socket */
099            Socket mysocket;
100    
101            /**
102             * ctor
103             *
104             * @param idv the idv
105             * @param server the server
106             * @param socket the socket we handle the connection of
107             *
108             * @throws Exception On badness
109             */
110            public MonitorRequestHandler(IntegratedDataViewer idv,
111                                             HttpServer server, Socket socket)
112                    throws Exception {
113                super(server, socket);
114                this.idv = idv;
115                this.mysocket = socket;
116            }
117    
118            /**
119             * Try to trap the case where the socket doesn't contain any bytes
120             * This can happen when mcservl connects to ping
121             * Prevents an infinite loop in HttpServer
122             */
123            public void run() {
124                try {
125                    int availableBytes = mysocket.getInputStream().available();
126                    if (availableBytes != 0) {
127                            super.run();
128                    }
129                    mysocket.close();
130                } catch (Exception e) {
131                    System.err.println("HTTP server error");
132                }
133            }
134            
135            private void decorateHtml(StringBuffer sb) throws Exception {
136                String header = "<h1>McIDAS-V HTTP monitor</h1><hr>" +
137                    "<a href=stack.html>Stack Trace</a>&nbsp;|&nbsp;" +
138                    "<a href=info.html>System Information</a>&nbsp;|&nbsp;" +
139                    "<a href=shutdown.html>Shut Down</a><hr>";
140                writeResult(true,  header+sb.toString(),"text/html");
141            }
142    
143            /**
144             *
145             * @param path url path. ignored.
146             * @param formArgs form args
147             * @param httpArgs http args
148             * @param content content. unused.
149             *
150             * @throws Exception On badness
151             */
152            protected void handleRequest(String path, Hashtable formArgs,
153                                         Hashtable httpArgs, String content)
154                    throws Exception {
155                    if (path.equals("/stack.html")) {
156                            StringBuffer stack = LogUtil.getStackDump(true);
157                            decorateHtml(stack);
158                    }
159                    else if (path.equals("/info.html")) {
160                            StringBuffer extra   = idv.getIdvUIManager().getSystemInfo();
161                            extra.append("<H3>Data Sources</H3>");
162                            extra.append("<div style=\"margin-left:20px;\">");
163                            extra.append(idv.getDataManager().getDataSourceHtml());
164                            extra.append("</div>");
165                            extra.append(idv.getPluginManager().getPluginHtml());
166                            extra.append(idv.getResourceManager().getHtmlView());
167                            decorateHtml(extra);
168                    }
169                    else if (path.equals("/shutdown.html")) {
170                            decorateHtml(new StringBuffer("<a href=\"reallyshutdown.html\">Shut down McIDAS-V</a>"));
171                    }
172                    else if (path.equals("/reallyshutdown.html")) {
173                            writeResult(true, "McIDAS-V is shutting down","text/html");
174                            System.exit(0);
175                    }
176                    else if (path.equals("/") || path.equals("/index.html")) {
177                            decorateHtml(new StringBuffer(""));
178                    }
179                    else {
180                            decorateHtml(new StringBuffer("Unknown url:" + path));
181                    }
182            }
183        }
184    
185    }