001/* 002 * $Id: AjaxRestWebsocketListener.java 997 2015-08-21 00:06:40Z tgutwin $ 003 * $HeadURL: $ 004 * $Revision: 997 $ 005 * $LastChangedDate: 2015-08-20 17:06:40 -0700 (Thu, 20 Aug 2015) $ 006 * $LastChangedBy: tgutwin $ 007 * Copyright (c) 2014-2015 Tom B. Gutwin P.Eng. North Vancouver BC Canada 008 * 009 * This program is free software; you can redistribute it and/or 010 * modify it under the terms of the GNU General Public License 011 * as published by the Free Software Foundation; either version 3 012 * of the License, or any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program; If not, see <http://www.gnu.org/licenses/>. 021 */ 022package ca.bc.webarts.servlet; 023 024import ca.bc.webarts.tools.Log; 025import ca.bc.webarts.widgets.Util; 026import ca.bc.webarts.widgets.ResultSetConverter; 027import ca.bc.webarts.widgets.tunes.TunesHelper; 028 029import com.oreilly.servlet.ParameterParser; 030import com.oreilly.servlet.ParameterNotFoundException; 031import com.oreilly.servlet.ServletUtils; 032 033import java.text.DecimalFormat; 034import java.io.BufferedReader; 035import java.io.File; 036import java.io.FileNotFoundException; 037import java.io.FileOutputStream; 038import java.io.FileReader; 039import java.io.FileWriter; 040import java.io.FileInputStream; 041import java.io.IOException; 042import java.io.InputStream; 043import java.io.OutputStream; 044import java.net.InetAddress; 045import java.net.MalformedURLException; 046import java.net.URL; 047import java.net.UnknownHostException; 048import java.util.Calendar; 049import java.util.Date; 050import java.util.Enumeration; 051import java.util.TimeZone; 052import java.util.zip.ZipEntry; 053import java.util.zip.ZipOutputStream; 054 055import javax.servlet.*; 056import javax.servlet.http.*; 057 058//import javax.json.Json; 059 060import javax.servlet.annotation.WebServlet; 061 062import org.eclipse.jetty.websocket.servlet.WebSocketServlet; 063import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; 064 065/** 066 * This class is a generic listener, implemented as a servlet, for responding to AJAX and/or Rest style requests.<br /> 067 * 068 * @author tgutwin 069 * @created April 25, 2016 070 */ 071@SuppressWarnings("serial") 072public class AjaxRestWebsocketListener extends WebSocketServlet 073{ 074 // implements SingleThreadModel 075 076 /** Class constant. **/ 077 protected static final String className_ = "AjaxRestWebsocketListener"; 078 private final static String SYSTEM_FILE_SEPERATOR = File.separator; 079 /** Version String. */ 080 private final static String SERVLET_VERSION = Util.spacesToCapsInString("0.01_[$Rev: 1086 $]"); 081 082 public static final String CLIENT_SETTING_NAME_VIEWPORTWIDTH = "clientSetting.viewPortWidth"; 083 public static final String CLIENT_SETTING_NAME_VIEWPORTHEIGHT = "clientSetting.viewPortHeight"; 084 public static final String CLIENT_SETTING_NAME_BROWSER_NAME = "clientSetting.browserName"; 085 public static final String CLIENT_SETTING_NAME_BROWSER_VERSION = "clientSetting.browserVersion"; 086 public static final String CLIENT_SETTING_NAME_DEVICE_TYPE = "clientSetting.deviceType"; 087 088 public static final String CLIENT_SETTING_NAME_LASTFM_SESSION_KEY = "clientSetting.lastFmSession"; 089 public static final String CLIENT_SETTING_NAME_LASTFM_USERID = "clientSetting.lastFmUserID"; 090 public static final String CLIENT_SETTING_NAME_LASTFM_USER_RECENT = "clientSetting.lastFmUserRecent"; 091 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_TRACK_NUM = "clientSetting.lastFmPlayTrackNum"; 092 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_TRACK = "clientSetting.lastFmPlayTrack"; 093 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_ALBUM = "clientSetting.lastFmPlayAlbum"; 094 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_ARTIST = "clientSetting.lastFmPlayArtist"; 095 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_ALBUM_ARTIST = "clientSetting.lastFmPlayAlbumArtist"; 096 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_TIME = "clientSetting.lastFmPlayTime"; 097 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_DURATION = "clientSetting.lastFmPlayDuration"; 098 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_TRACK = "clientSetting.lastFmScrobbleTrack"; 099 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ARTIST = "clientSetting.lastFmScrobbleArtist"; 100 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ALBUM = "clientSetting.lastFmScrobbleAlbum"; 101 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ALBUM_ARTIST= "clientSetting.lastFmScrobbleAlbumArtist"; 102 public static final String CLIENT_SETTING_NAME_LASTFM_LOVE_TRACK = "clientSetting.lastFmLoveTrack"; 103 public static final String CLIENT_SETTING_NAME_LASTFM_LIST_LOVE_TRACK = "clientSetting.lastFmListLovedTracks"; 104 105 /** DEFAULT Last.FM username to use: admin .**/ 106 protected static final String LASTFM_DEFAULT_USERNAME = "tgutwin"; //"${lastfm.user}"; 107 /** DEFAULT Last.FM password to use: admin .**/ 108 protected static final String LASTFM_DEFAULT_PASSWORD = "~19AcrobatiC19~~~"; //"${lastfm.pass}"; 109 110 /** Build String. (yymmddhhss) */ 111 private final static String BUILD_TAG = "160425183718"; 112 113 private static String webServerHostName_ = "zenbook.webarts.bc.ca"; 114 115 private boolean debugOut_ = true; 116 protected static Log log_= Log.getInstance(); 117 118 private int viewPortWidth_ = 0; 119 private int viewPortHeight_ = 0; 120 private String someParamYouWannaSet_ = ""; 121 122 /** Control for rest response format XML(default) or JSON. **/ 123 private boolean xmlResponse_ = false; 124 125 /** AJAX param - **/ 126 private String debugOut = ""; 127 private int viewPortWidth = 0; 128 private int viewPortHeight = 0; 129 private String browserName = ""; 130 private String browserVersion = ""; 131 private String lastFmSessionKey = ""; 132 private String lastFmPlayTrack = ""; 133 private String lastFmPlayArtist = ""; 134 private String lastFmScrobbleTrack = ""; 135 private String lastFmScrobbleArtist = ""; 136 private String lastFmScrobbleAlbum = ""; 137 private String lastFmLoveTrack = ""; 138 private boolean xmlResponse = xmlResponse_; 139 private TunesHelper tunesHelper = null; 140 private String lastFmUserID_ = LASTFM_DEFAULT_USERNAME; 141 private String lastFmPassword_ = LASTFM_DEFAULT_PASSWORD; 142 private boolean lastFMInit_ = false; 143 144 /** 145 * Gets the ServletInfo attribute of the AjaxRestWebsocketListener object 146 * 147 * @return The ServletInfo value 148 */ 149 public String getServletInfo() 150 { 151 final String methodName = "getServletInfo"; 152 return "WebARTS Design AjaxRestWebsocketListener servlet. Version:" + SERVLET_VERSION + 153 " Build:" + BUILD_TAG; 154 } 155 156 157 /** 158 * The one time servlet init stuff goes here. It sets the derbyDBDir based on the following prioritized varables: 159 * <ol><li>context init param: derbyDBDir</li><li>servlet init param (from web.xml): derbyDBDir</li> 160 * <li>default hardcoded variable: derbyDBDir</li></ol>If defined in multiple places, the higher priority item will 161 * be used. 162 **/ 163 public void init() 164 { 165 System.out.println("\n~~~~~~~~\n~~~~~~~~\nInitializing ca.bc.webarts.servlet.AjaxRestWebsocketListener\n~~~~~~~~\n~~~~~~~~"); 166 167 boolean notFoundInit = true; 168 boolean notFoundContext = true; 169 java.util.Enumeration <String> initEnum = getInitParameterNames(); 170 for (; notFoundInit && initEnum.hasMoreElements();) 171 { 172 if(initEnum.nextElement().equals("someParamYouWannaSet")) 173 { 174 notFoundInit = false; 175 /* Do something with the init param */ 176 someParamYouWannaSet_ = getInitParameter("someParamYouWannaSet"); 177 System.out.println("\n~~~~~~~~\n INIT ServletParam: someParamYouWannaSet="+someParamYouWannaSet_); 178 } 179 } 180 181 //also check context 182 initEnum = getServletConfig().getServletContext().getInitParameterNames(); 183 for (; notFoundContext && initEnum.hasMoreElements();) 184 { 185 if(initEnum.nextElement().equals("someParamYouWannaSet")) 186 { 187 notFoundContext = false; 188 /* Do something with the init param */ 189 someParamYouWannaSet_ = getServletConfig().getServletContext().getInitParameter("derbyDBDir"); 190 System.out.println("\n~~~~~~~~\n INIT ContextParam: someParamYouWannaSet="+someParamYouWannaSet_); 191 } 192 } 193 194 if(notFoundInit && notFoundContext ) 195 { 196 /* Set the default values */ 197 //eagleDBDir_ = pEye_.getDerbyDBDir(); 198 } 199 200 try 201 { 202 webServerHostName_ = InetAddress.getLocalHost().getHostName(); 203 } 204 catch (UnknownHostException ex) 205 { 206 webServerHostName_ = "red.webarts.bc.ca"; 207 } 208 } 209 210 211 /** Override to close Things **/ 212 public void destroy() 213 { 214 super.destroy(); 215 } 216 217 218 219 @Override 220 public void configure(WebSocketServletFactory factory) 221 { 222 // set a 10 second timeout 223 factory.getPolicy().setIdleTimeout(10000); 224 225 // register MyEchoSocket as the WebSocket to create on Upgrade 226 factory.register(EventSocket.class); 227 // factory.register(AjaxRestWebsocketListener.class); 228} 229 230 231 /** 232 * Returns the value of viewPortWidth_. 233 */ 234 public int getViewPortWidth() { 235 return viewPortWidth_; 236 } 237 238 239 /** 240 * Sets the value of viewPortWidth_. 241 * @param viewPortWidth The value to assign viewPortWidth_. 242 */ 243 public void setViewPortWidth(int viewPortWidth) { 244 this.viewPortWidth_ = viewPortWidth; 245 } 246 247 248 /** 249 * Returns the value of viewPortHeight_. 250 */ 251 public int getViewPortHeight() { 252 return viewPortHeight_; 253 } 254 255 256 /** 257 * Sets the value of viewPortHeight_. 258 * @param viewPortWidth The value to assign viewPortWidth_. 259 */ 260 public void setViewPortHeight(int viewPortHeight) { 261 this.viewPortHeight_ = viewPortHeight; 262 } 263 264 265 /** 266 * Returns the value of debugOut_. 267 */ 268 public boolean getDebugOut() 269 { 270 return debugOut_; 271 } 272 273 274 /** 275 * Sets the value of debugOut_. 276 * @param debugOut The value to assign debugOut_. 277 */ 278 public void setDebugOut(boolean debugOut) 279 { 280 this.debugOut_ = debugOut; 281 log_.setLogLevel((debugOut_?log_.DEBUG:log_.MINOR)); 282 } 283 284 285 /** 286 * Get Method for class field 'xmlResponse'. 287 * 288 * @return boolean - The value the class field 'xmlResponse' XML (true) or JSON (false). 289 * 290 **/ 291 public boolean getXmlResponse() 292 { 293 return xmlResponse_; 294 } // getXmlResponse Method 295 296 297 /** 298 * Set Method for class field 'xmlResponse' that controls if teh rest response is in XML (true) or JSON (false). 299 * 300 * @param xmlResponse is the value to set this class field to XML (true) or JSON (false). 301 * 302 **/ 303 public void setXmlResponse(boolean xmlResponse) 304 { 305 this.xmlResponse_ = xmlResponse; 306 } // setXmlResponse Method 307 308 309 /** 310 * streams to a zipped out stream (without creating a file). 311 * from: http://www.coderanch.com/t/276892/java-io/java/Stream-data-ZipOutputStream 312 * @param servletOutput is the stream to zip into 313 * @param dataName are the pseudo fileName that will get created in the zip (pseudo file) stream 314 * @param dataStream the data to zip 315 **/ 316 private void streamZIP(OutputStream servletOut, String dataName, InputStream dataStream) 317 { 318 String[] dataNames = {dataName}; 319 InputStream[] dataStreams = {dataStream}; 320 streamZIP(servletOut, dataNames,dataStreams); 321 } 322 323 324 /** 325 * streams to a zipped out stream (without creating a file). 326 * from: http://www.coderanch.com/t/276892/java-io/java/Stream-data-ZipOutputStream 327 * 328 * Sample servlet doGet...<br /> 329 * public void doGet(HttpServletRequest request, 330 HttpServletResponse response) throws IOException{ 331 response.setContentType("text/plain"); 332 response.setHeader("Content-Disposition", 333 "attachment;filename=downloadname.txt"); 334 String[] dataNames = {dataName}; 335 InputStream[] dataStreams = {dataStream}; 336 OutputStream os = response.getOutputStream(); 337 streamZIP(servletOut, dataNames,dataStreams); 338 } 339 * 340 * 341 * @param servletOutput is the stream to zip into 342 * @param dataNames are the pseudo fileNames that will get created in the zip (pseudo file) stream 343 * @param dataStreams the data to zip 344 **/ 345 private void streamZIP(OutputStream servletOut, 346 String[] dataNames, 347 InputStream[] dataStreams) 348 { 349 ZipOutputStream zos = new ZipOutputStream(servletOut); 350 final int DATA_BLOCK_SIZE = 2048; 351 int byteCount; 352 byte[] data; 353 354 try 355 { 356 for(int i = 0; i < dataNames.length; i++) 357 { 358 ZipEntry ze = new ZipEntry(dataNames[i]); 359 zos.putNextEntry(ze); 360 data = new byte[DATA_BLOCK_SIZE]; 361 362 while((byteCount = dataStreams[i].read(data, 0, DATA_BLOCK_SIZE)) != -1) 363 { 364 zos.write(data, 0, byteCount); 365 } 366 367 zos.flush(); 368 zos.closeEntry(); 369 dataStreams[i].close(); 370 } 371 zos.close(); 372 } 373 catch(Exception e) 374 { 375 System.err.println("Problem streaming zip data " + e.toString()); 376 } 377 } 378 379 380 /** Parses the REST command string and prepares the response in XML format. 381 * @param restPath is the rest command part of the rest URL 382 * @return a string holding the XML rest response 383 **/ 384 private String parseRestRequest(String restPath) 385 { 386 String restResponse = null; 387 System.out.println("REST Request: " +restPath); 388 String pre = "/"; 389 390 DecimalFormat dfp = new DecimalFormat( "##0" ); 391 DecimalFormat dfe = new DecimalFormat( "###0.000" ); 392 if(restPath.equals(pre+"power/current")) 393 { 394 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 395 /* 396 restResponse = "<RestResponse succeeded=\"true\"><power unit=\"watts\" timetamp=\"current\">"+ 397 pEye_.getCurrentDemand()+ 398 "</power></RestResponse>"; 399 */ 400 sb.append("</RestResponse>"); 401 } 402 else if(restPath.equals(pre+"power/recent")) 403 { 404 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 405 /* 406 ca.bc.webarts.tools.rainforest.InstantaneousDemand [] idmf = pEye_.getCurrentReadingsCache(); 407 for (int i=0; i< idmf.length; i++) 408 { 409 if(idmf[i]!=null) 410 { 411 sb.append("<power unit=\"watts\" timetamp=\""); 412 sb.append(idmf[i].getLocalTimestampStr()); 413 sb.append("\">"); 414 sb.append(dfp.format(idmf[i].getCalculatedValue())); 415 sb.append("</power>"); 416 } 417 } 418 */ 419 sb.append("</RestResponse>"); 420 restResponse = sb.toString(); 421 } 422 else if(restPath.equals(pre+"energy/recent")) 423 { 424 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 425 /* 426 ca.bc.webarts.tools.rainforest.CurrentSummationDelivered [] csd = pEye_.getCurrentEnergyCache(); 427 for (int i=0; i< csd.length; i++) 428 { 429 if(csd[i]!=null) 430 { 431 sb.append("<energy unit=\"wattHours\" timetamp=\""); 432 sb.append(csd[i].getLocalTimestampStr()); 433 sb.append("\">"); 434 sb.append(dfe.format(csd[i].getCalculatedValue())); 435 sb.append("</energy>"); 436 } 437 } 438 */ 439 sb.append("</RestResponse>"); 440 restResponse = sb.toString(); 441 } 442 else if(restPath.equals(pre+"energy/current")) 443 { 444 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 445 /* Add In the response content */ 446 sb.append("</RestResponse>"); 447 restResponse = sb.toString(); 448 } 449 else if(restPath.equals(pre+"price/current")) 450 { 451 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 452 /* Add In the response content */ 453 sb.append("</RestResponse>"); 454 restResponse = sb.toString(); 455 } 456 else if(restPath.equals(pre+"price/label/current")) 457 { 458 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 459 /* Add In the response content */ 460 sb.append("</RestResponse>"); 461 restResponse = sb.toString(); 462 } 463 return restResponse; 464 } 465 466 467 /** Parses any defined servlet params into the defined class vars. **/ 468 private void parseParams(HttpServletRequest req) 469 { 470 ParameterParser parser = new ParameterParser(req); 471 if(debugOut_) 472 { 473 System.out.println("\nRequest Params:"); 474 Enumeration<String> parmNames = req.getParameterNames(); 475 for (; parmNames.hasMoreElements();) 476 { 477 String currParamName = (String) parmNames.nextElement(); 478 System.out.println(" "+currParamName+"="+req.getParameter(currParamName)); 479 } 480 } 481 482 /* parse out the request params into class vars */ 483 debugOut = parser.getStringParameter("debugOut", ""); 484 viewPortWidth = parser.getIntParameter("viewPortWidth",0); 485 viewPortHeight = parser.getIntParameter("viewPortHeight",0); 486 browserName = parser.getStringParameter("clientBrowser",""); 487 browserVersion = parser.getStringParameter("clientBrowserVersion",""); 488 lastFmSessionKey = parser.getStringParameter("lastFmUserID",""); 489 lastFmSessionKey = parser.getStringParameter("lastFmPassword",""); 490 lastFmSessionKey = parser.getStringParameter("lastFmSessionKey",""); 491 lastFmPlayTrack = parser.getStringParameter("lastFmPlayTrack",""); 492 lastFmPlayArtist = parser.getStringParameter("lastFmPlayArtist",""); 493 lastFmScrobbleTrack = parser.getStringParameter("lastFmScrobbleTrack",""); 494 lastFmScrobbleAlbum = parser.getStringParameter("lastFmScrobbleAlbum",""); 495 lastFmScrobbleArtist = parser.getStringParameter("lastFmScrobbleArtist",""); 496 lastFmLoveTrack = parser.getStringParameter("lastFmLoveTrack",""); 497 xmlResponse = parser.getBooleanParameter("xmlResponse",xmlResponse_); 498 499 if(debugOut_) { System.out.println(" PlayTrack="+lastFmPlayTrack+" lastFmPlayArtist="+lastFmPlayArtist );} 500 if(debugOut_) { System.out.println(" ScrobbleTrack="+lastFmScrobbleTrack+" lastFmScrobbleAlbum="+lastFmScrobbleAlbum+" lastFmScrobbleArtist="+lastFmScrobbleArtist );} 501 502 } 503 504 505 /** Convert a well-formed (but not necessarily valid) XML string into a JSON String. **/ 506 private String xmlToJson(String xml) 507 { 508 String jsonStr = ""; 509 if (xml== null || xml.length()<2) xml = ""; 510 org.json.JSONObject jsonObj = org.json.XML.toJSONObject(xml); 511 if(jsonObj!= null) jsonStr = jsonObj.toString(2); 512 return jsonStr; 513 } 514 515 516 /** 517 * This method handles the "GET" submission - it is used for Ajax calls to set webApp parameters using JQuery. 518 * 519 * @param req Description of the Parameter 520 * @param res Description of the Parameter 521 * @exception ServletException Description of the Exception 522 * @exception IOException Description of the Exception 523 */ 524 public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 525 { 526 parseParams(req); 527 528 ServletOutputStream out = res.getOutputStream(); 529 String conPath = req.getContextPath(); 530 String restPath = req.getPathInfo(); // basically anything added to the end of the URL is considered a RESt request 531 532 533 if(debugOut_) 534 { 535 System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 536 System.out.println("AjaxRestWebsocketListener.doGet "+ " debugOut="+debugOut); 537 System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 538 } 539 540 boolean ajaxCall = false; 541 boolean restRequest = false; 542 String ajaxResponse = ""; 543 String restResponse = null; 544 545 res.setStatus(HttpServletResponse.SC_OK); // default ids OK,, set again lower downif NOT 546 547 ajaxResponse = checkForAjaxRequest(req); 548 if (!ajaxResponse.equals("")) ajaxCall=true; 549 550 if(!ajaxCall) restResponse = checkForRestRequest(req); 551 if (restResponse!=null && !restResponse.equals("")) restRequest=true; 552 553 if(debugOut_) { System.out.println("ajaxCall="+ajaxCall+" restRequest="+restRequest );} 554 /* * * * * * * * * * * EMPTY * * * * * * * * * * */ 555 /* *********************************************** */ 556 if( !ajaxCall && !restRequest) // EMPTY query and NO parms... it was *NOT* a JQuery Ajax call or a REST call, so just present some status back to user 557 { 558 sendServletAdminPage(req, res); 559 } 560 561 if(ajaxCall) 562 { 563 res.setContentType("text/plain"); 564 if(out!=null ) 565 { 566 if (debugOut_) 567 System.out.println("AJAX REPLY("+ajaxResponse.length()+")="+ajaxResponse); 568 out.print(ajaxResponse); 569 } 570 else 571 System.out.println("HttpServletResponse.ServletOutputStream is NOT ready"); 572 } 573 else if(restRequest) 574 { 575 if (xmlResponse_) res.setContentType("text/xml"); 576 else res.setContentType("application/javascript"); 577 if(restResponse!=null && !restResponse.equals("")) 578 { 579 res.setStatus(HttpServletResponse.SC_OK); 580 } 581 else 582 { 583 res.setStatus(HttpServletResponse.SC_NOT_FOUND); 584 restResponse = "<RestResponse succeeded=\"false\"><status>404</status></RestResponse>"; 585 } 586 if(out!=null ) 587 { 588 if (!xmlResponse_) restResponse = xmlToJson(restResponse); 589 if (debugOut_) 590 System.out.println("REST REPLY("+restResponse.length()+")="+restResponse); 591 out.print(restResponse); 592 } 593 else 594 System.out.println("HttpServletResponse.ServletOutputStream is NOT ready"); 595 } 596 out.flush(); 597 res.flushBuffer(); 598 } 599 600 601 /** 602 * This method handles the "POST" submissions. 603 * 604 * @param req Description of Parameter 605 * @param res Description of Parameter 606 * @exception ServletException Description of Exception 607 * @exception IOException Description of Exception 608 */ 609 public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 610 { 611 //parseParams(req); 612 613 StringBuffer postBody = new StringBuffer(""); 614 String line = null; 615 // try 616 // { 617 BufferedReader reader = req.getReader(); 618 while ((line = reader.readLine()) != null) 619 postBody.append(line+"\n"); 620 621 String postReply = ""; 622 623 // Do something with the posted message 624 // send it to a helper class if desired 625 /*String postReply = pEye_.newMessage(postBody.toString()); */ 626 627 // send back an empty reply 628 if ((postReply==null || postReply.equals(""))) 629 { 630 // send back a 200 with an empty body 631 res.setStatus(HttpServletResponse.SC_OK); 632 res.setContentLength(0); 633 postReply = ""; 634 if (debugOut_) System.out.println("AjaxRestWebsocketListener.doPost: emptyreply from newMessage"); 635 } 636 /* 637 else if(!sendFastPoll_) 638 { 639 // send back the pEyeReply as the body 640 res.setStatus(HttpServletResponse.SC_OK); 641 res.setContentLength(pEyeReply.length()); 642 if (debugOut_) System.out.println("AjaxRestWebsocketListener.doPost: SLOW Poll & newMessage reply existed"); 643 } 644 else // if(sendFastPoll_) 645 { 646 MessageCommand mc = new MessageCommand(pEye_.getMeterMacId()); 647 pEyeReply = mc.getSetFastPollCommandStr(fastPollFreq_,fastPollDur_); 648 649 res.setContentLength(0); // send back the setFastPollCommand string as the body 650 //if (debugOut_) System.out.println(" *!*!*!*! AjaxRestWebsocketListener.doPost: Send FAST Poll to:"+pEye_.getMeterMacId() ); 651 652 // now reset fastPoll for next message 653 sendFastPoll_ = false; 654 } 655 */ 656 657 postReply = "\n"+postReply; 658 res.setContentType("application/xml"); 659 res.setStatus(HttpServletResponse.SC_OK); 660 res.setContentLength(postReply.length()); 661 662 ServletOutputStream out = res.getOutputStream(); 663 if(out!=null ) 664 { 665 if (debugOut_) System.out.println("Attempting to HttpServletResponse REPLY("+postReply.length()+")="+postReply); 666 out.print(postReply); 667 out.flush(); 668 } 669 else 670 System.out.println("HttpServletResponse.ServletOutputStream is NOT ready"); 671 672 res.flushBuffer(); 673 674 /* 675 } 676 catch (Exception e) 677 { 678 //report an error 679 e.printStackTrace(); 680 } 681 */ 682 } 683 684 685 /** Parses the REST command string and prepares the response in XML format. 686 * @param restPath is the rest command part of the rest URL 687 * @return a string holding the XML rest response OR null if not a REST Request 688 **/ 689 private String checkForRestRequest(HttpServletRequest req) throws ServletException, IOException 690 { 691 String restResponse = null; 692 String servletPath = req.getServletPath(); 693 String restPath = req.getPathInfo(); // basically anything added to the end of the URL is considered a RESt request 694 String pre = "/"; 695 boolean returnXml = xmlResponse_; // false means JSON 696 697 if (servletPath.equals("/rest") && restPath!=null && !restPath.equals("") ) 698 { 699 700 DecimalFormat dfp = new DecimalFormat( "##0" ); 701 DecimalFormat dfe = new DecimalFormat( "###0.000" ); 702 if(restPath.equals(pre+"test")) 703 { 704 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 705 /* Add In the response content */ 706 sb.append("<testNode className=\""); 707 sb.append(className_); 708 sb.append("\">"); 709 sb.append("Hello"); 710 sb.append("</testNode>"); 711 sb.append("</RestResponse>"); 712 restResponse = sb.toString(); 713 } 714 if(restPath.equals(pre+"power/current")) 715 { 716 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 717 /* Add In the response content */ 718 sb.append("</RestResponse>"); 719 restResponse = sb.toString(); 720 } 721 else if(restPath.equals(pre+"power/recent")) 722 { 723 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 724 /* Add In the response content */ 725 sb.append("</RestResponse>"); 726 restResponse = sb.toString(); 727 } 728 else if(restPath.equals(pre+"energy/recent")) 729 { 730 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 731 /* Add In the response content */ 732 sb.append("</RestResponse>"); 733 restResponse = sb.toString(); 734 } 735 else if(restPath.equals(pre+"energy/current")) 736 { 737 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 738 /* Add In the response content */ 739 sb.append("</RestResponse>"); 740 restResponse = sb.toString(); 741 } 742 else if(restPath.equals(pre+"price/current")) 743 { 744 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 745 /* Add In the response content */ 746 sb.append("</RestResponse>"); 747 restResponse = sb.toString(); 748 } 749 else if(restPath.equals(pre+"price/label/current")) 750 { 751 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 752 /* Add In the response content */ 753 sb.append("</RestResponse>"); 754 restResponse = sb.toString(); 755 } 756 757 // Database Queries 758 /* 759 - Dump the database tables directly to (JSON or ) XML using a REST call: 760 http://red.webarts.bc.ca:8080/powereye/rest/db/table/<tablename> 761 <tablename> can be reading, energy, load_device, load_type 762 763 or with the optional <number of rows> 764 positive number means sorted ascending (oldest 1st) 765 negative number means sorted descending (newest 1st) 766 http://red.webarts.bc.ca:8080/powereye/rest/db/table/<tablename>/100 767 768 These database calls are LOOOOooong so you might want to use a commandline URL query tool like 769 <a href="http://www.gnu.org/software/wget/">wget</a>, or perl or java or whatever. 770 */ 771 else if(restPath.startsWith(pre+"db/table/")) 772 { 773 returnXml = true; // false means JSON 774 String content = ""; 775 try 776 { 777 restResponse = "<RestResponse succeeded=\"false\"></RestResponse>"; 778 int tblIndex = (pre+"db/table/").length(); 779 int numRowsIndex = restPath.indexOf("/",tblIndex)+1; // /rest/db/table/reading/99 780 boolean numRowsWasSpecified = (numRowsIndex>0); 781 int numReadings = (numRowsWasSpecified?Integer.parseInt(restPath.substring(numRowsIndex)):0); //0 means send all 782 boolean sortAscendingByDate = false; // sort default is descending 783 if(numReadings<0) // negative numbers means ascending 784 { 785 sortAscendingByDate = true; 786 numReadings *= -1; // now normalize it to be a psitive rowCount 787 } 788 String tableName = (numRowsWasSpecified?restPath.substring(tblIndex,numRowsIndex-1):restPath.substring(tblIndex)); 789 790 System.out.println("Dumping DB Table: "+tableName); 791 if(numRowsWasSpecified) System.out.println(" numRows: "+numReadings +" "+ 792 (sortAscendingByDate?"ascending":"descending")); 793 java.sql.ResultSet rs = null; 794 if(tableName.equalsIgnoreCase("reading")) 795 if(numRowsWasSpecified) 796 { 797 //rs = pEye_.dumpReadingTableToRS(sortAscendingByDate,(numReadings!=0?numReadings:-1));//dumpReadingTableToRS(); 798 } 799 else 800 { 801 //rs = pEye_.dumpReadingTableToRS(); 802 } 803 else if(tableName.equalsIgnoreCase("energy")) 804 if(numRowsWasSpecified) 805 { 806 //rs = pEye_.dumpEnergyTableToRS(sortAscendingByDate,(numReadings!=0?numReadings:-1));//dumpEnergyTableToRS(); 807 } 808 else 809 { 810 //rs = pEye_.dumpEnergyTableToRS(); 811 } 812 else if(tableName.equalsIgnoreCase("load_type")) 813 if(numRowsWasSpecified) 814 { 815 //rs = pEye_.dumpDBTableToRS("load_type",numReadings);//dumpLoadTypeTableToRS(); 816 } 817 else 818 { 819 //rs = pEye_.dumpLoadTypeTableToRS(); 820 } 821 else if(tableName.equalsIgnoreCase("load_device")) 822 if(numRowsWasSpecified) 823 { 824 //rs = pEye_.dumpDBTableToRS("load_device",numReadings);//dumpLoadDeviceTableToRS(); 825 } 826 else 827 { 828 //rs = pEye_.dumpLoadDeviceTableToRS(); 829 } 830 831 if(rs!=null) 832 { 833 ResultSetConverter rsc = new ResultSetConverter(rs); 834 if (returnXml) content = rsc.convertToXml().toXML().substring("<?xml version=\"1.0\"?>".length()); 835 else content = rsc.convertToJson().toString(); 836 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 837 /* Add In the response content */ 838 sb.append("<db table=\""+tableName+"\">"); 839 sb.append(content); 840 sb.append("</db>"); 841 842 sb.append("</RestResponse>"); 843 restResponse = sb.toString(); 844 } 845 } 846 catch(Exception ioEx) 847 { 848 restResponse = "<RestResponse succeeded=\"false\"></RestResponse>"; 849 } 850 } 851 } 852 853 return restResponse; 854 } 855 856 857 /** Checks if this Request is an AJAX request and prepares the response in XML format. 858 * @param req the servlet request 859 * @return a string holding the response value to be returned OR null if not an expected/Valid AJAX Request 860 **/ 861 private String checkForAjaxRequest(HttpServletRequest req) throws ServletException, IOException 862 { 863 String ajaxResponse = ""; 864 // was it a JQuery Ajax call for info... (such as eagleDBDir_) 865 if (debugOut!=null &&!debugOut.equals("") ) 866 { 867 debugOut_ = Boolean.parseBoolean(debugOut); 868 setDebugOut(debugOut_); 869 //pEye_.setDebugOut(debugOut_); 870 System.out.println("AjaxRestWebsocketListener.doGet - debugOut_="+debugOut_); 871 ajaxResponse = ""+debugOut_; 872 } 873 else if (viewPortWidth!=0 ) 874 { 875 // do something with the passed parms 876 viewPortWidth_=viewPortWidth; 877 req.getSession().setAttribute(CLIENT_SETTING_NAME_VIEWPORTWIDTH, viewPortWidth); 878 ajaxResponse = ""+viewPortWidth_; 879 } 880 else if (viewPortHeight!=0 ) 881 { 882 // do something with the passed parms 883 viewPortHeight_=viewPortHeight; 884 req.getSession().setAttribute(CLIENT_SETTING_NAME_VIEWPORTHEIGHT, viewPortHeight); 885 ajaxResponse = ""+viewPortHeight_; 886 } 887 else if (browserName!=null &&!browserName.equals("") ) 888 { 889 req.getSession().setAttribute(CLIENT_SETTING_NAME_BROWSER_NAME, browserName); 890 ajaxResponse = ""+browserName; 891 } 892 else if (browserVersion!=null &&!browserVersion.equals("") ) 893 { 894 req.getSession().setAttribute(CLIENT_SETTING_NAME_BROWSER_VERSION, browserVersion); 895 ajaxResponse = ""+browserVersion; 896 } 897 // Ajax Call - lastFmPlayTrack 898 else if (lastFmPlayTrack!=null &&!lastFmPlayTrack.equals("") ) 899 { 900 System.out.println("Ajax Call - lastFmPlayTrack="+lastFmPlayTrack); 901 HttpSession session = req.getSession(true); 902 System.out.println(" ajaxParam Found: lastFmPlayTrack="+lastFmPlayTrack +" lastFmPlayArtist="+lastFmPlayArtist); 903 System.out.println(" AjaxRestWebsocketListener SessionID: "+session.getId() ); 904 905 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_PLAY_TRACK, lastFmPlayTrack); 906 if (lastFmPlayArtist!=null && !lastFmPlayArtist.equals("") ) 907 { 908 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_PLAY_ARTIST, lastFmPlayArtist); 909 } 910 // Threaded call to send a play notification to last.fm 911 loginLastFM(); 912 //HttpSession session = request.getSession(); 913 session.setAttribute("AjaxRestWebsocketListener.tunesHelper", tunesHelper); 914 915 if ( lastFMInit_) 916 { 917 tunesHelper.nowPlaying(lastFmPlayArtist, lastFmPlayTrack); 918 ajaxResponse = ""+lastFmPlayArtist+"/"+lastFmPlayTrack; 919 } 920 else 921 { 922 ajaxResponse = "null/null"; 923 } 924 } 925 // Ajax Call - lastFmScrobbleTrack 926 else if (lastFmScrobbleTrack!=null &&!lastFmScrobbleTrack.equals("") && (lastFmLoveTrack==null || lastFmLoveTrack.equals(""))) 927 { 928 System.out.println("Ajax Call - lastFmScrobbleTrack="+lastFmScrobbleTrack); 929 HttpSession session = req.getSession(true); 930 System.out.println(" ajaxParam Found: lastFmScrobbleTrack="+lastFmScrobbleTrack +" lastFmScrobbleArtist="+lastFmScrobbleArtist); 931 System.out.println(" AjaxRestWebsocketListener SessionID: "+session.getId() ); 932 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_TRACK, lastFmScrobbleTrack); 933 if (lastFmScrobbleAlbum !=null &&!lastFmScrobbleAlbum.equals("") ) 934 { 935 System.out.println(" ajaxParam Found: lastFmScrobbleAlbum="+lastFmScrobbleAlbum ); 936 req.getSession().setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ALBUM, lastFmScrobbleAlbum); 937 } 938 if (lastFmScrobbleArtist!=null &&!lastFmScrobbleArtist.equals("") ) 939 { 940 req.getSession().setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ARTIST, lastFmScrobbleArtist); 941 } 942 // Threaded call to send a play notification to last.fm 943 loginLastFM(); 944 //HttpSession session = request.getSession(); 945 session.setAttribute("AjaxRestWebsocketListener.tunesHelper", tunesHelper); 946 947 if ( lastFMInit_) 948 { 949 tunesHelper.scrobble(lastFmScrobbleArtist, lastFmScrobbleAlbum, lastFmScrobbleTrack); 950 ajaxResponse = ""+lastFmScrobbleArtist+"/"+lastFmScrobbleAlbum+"/"+lastFmScrobbleTrack; 951 } 952 else 953 { 954 ajaxResponse = "null/null"; 955 } 956 } 957 // Ajax Call - lastFmLoveTrack 958 else if (lastFmLoveTrack!=null && !lastFmLoveTrack.equals("") && lastFmScrobbleTrack!=null && !lastFmScrobbleTrack.equals("") ) 959 { 960 System.out.println("Ajax Call - lastFmLoveTrack="+lastFmLoveTrack); 961 HttpSession session = req.getSession(true); 962 if (lastFmScrobbleArtist!=null &&!lastFmScrobbleArtist.equals("") ) 963 { 964 req.getSession().setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ARTIST, lastFmScrobbleArtist); 965 } 966 System.out.println(" ajaxParam Found: lastFmLoveTrack="+lastFmLoveTrack+ 967 "lastFmScrobbleTrack="+lastFmScrobbleTrack + 968 " lastFmScrobbleArtist="+lastFmScrobbleArtist); 969 System.out.println(" AjaxRestWebsocketListener SessionID: "+session.getId() ); 970 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_LOVE_TRACK, lastFmLoveTrack); 971 // Threaded call to send a play notification to last.fm 972 loginLastFM(); 973 //HttpSession session = request.getSession(); 974 session.setAttribute("AjaxRestWebsocketListener.tunesHelper", tunesHelper); 975 976 if ( lastFMInit_) 977 { 978 //http://10.0.0.253/tunes/ajax/?lastFmLoveTrack=1&lastFmScrobbleTrack=18TillIDie&lastFmScrobbleArtist=BryanAdams 979 ajaxResponse = tunesHelper.loveTrack(lastFmScrobbleArtist, lastFmScrobbleTrack); 980 //ajaxResponse = ""+lastFmScrobbleArtist+"/"+lastFmScrobbleTrack; 981 } 982 else 983 { 984 ajaxResponse = "null/null"; 985 } 986 } 987 988 return ajaxResponse; 989 } 990 991 992 /** 993 * Logs into the last.fm session with the already provided user/pass. 994 * this method uses TunesHelper to do this. 995 * 996 * @return success or not 997 **/ 998 private boolean loginLastFM() 999 { 1000 if(tunesHelper == null) tunesHelper = new TunesHelper(); 1001 /* should probably also use the lastFM user pass sent by some AJAX call. */ 1002 tunesHelper.setLastFmUserID(lastFmUserID_); 1003 tunesHelper.setLastFmPassword(lastFmPassword_); 1004 1005 if (tunesHelper!=null) 1006 { 1007 if (!lastFmSessionKey.equals("") ) 1008 { 1009 if (tunesHelper.restoreLastFmUserSession(lastFmSessionKey)) 1010 { 1011 lastFMInit_ = true; 1012 } 1013 else 1014 { 1015 lastFMInit_ = tunesHelper.initLastFmUserSession(true, lastFmUserID_, lastFmPassword_); 1016 } 1017 } 1018 } 1019 return lastFMInit_; 1020 } 1021 1022 1023 /** Prepares and returns basic info page about the server. **/ 1024 private void sendServletAdminPage(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 1025 { 1026 ServletOutputStream out = res.getOutputStream(); 1027 ServletContext context = getServletContext(); 1028 java.util.Properties sysProps = System.getProperties(); 1029 TimeZone localTz = Calendar.getInstance().getTimeZone(); 1030 int offset = localTz.getRawOffset(); 1031 // shift Daylight savings hour if needed 1032 Date dateNow = new Date(); 1033 boolean dst = localTz.inDaylightTime(dateNow); 1034 int dstOffset = localTz.getDSTSavings(); 1035 //if(dst) offset = offset + dstOffset; 1036 1037 String prop = ""; 1038 1039 // Send Back a response to be presented to the users browser 1040 res.setContentType("text/html"); 1041 out.println("<html>\n"); 1042 out.println("<head>\n"); 1043 out.println("<title>Ajax / REST Listener - Servlet Console</title>\n"); 1044 out.println("<link rel=\"icon\""); 1045 out.println(" type=\"image/png\""); 1046 out.println(" href=\"images/20x20/Eagle_sml.png\" />"); 1047 out.println("<style>"); 1048 out.println("H1 { font-weight: bolder; background-color: #000033; color: #ffffbb; font-size: 200%}"); 1049 out.println("H2 { font-weight: bolder; color: #ffff99; font-size: 160%; text-decoration: underline}"); 1050 out.println("H3 { font-weight: bolder; color: #ffff44; font-size: 140%}"); 1051 out.println("H4, H5 { color: #ffffff }"); 1052 out.println("A { color: #ffaadd }"); 1053 out.println("DT { font-weight: bolder }"); 1054 out.println("LI { line-height: 125% }"); 1055 out.println("BODY { background-color: #101066; color: #ffff44; font-size: 100%; line-height: 110% }"); 1056 out.println(".val { color: #ffffff; font: \"Lucida Console\", Monaco, monospace }"); 1057 out.println(""); 1058 out.println(""); 1059 out.println(""); 1060 out.println("</style>"); 1061 1062 //out.println("<META HTTP-EQUIV=\"refresh\" content=\"2;URL=\"javascript:history.go(-2);\">\n"); 1063 out.println("</head>\n"); 1064 out.println("<body>"); 1065 out.println("<h1>Web<i>ARTS</i> Ajax / REST Listener</h1><h2>Servlet Console</h2>"); 1066 out.println(getServletInfo()); 1067 out.println(" <h3>Parameters</h3>"); 1068 out.println(" <ul>"); 1069 out.println(" <li>debug = <span class=\"val\">"+debugOut_+"</span></li>"); 1070 out.println("<br />"); 1071 out.println(" <li>Servlet Init Params:"); 1072 out.println(" <ul>"); 1073 1074 java.util.Enumeration <String> initEnum = getInitParameterNames(); 1075 String currParamName = ""; 1076 for (; initEnum.hasMoreElements();) 1077 { 1078 currParamName = initEnum.nextElement(); 1079 out.print(" <li>"); 1080 out.print(currParamName+" = <span class=\"val\">"+getInitParameter(currParamName)); 1081 out.println("</span></li>"); 1082 } 1083 out.println(" </ul>"); 1084 out.println(" </li>"); // servlet init params 1085 1086 out.println("<br />"); 1087 out.println(" <li>Context Params for "+context.getServletContextName()+":"); 1088 out.println(" <ul>"); 1089 out.print(" <li>"); 1090 out.print("ContextPath"+" = <span class=\"val\">"+context.getContextPath()); 1091 out.println("</span></li>"); 1092 out.print(" <li>"); 1093 out.print("Real Path For Context Root"+" = <span class=\"val\">"+context.getRealPath("/")); 1094 out.println("</span></li>"); 1095 out.println(" </ul>"); 1096 out.println(" </li>"); // CONTEXT params 1097 1098 out.println("<br />"); 1099 out.println(" <li>Context <b>Init</b> Params:"); 1100 out.println(" <ul>"); 1101 initEnum = context.getInitParameterNames(); 1102 currParamName = ""; 1103 for (; initEnum.hasMoreElements();) 1104 { 1105 currParamName = initEnum.nextElement(); 1106 out.print(" <li>"); 1107 out.print(currParamName+" = <span class=\"val\">"+context.getInitParameter(currParamName)); 1108 out.println("</span></li>"); 1109 } 1110 out.println(" </ul>"); 1111 out.println(" </li>"); // context init params 1112 1113 out.println(" </ul>"); 1114 1115 out.println("<br /><br />"); 1116 out.println("<h3>Server Status</h3>"); 1117 out.println(" <ul>"); 1118 out.println(" <li>Server name = <span class=\"val\">"+req.getServerName()+" ("+req.getLocalAddr()+")</span></li>"); 1119 out.println(" <li>Server port = <span class=\"val\">"+req.getServerPort()+"</span></li>"); 1120 out.println(" <li>WebApp Engine = <span class=\"val\">"+context.getServerInfo()+"</span></li>"); 1121 out.println(" <li>Supported Servlet Version = <span class=\"val\">"+context.getMajorVersion()+"."+context.getMinorVersion()+"</span></li>"); 1122 1123 if(context.getMajorVersion()>2 && context.getMinorVersion()>-1) 1124 out.println(" <ul><li>Effective Version = <span class=\"val\">"+ 1125 context.getEffectiveMajorVersion()+"."+context.getEffectiveMinorVersion()+"</span></li></ul>"); 1126 out.println(" </li>"); 1127 if(context.getMajorVersion()>2 && context.getMinorVersion()>0) 1128 { 1129 try { 1130 out.println(" <li>Logical Hostname = <span class=\"val\">"+context.getVirtualServerName()+"</span></li>"); 1131 } catch (Exception ex) {} 1132 } 1133 1134 out.println(" <li>System Properties\n <ul>"); 1135 prop = "java.vendor"; 1136 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1137 prop = "java.runtime.version"; 1138 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1139 prop = "java.version"; 1140 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1141 prop = "os.arch"; 1142 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1143 prop = "os.name"; 1144 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1145 prop = "os.version"; 1146 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1147 1148 out.println(" </ul>\n </li>"); 1149 1150 out.println("<br /><br />"); 1151 out.println("<h3>Client Request</h3>"); 1152 out.println(" <ul>"); 1153 out.println(" <li>Client/proxy Host = <span class=\"val\">"+req.getRemoteHost()+" ("+req.getRemoteAddr()+")</span></li>"); 1154 out.println(" <li>Client/proxy port = <span class=\"val\">"+req.getRemotePort()+"</span></li>"); 1155 out.println(" <li>Protocol = <span class=\"val\">"+req.getProtocol()+"</span></li>"); 1156 out.println(" </ul>"); 1157 1158 out.println("<br /><br />"); 1159 out.println("<h3>Client Parms Status</h3>"); 1160 out.println(" <ul>"); 1161 out.println(" <li>Browser = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_BROWSER_NAME)+" v"+ 1162 req.getSession().getAttribute(CLIENT_SETTING_NAME_BROWSER_VERSION)+"</span></li>"); 1163 out.println(" <li>Device Type = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_DEVICE_TYPE)+"</span></li>"); 1164 out.println(" <li>viewport.width = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_VIEWPORTWIDTH)+"</span></li>"); 1165 out.println(" <li>viewport.height= <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_VIEWPORTHEIGHT)+"</span></li>"); 1166 out.println(" </ul>"); 1167 out.println("<br /><br />"); 1168 out.println("\n</body>\n</html>"); 1169 } 1170}