001/*
002 * Copyright (c) 2004-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2012-11-26 22:19:36 +0000 (Mon, 26 Nov 2012) $' 
007 * '$Revision: 31113 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.sdm.spa;
031
032import static java.net.HttpURLConnection.HTTP_OK;
033
034import java.io.IOException;
035import java.io.InputStream;
036import java.io.OutputStream;
037import java.net.InetSocketAddress;
038import java.net.URI;
039import java.net.URLDecoder;
040import java.util.HashMap;
041import java.util.Iterator;
042
043import org.apache.commons.logging.Log;
044import org.apache.commons.logging.LogFactory;
045
046import com.sun.net.httpserver.HttpExchange;
047import com.sun.net.httpserver.HttpHandler;
048import com.sun.net.httpserver.HttpServer;
049
050//////////////////////////////////////////////////////////////////////////
051////BrowserUIServer
052/*
053 * <p>BrowserUIServer is to provide web server support for BrowserUI actor
054 * </p>
055 * <p> This class use com.sun.net.httpserver package in java 1.6 
056 * which can easily create a httpserver. The server will be created when 
057 * initiating the actor and will be destroyed in its postfire() function. 
058 * Also only local user can visit it and only a certain url, 
059 * e.g. localhost:port/browserUI.
060 * Since the com.sun.net.httpserver package is only available in java 1.6, 
061 * $Kepler/modules/actors/lib/jar/http.jar is added to make it work with java 1.5. 
062 * </p>
063 *
064 * @author Jianwu Wang
065 * @version $Id: BrowserUIServer.java 31113 2012-11-26 22:19:36Z crawl $
066 *
067 */
068
069public final class BrowserUIServer {
070
071        private static final Log log = LogFactory.getLog(BrowserUIServer.class
072                        .getName());
073        private static final boolean isDebugging = log.isDebugEnabled();
074
075        InetSocketAddress addr;
076        HttpServer server;
077
078        protected void startServer(String context, int port) throws IOException {
079                try{
080                        addr = new InetSocketAddress("localhost", port);
081                        server = HttpServer.create(addr, 11);
082                        server.createContext("/" + context, new BrowserUIHandler());
083                        server.start();
084                        if (isDebugging)
085                                log.debug("server " + server.getAddress());
086                } catch (java.net.BindException e){
087                        if (e.getMessage().equalsIgnoreCase("Address already in use"))
088                                System.out.println("the server for BrowserUI is already started. Reuse it...");
089                }
090        }
091
092        protected void stopServer() throws IOException {
093
094                server.stop(1);
095        }
096
097        class BrowserUIHandler implements HttpHandler {
098                HashMap repository = new HashMap();
099
100                public void handle(HttpExchange t) throws IOException {
101                        final InputStream is;
102                        OutputStream os;
103                        StringBuilder buf;
104                        StringBuilder output;
105                        int b;
106                        String ptid = null;
107                        HashMap map;
108                        String request, response;
109
110                        buf = new StringBuilder();
111                        output = new StringBuilder();
112                        String hostname = t.getRemoteAddress().getHostName();
113                        if (!hostname.equalsIgnoreCase("127.0.0.1")
114                                        && !hostname.equalsIgnoreCase("localhost")) {
115
116                                response = "Error: BrowserUIServer only accept requests from hocalhost";
117                                t.sendResponseHeaders(HTTP_OK, response.length());
118                                os = t.getResponseBody();
119                                os.write(response.getBytes());
120                                os.close();
121                                t.close();
122                                return;
123                        }
124
125                        String requestMethod = t.getRequestMethod();
126
127                        if (requestMethod.equalsIgnoreCase("POST")) {
128                                is = t.getRequestBody();
129                                while ((b = is.read()) != -1) {
130                                        buf.append((char) b);
131                                }
132                                is.close();
133                                if (buf.length() > 0) {
134                                        request = URLDecoder.decode(buf.toString(), "UTF-8");
135                                } else {
136                                        request = null;
137                                }
138                                // the request url does not have ptid parameter, then save data
139                                // into
140                                // repository.
141                                if (request != null) {
142                                        // the first POST request for a POST form, fetch data
143                                        saveInfo(request, t);
144                                }
145
146                        } else if (requestMethod.equalsIgnoreCase("GET"))// if request is
147                        // null, the
148                        // form may use
149                        // 'get'. So
150                        // read info
151                        // from requestURI.
152                        {
153                                URI requests = t.getRequestURI();
154                                String requestQuery = requests.getQuery();
155                                if (requestQuery.indexOf("&") != -1) {
156                                        // the first GET request for a GET form, fetch data
157                                        saveInfo(requestQuery, t);
158                                }
159                                // the request url has ptid parameter, try to fetch data from
160                                // repository.
161                                else {
162                                        // the second GET request for a POST/GET form, fetch data
163                                        getInfo(requestQuery, t);
164                                }
165                        } else {
166                                response = "Error: BrowserUIServer only accept GET and POST requests";
167                                t.sendResponseHeaders(HTTP_OK, response.length());
168                                os = t.getResponseBody();
169                                os.write(response.getBytes());
170                                os.close();
171                                t.close();
172                                return;
173                        }
174                }
175
176                void saveInfo(String request, HttpExchange t) throws IOException {
177                        HashMap map = new HashMap();
178                        String ptid = null, response;
179                        StringBuilder output = new StringBuilder();
180                        OutputStream os;
181                        String[] requestArray = request.split("&");
182                        for (int i = 0; i < requestArray.length; i++) {
183                                String[] oneRequestArray = requestArray[i].split("=");
184                                for (int j = 0; j < oneRequestArray.length; j++) {
185                                        if (oneRequestArray[0] != null) {
186                                                if (oneRequestArray[0].equalsIgnoreCase("ptid")) {
187                                                        ptid = oneRequestArray[1];
188                                                } else {
189                                                        if (oneRequestArray.length > 1)
190                                                                map.put(oneRequestArray[0], oneRequestArray[1]);
191                                                        else
192                                                                map.put(oneRequestArray[0], null);
193                                                }
194                                        }
195                                }
196                        }
197                        if (ptid == null) {
198                                output.append("sorry, no ptid was found.");
199                        } else if (repository.containsKey(ptid)) {
200                                output
201                                                .append("sorry, an item with the same ptid was found in the repository.");
202                        } else {
203                                output.append("done.");
204                                repository.put(ptid, map);
205                                if (isDebugging)
206                                        log
207                                                        .debug("new item in repository at BrowserUIHandler. Key="
208                                                                        + ptid + ", value=" + map);
209                        }
210                        response = output.toString();
211                        t.sendResponseHeaders(HTTP_OK, response.length());
212                        os = t.getResponseBody();
213                        os.write(response.getBytes());
214                        os.close();
215                        t.close();
216                }
217
218                void getInfo(String request, HttpExchange t) throws IOException {
219                        HashMap map = new HashMap();
220                        String ptid = null, response;
221                        StringBuilder output = new StringBuilder();
222                        OutputStream os;
223                        String[] requestQueryArray = request.split("=");
224                        ptid = requestQueryArray[1];
225                        if (ptid == null) {
226                                output.append("sorry, no ptid was found.");
227                        } else {
228                                map = (HashMap) repository.get(ptid);
229                                if (map == null) {
230                                        output.append("sorry, no item was saved with id " + ptid
231                                                        + ".");
232                                } else {
233                                        repository.remove(ptid);
234                                        output.append("<xmp>\n");
235                                        Iterator keyIt = map.keySet().iterator();
236                                        while (keyIt.hasNext()) {
237                                                String key = (String) keyIt.next();
238                                                String value = (String) map.get(key);
239                                                output
240                                                                .append("    <name>" + key
241                                                                                + "</name>\n    <value>" + value
242                                                                                + "</value>\n");
243                                        }
244                                        output.append("</xmp>");
245                                }
246
247                                response = output.toString();
248                                t.sendResponseHeaders(HTTP_OK, response.length());
249                                os = t.getResponseBody();
250                                os.write(response.getBytes());
251                                os.close();
252                                t.close();
253                        }
254                }
255
256        }
257
258}