001/* 002 * $Id: AjaxRestListener.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; 054import java.text.DateFormat; 055import java.text.SimpleDateFormat; 056import java.time.Duration; 057import java.time.LocalDateTime; 058import java.time.ZonedDateTime; 059import java.time.format.DateTimeFormatter; 060 061import javax.servlet.*; 062import javax.servlet.http.*; 063 064//import javax.json.Json; 065 066/** 067 * This class is a generic listener, implemented as a servlet, for responding to AJAX and/or Rest style requests.<br /> 068 * 069 * @author tgutwin 070 * @created April 25, 2016 071 */ 072public class AjaxRestListener extends HttpServlet 073{ 074 // implements SingleThreadModel 075 076 /** Class constant. **/ 077 protected static final String className_ = "AjaxRestListener"; 078 private final static String SYSTEM_FILE_SEPERATOR = File.separator; 079 /** Version String. */ 080 private final static String SERVLET_VERSION = Util.spacesToCapsInString("0.99.RC.5_[$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_USER_RECENT = "clientSetting.lastFmUserRecent"; 090 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_TRACK_NUM = "clientSetting.lastFmPlayTrackNum"; 091 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_TRACK = "clientSetting.lastFmPlayTrack"; 092 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_ALBUM = "clientSetting.lastFmPlayAlbum"; 093 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_ARTIST = "clientSetting.lastFmPlayArtist"; 094 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_ALBUM_ARTIST = "clientSetting.lastFmPlayAlbumArtist"; 095 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_TIME = "clientSetting.lastFmPlayTime"; 096 public static final String CLIENT_SETTING_NAME_LASTFM_PLAY_DURATION = "clientSetting.lastFmPlayDuration"; 097 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_TRACK = "clientSetting.lastFmScrobbleTrack"; 098 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ARTIST = "clientSetting.lastFmScrobbleArtist"; 099 public static final String CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ALBUM = "clientSetting.lastFmScrobbleAlbum"; 100 public static final String CLIENT_SETTING_NAME_LASTFM_LOVE_TRACK = "clientSetting.lastFmLoveTrack"; 101 102 /** DEFAULT Last.FM username to use: admin .**/ 103 protected static final String LASTFM_DEFAULT_USERNAME = "tgutwin"; //"${lastfm.user}"; 104 /** DEFAULT Last.FM password to use: admin .**/ 105 protected static final String LASTFM_DEFAULT_PASSWORD = "~19AcrobatiC19~~~"; //"${lastfm.pass}"; 106 107 /** Build String. (yymmddhhss) */ 108 private final static String BUILD_TAG = "160425183718"; 109 110 private static String webServerHostName_ = "warp4.webarts.bc.ca"; 111 112 private boolean debugOut_ = true; 113 protected static Log log_= Log.getInstance(); 114 115 private int viewPortWidth_ = 0; 116 private int viewPortHeight_ = 0; 117 private String someParamYouWannaSet_ = ""; 118 119 /** Control for rest response format XML(default) or JSON. **/ 120 private boolean xmlResponse_ = false; 121 122 /** AJAX param - **/ 123 private String debugOut = ""; 124 private int viewPortWidth = 0; 125 private int viewPortHeight = 0; 126 private String browserName = ""; 127 private String browserVersion = ""; 128 private String lastFmSessionKey = ""; 129 private String lastFmUserRecent = ""; 130 private String lastFmPlayTrack = ""; 131 private int lastFmPlayTrackNum = 0; 132 private String lastFmPlayAlbum = ""; 133 private String lastFmPlayArtist = ""; 134 private String lastFmPlayAlbumArtist = ""; 135 private int lastFmPlayTime = 0; 136 private int lastFmPlayDuration = 0; 137 private String lastFmScrobbleTrack = ""; 138 private String lastFmPreviousScrobbleTrack = ""; 139 private String lastFmScrobbleArtist = ""; 140 private String lastFmScrobbleAlbum = ""; 141 private String lastFmLoveTrack = ""; 142 private boolean xmlResponse = xmlResponse_; 143 private TunesHelper tunesHelper = null; 144 private String lastFmUserID_ = LASTFM_DEFAULT_USERNAME; 145 private String lastFmPassword_ = LASTFM_DEFAULT_PASSWORD; 146 private boolean lastFMInit_ = false; 147 private java.util.Vector <de.umass.lastfm.Track > lastFmRecentTracks_ = null; 148 149 /** 150 * Gets the ServletInfo attribute of the AjaxRestListener object 151 * 152 * @return The ServletInfo value 153 */ 154 public String getServletInfo() 155 { 156 final String methodName = "getServletInfo"; 157 return "WebARTS Design AjaxRestListener servlet. Version:" + SERVLET_VERSION + 158 " Build:" + BUILD_TAG; 159 } 160 161 162 /** 163 * The one time servlet init stuff goes here. It sets the derbyDBDir based on the following prioritized varables: 164 * <ol><li>context init param: derbyDBDir</li><li>servlet init param (from web.xml): derbyDBDir</li> 165 * <li>default hardcoded variable: derbyDBDir</li></ol>If defined in multiple places, the higher priority item will 166 * be used. 167 **/ 168 public void init() 169 { 170 System.out.println("\n~~~~~~~~\n~~~~~~~~\nInitializing ca.bc.webarts.servlet.AjaxRestListener\n~~~~~~~~\n~~~~~~~~"); 171 172 boolean notFoundInit = true; 173 boolean notFoundContext = true; 174 java.util.Enumeration <String> initEnum = getInitParameterNames(); 175 for (; notFoundInit && initEnum.hasMoreElements();) 176 { 177 if(initEnum.nextElement().equals("someParamYouWannaSet")) 178 { 179 notFoundInit = false; 180 /* Do something with the init param */ 181 someParamYouWannaSet_ = getInitParameter("someParamYouWannaSet"); 182 System.out.println("\n~~~~~~~~\n INIT ServletParam: someParamYouWannaSet="+someParamYouWannaSet_); 183 } 184 } 185 186 //also check context 187 initEnum = getServletConfig().getServletContext().getInitParameterNames(); 188 for (; notFoundContext && initEnum.hasMoreElements();) 189 { 190 if(initEnum.nextElement().equals("someParamYouWannaSet")) 191 { 192 notFoundContext = false; 193 /* Do something with the init param */ 194 someParamYouWannaSet_ = getServletConfig().getServletContext().getInitParameter("derbyDBDir"); 195 System.out.println("\n~~~~~~~~\n INIT ContextParam: someParamYouWannaSet="+someParamYouWannaSet_); 196 } 197 } 198 199 if(notFoundInit && notFoundContext ) 200 { 201 /* Set the default values */ 202 //eagleDBDir_ = pEye_.getDerbyDBDir(); 203 } 204 205 try 206 { 207 webServerHostName_ = InetAddress.getLocalHost().getHostName(); 208 } 209 catch (UnknownHostException ex) 210 { 211 webServerHostName_ = "red.webarts.bc.ca"; 212 } 213 } 214 215 216 /** Override to close Things **/ 217 public void destroy() 218 { 219 super.destroy(); 220 } 221 222 223 224 /** 225 * Returns the value of viewPortWidth_. 226 */ 227 public int getViewPortWidth() { 228 return viewPortWidth_; 229 } 230 231 232 /** 233 * Sets the value of viewPortWidth_. 234 * @param viewPortWidth The value to assign viewPortWidth_. 235 */ 236 public void setViewPortWidth(int viewPortWidth) { 237 this.viewPortWidth_ = viewPortWidth; 238 } 239 240 241 /** 242 * Returns the value of viewPortHeight_. 243 */ 244 public int getViewPortHeight() { 245 return viewPortHeight_; 246 } 247 248 249 /** 250 * Sets the value of viewPortHeight_. 251 * @param viewPortWidth The value to assign viewPortWidth_. 252 */ 253 public void setViewPortHeight(int viewPortHeight) { 254 this.viewPortHeight_ = viewPortHeight; 255 } 256 257 258 /** 259 * Returns the value of debugOut_. 260 */ 261 public boolean getDebugOut() 262 { 263 return debugOut_; 264 } 265 266 267 /** 268 * Sets the value of debugOut_. 269 * @param debugOut The value to assign debugOut_. 270 */ 271 public void setDebugOut(boolean debugOut) 272 { 273 this.debugOut_ = debugOut; 274 log_.setLogLevel((debugOut_?log_.DEBUG:log_.MINOR)); 275 } 276 277 278 /** 279 * Get Method for class field 'xmlResponse'. 280 * 281 * @return boolean - The value the class field 'xmlResponse' XML (true) or JSON (false). 282 * 283 **/ 284 public boolean getXmlResponse() 285 { 286 return xmlResponse_; 287 } // getXmlResponse Method 288 289 290 /** 291 * Set Method for class field 'xmlResponse' that controls if teh rest response is in XML (true) or JSON (false). 292 * 293 * @param xmlResponse is the value to set this class field to XML (true) or JSON (false). 294 * 295 **/ 296 public void setXmlResponse(boolean xmlResponse) 297 { 298 this.xmlResponse_ = xmlResponse; 299 } // setXmlResponse Method 300 301 302 /** 303 * streams to a zipped out stream (without creating a file). 304 * from: http://www.coderanch.com/t/276892/java-io/java/Stream-data-ZipOutputStream 305 * @param servletOutput is the stream to zip into 306 * @param dataName are the pseudo fileName that will get created in the zip (pseudo file) stream 307 * @param dataStream the data to zip 308 **/ 309 private void streamZIP(OutputStream servletOut, String dataName, InputStream dataStream) 310 { 311 String[] dataNames = {dataName}; 312 InputStream[] dataStreams = {dataStream}; 313 streamZIP(servletOut, dataNames,dataStreams); 314 } 315 316 317 /** 318 * streams to a zipped out stream (without creating a file). 319 * from: http://www.coderanch.com/t/276892/java-io/java/Stream-data-ZipOutputStream 320 * 321 * Sample servlet doGet...<br /> 322 * public void doGet(HttpServletRequest request, 323 HttpServletResponse response) throws IOException{ 324 response.setContentType("text/plain"); 325 response.setHeader("Content-Disposition", 326 "attachment;filename=downloadname.txt"); 327 String[] dataNames = {dataName}; 328 InputStream[] dataStreams = {dataStream}; 329 OutputStream os = response.getOutputStream(); 330 streamZIP(servletOut, dataNames,dataStreams); 331 } 332 * 333 * 334 * @param servletOutput is the stream to zip into 335 * @param dataNames are the pseudo fileNames that will get created in the zip (pseudo file) stream 336 * @param dataStreams the data to zip 337 **/ 338 private void streamZIP(OutputStream servletOut, 339 String[] dataNames, 340 InputStream[] dataStreams) 341 { 342 ZipOutputStream zos = new ZipOutputStream(servletOut); 343 final int DATA_BLOCK_SIZE = 2048; 344 int byteCount; 345 byte[] data; 346 347 try 348 { 349 for(int i = 0; i < dataNames.length; i++) 350 { 351 ZipEntry ze = new ZipEntry(dataNames[i]); 352 zos.putNextEntry(ze); 353 data = new byte[DATA_BLOCK_SIZE]; 354 355 while((byteCount = dataStreams[i].read(data, 0, DATA_BLOCK_SIZE)) != -1) 356 { 357 zos.write(data, 0, byteCount); 358 } 359 360 zos.flush(); 361 zos.closeEntry(); 362 dataStreams[i].close(); 363 } 364 zos.close(); 365 } 366 catch(Exception e) 367 { 368 System.err.println("Problem streaming zip data " + e.toString()); 369 } 370 } 371 372 373 /** Parses the REST command string and prepares the response in XML format. 374 * @param restPath is the rest command part of the rest URL 375 * @return a string holding the XML rest response 376 **/ 377 private String parseRestRequest(String restPath) 378 { 379 String restResponse = null; 380 System.out.println("REST Request: " +restPath); 381 String pre = "/"; 382 383 DecimalFormat dfp = new DecimalFormat( "##0" ); 384 DecimalFormat dfe = new DecimalFormat( "###0.000" ); 385 if(restPath.equals(pre+"power/current")) 386 { 387 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 388 /* 389 restResponse = "<RestResponse succeeded=\"true\"><power unit=\"watts\" timetamp=\"current\">"+ 390 pEye_.getCurrentDemand()+ 391 "</power></RestResponse>"; 392 */ 393 sb.append("</RestResponse>"); 394 } 395 else if(restPath.equals(pre+"power/recent")) 396 { 397 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 398 /* 399 ca.bc.webarts.tools.rainforest.InstantaneousDemand [] idmf = pEye_.getCurrentReadingsCache(); 400 for (int i=0; i< idmf.length; i++) 401 { 402 if(idmf[i]!=null) 403 { 404 sb.append("<power unit=\"watts\" timetamp=\""); 405 sb.append(idmf[i].getLocalTimestampStr()); 406 sb.append("\">"); 407 sb.append(dfp.format(idmf[i].getCalculatedValue())); 408 sb.append("</power>"); 409 } 410 } 411 */ 412 sb.append("</RestResponse>"); 413 restResponse = sb.toString(); 414 } 415 else if(restPath.equals(pre+"energy/recent")) 416 { 417 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 418 /* 419 ca.bc.webarts.tools.rainforest.CurrentSummationDelivered [] csd = pEye_.getCurrentEnergyCache(); 420 for (int i=0; i< csd.length; i++) 421 { 422 if(csd[i]!=null) 423 { 424 sb.append("<energy unit=\"wattHours\" timetamp=\""); 425 sb.append(csd[i].getLocalTimestampStr()); 426 sb.append("\">"); 427 sb.append(dfe.format(csd[i].getCalculatedValue())); 428 sb.append("</energy>"); 429 } 430 } 431 */ 432 sb.append("</RestResponse>"); 433 restResponse = sb.toString(); 434 } 435 else if(restPath.equals(pre+"energy/current")) 436 { 437 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 438 /* Add In the response content */ 439 sb.append("</RestResponse>"); 440 restResponse = sb.toString(); 441 } 442 else if(restPath.equals(pre+"price/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/label/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 return restResponse; 457 } 458 459 460 /** Parses any defined servlet params into the defined class vars. **/ 461 private void parseParams(HttpServletRequest req) 462 { 463 ParameterParser parser = new ParameterParser(req); 464 if(debugOut_) 465 { 466 System.out.println("\nRequest Params:"); 467 Enumeration<String> parmNames = req.getParameterNames(); 468 for (; parmNames.hasMoreElements();) 469 { 470 String currParamName = (String) parmNames.nextElement(); 471 System.out.println(" "+currParamName+"="+req.getParameter(currParamName)); 472 } 473 } 474 475 /* parse out the request params into class vars */ 476 debugOut = parser.getStringParameter("debugOut", ""); 477 viewPortWidth = parser.getIntParameter("viewPortWidth",0); 478 viewPortHeight = parser.getIntParameter("viewPortHeight",0); 479 browserName = parser.getStringParameter("clientBrowser",""); 480 browserVersion = parser.getStringParameter("clientBrowserVersion",""); 481 482 lastFmUserID_ = parser.getStringParameter("lastFmUserID",LASTFM_DEFAULT_USERNAME); 483 lastFmPassword_ = parser.getStringParameter("lastFmPassword",LASTFM_DEFAULT_PASSWORD); 484 lastFmSessionKey = parser.getStringParameter("lastFmSessionKey",""); 485 lastFmUserRecent = parser.getStringParameter("lastFmUserRecent",""); 486 487 lastFmPlayTrackNum = parser.getIntParameter("lastFmPlayTrackNum",0); 488 lastFmPlayTrack = parser.getStringParameter("lastFmPlayTrack","").replace("_"," ").trim(); 489 lastFmPlayAlbum = parser.getStringParameter("lastFmPlayAlbum","").replace("_"," ").trim(); 490 lastFmPlayArtist = parser.getStringParameter("lastFmPlayArtist","").replace("_"," ").trim(); 491 lastFmPlayAlbumArtist = parser.getStringParameter("lastFmPlayAlbumArtist","").replace("_"," ").trim(); 492 lastFmPlayTime = parser.getIntParameter("lastFmPlayTime",0); 493 lastFmPlayDuration = parser.getIntParameter("lastFmPlayDuration",0); 494 495 lastFmScrobbleTrack = parser.getStringParameter("lastFmScrobbleTrack","").replace("_"," ").trim(); 496 lastFmScrobbleAlbum = parser.getStringParameter("lastFmScrobbleAlbum","").replace("_"," ").trim(); 497 lastFmScrobbleArtist = parser.getStringParameter("lastFmScrobbleArtist","").replace("_"," ").trim(); 498 lastFmLoveTrack = parser.getStringParameter("lastFmLoveTrack","").replace("_"," ").trim(); 499 xmlResponse = parser.getBooleanParameter("xmlResponse",xmlResponse_); 500 501 if(debugOut_) { System.out.println(" PlayTrack="+lastFmPlayTrack+" lastFmPlayArtist="+lastFmPlayArtist +" lastFmPlayAlbumArtist="+lastFmPlayAlbumArtist );} 502 if(debugOut_) { System.out.println(" ScrobbleTrack="+lastFmScrobbleTrack+" lastFmScrobbleAlbum="+lastFmScrobbleAlbum+" lastFmScrobbleArtist="+lastFmScrobbleArtist );} 503 504 } 505 506 507 /** Convert a well-formed (but not necessarily valid) XML string into a JSON String. **/ 508 private String xmlToJson(String xml) 509 { 510 String jsonStr = ""; 511 if (xml== null || xml.length()<2) xml = ""; 512 org.json.JSONObject jsonObj = org.json.XML.toJSONObject(xml); 513 if(jsonObj!= null) jsonStr = jsonObj.toString(2); 514 return jsonStr; 515 } 516 517 518 /** 519 * This method handles the "GET" submission - it is used for Ajax calls to set webApp parameters using JQuery. 520 * 521 * @param req Description of the Parameter 522 * @param res Description of the Parameter 523 * @exception ServletException Description of the Exception 524 * @exception IOException Description of the Exception 525 */ 526 public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 527 { 528 parseParams(req); 529 530 ServletOutputStream out = res.getOutputStream(); 531 String conPath = req.getContextPath(); 532 String restPath = req.getPathInfo(); // basically anything added to the end of the URL is considered a RESt request 533 534 535 if(debugOut_) 536 { 537 System.out.println("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 538 System.out.println("Tunes AjaxRestListener.doGet "+ " debugOut="+debugOut_); 539 System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 540 } 541 542 boolean ajaxCall = false; 543 boolean restRequest = false; 544 String ajaxResponse = ""; 545 String restResponse = null; 546 547 res.setStatus(HttpServletResponse.SC_OK); // default ids OK,, set again lower downif NOT 548 549 ajaxResponse = checkForAjaxRequest(req); 550 if (!ajaxResponse.equals("")) ajaxCall=true; 551 552 if(!ajaxCall) restResponse = checkForRestRequest(req); 553 if (restResponse!=null && !restResponse.equals("")) restRequest=true; 554 555 if(debugOut_) { System.out.println("ajaxCall="+ajaxCall+" restRequest="+restRequest );} 556 /* * * * * * * * * * * EMPTY * * * * * * * * * * */ 557 /* *********************************************** */ 558 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 559 { 560 sendServletAdminPage(req, res); 561 } 562 563 if(ajaxCall) 564 { 565 res.setContentType("text/plain"); 566 // https://stackoverflow.com/questions/5750696/how-to-get-a-cross-origin-resource-sharing-cors-post-request-working 567 res.setHeader("Access-Control-Allow-Origin", "*"); 568 if(out!=null ) 569 { 570 if (debugOut_) 571 System.out.println("AJAX REPLY("+ajaxResponse.length()+")="+ajaxResponse); 572 out.print(ajaxResponse); 573 } 574 else 575 System.out.println("HttpServletResponse.ServletOutputStream is NOT ready"); 576 } 577 else if(restRequest) 578 { 579 if (xmlResponse_) res.setContentType("text/xml"); 580 else res.setContentType("application/javascript"); 581 if(restResponse!=null && !restResponse.equals("")) 582 { 583 res.setStatus(HttpServletResponse.SC_OK); 584 } 585 else 586 { 587 res.setStatus(HttpServletResponse.SC_NOT_FOUND); 588 restResponse = "<RestResponse succeeded=\"false\"><status>404</status></RestResponse>"; 589 } 590 if(out!=null ) 591 { 592 if (!xmlResponse_) restResponse = xmlToJson(restResponse); 593 if (debugOut_) 594 System.out.println("REST REPLY("+restResponse.length()+")="+restResponse); 595 out.print(restResponse); 596 } 597 else 598 System.out.println("HttpServletResponse.ServletOutputStream is NOT ready"); 599 } 600 out.flush(); 601 res.flushBuffer(); 602 } 603 604 605 /** 606 * This method handles the "POST" submissions. 607 * 608 * @param req Description of Parameter 609 * @param res Description of Parameter 610 * @exception ServletException Description of Exception 611 * @exception IOException Description of Exception 612 */ 613 public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 614 { 615 //parseParams(req); 616 617 StringBuffer postBody = new StringBuffer(""); 618 String line = null; 619 // try 620 // { 621 BufferedReader reader = req.getReader(); 622 while ((line = reader.readLine()) != null) 623 postBody.append(line+"\n"); 624 625 String postReply = ""; 626 627 // Do something with the posted message 628 // send it to a helper class if desired 629 /*String postReply = pEye_.newMessage(postBody.toString()); */ 630 631 // send back an empty reply 632 if ((postReply==null || postReply.equals(""))) 633 { 634 // send back a 200 with an empty body 635 res.setStatus(HttpServletResponse.SC_OK); 636 res.setContentLength(0); 637 postReply = ""; 638 if (debugOut_) System.out.println("AjaxRestListener.doPost: emptyreply from newMessage"); 639 } 640 /* 641 else if(!sendFastPoll_) 642 { 643 // send back the pEyeReply as the body 644 res.setStatus(HttpServletResponse.SC_OK); 645 res.setContentLength(pEyeReply.length()); 646 if (debugOut_) System.out.println("AjaxRestListener.doPost: SLOW Poll & newMessage reply existed"); 647 } 648 else // if(sendFastPoll_) 649 { 650 MessageCommand mc = new MessageCommand(pEye_.getMeterMacId()); 651 pEyeReply = mc.getSetFastPollCommandStr(fastPollFreq_,fastPollDur_); 652 653 res.setContentLength(0); // send back the setFastPollCommand string as the body 654 //if (debugOut_) System.out.println(" *!*!*!*! AjaxRestListener.doPost: Send FAST Poll to:"+pEye_.getMeterMacId() ); 655 656 // now reset fastPoll for next message 657 sendFastPoll_ = false; 658 } 659 */ 660 661 postReply = "\n"+postReply; 662 res.setContentType("application/xml"); 663 res.setStatus(HttpServletResponse.SC_OK); 664 res.setContentLength(postReply.length()); 665 666 ServletOutputStream out = res.getOutputStream(); 667 if(out!=null ) 668 { 669 if (debugOut_) System.out.println("Attempting to HttpServletResponse REPLY("+postReply.length()+")="+postReply); 670 out.print(postReply); 671 out.flush(); 672 } 673 else 674 System.out.println("HttpServletResponse.ServletOutputStream is NOT ready"); 675 676 res.flushBuffer(); 677 678 /* 679 } 680 catch (Exception e) 681 { 682 //report an error 683 e.printStackTrace(); 684 } 685 */ 686 } 687 688 689 /** Parses the REST command string and prepares the response in XML format. 690 * @param restPath is the rest command part of the rest URL 691 * @return a string holding the XML rest response OR null if not a REST Request 692 **/ 693 private String checkForRestRequest(HttpServletRequest req) throws ServletException, IOException 694 { 695 String restResponse = null; 696 String servletPath = req.getServletPath(); 697 String restPath = req.getPathInfo(); // basically anything added to the end of the URL is considered a RESt request 698 String pre = "/"; 699 boolean returnXml = xmlResponse_; // false means JSON 700 701 if (servletPath.equals("/rest") && restPath!=null && !restPath.equals("") ) 702 { 703 704 DecimalFormat dfp = new DecimalFormat( "##0" ); 705 DecimalFormat dfe = new DecimalFormat( "###0.000" ); 706 if(restPath.equals(pre+"test")) 707 { 708 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 709 /* Add In the response content */ 710 sb.append("<testNode className=\""); 711 sb.append(className_); 712 sb.append("\">"); 713 sb.append("Hello"); 714 sb.append("</testNode>"); 715 sb.append("</RestResponse>"); 716 restResponse = sb.toString(); 717 } 718 if(restPath.equals(pre+"power/current")) 719 { 720 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 721 /* Add In the response content */ 722 sb.append("</RestResponse>"); 723 restResponse = sb.toString(); 724 } 725 else if(restPath.equals(pre+"power/recent")) 726 { 727 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 728 /* Add In the response content */ 729 sb.append("</RestResponse>"); 730 restResponse = sb.toString(); 731 } 732 else if(restPath.equals(pre+"energy/recent")) 733 { 734 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 735 /* Add In the response content */ 736 sb.append("</RestResponse>"); 737 restResponse = sb.toString(); 738 } 739 else if(restPath.equals(pre+"energy/current")) 740 { 741 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 742 /* Add In the response content */ 743 sb.append("</RestResponse>"); 744 restResponse = sb.toString(); 745 } 746 else if(restPath.equals(pre+"price/current")) 747 { 748 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 749 /* Add In the response content */ 750 sb.append("</RestResponse>"); 751 restResponse = sb.toString(); 752 } 753 else if(restPath.equals(pre+"price/label/current")) 754 { 755 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 756 /* Add In the response content */ 757 sb.append("</RestResponse>"); 758 restResponse = sb.toString(); 759 } 760 761 // Database Queries 762 /* 763 - Dump the database tables directly to (JSON or ) XML using a REST call: 764 http://red.webarts.bc.ca:8080/powereye/rest/db/table/<tablename> 765 <tablename> can be reading, energy, load_device, load_type 766 767 or with the optional <number of rows> 768 positive number means sorted ascending (oldest 1st) 769 negative number means sorted descending (newest 1st) 770 http://red.webarts.bc.ca:8080/powereye/rest/db/table/<tablename>/100 771 772 These database calls are LOOOOooong so you might want to use a commandline URL query tool like 773 <a href="http://www.gnu.org/software/wget/">wget</a>, or perl or java or whatever. 774 */ 775 else if(restPath.startsWith(pre+"db/table/")) 776 { 777 returnXml = true; // false means JSON 778 String content = ""; 779 try 780 { 781 restResponse = "<RestResponse succeeded=\"false\"></RestResponse>"; 782 int tblIndex = (pre+"db/table/").length(); 783 int numRowsIndex = restPath.indexOf("/",tblIndex)+1; // /rest/db/table/reading/99 784 boolean numRowsWasSpecified = (numRowsIndex>0); 785 int numReadings = (numRowsWasSpecified?Integer.parseInt(restPath.substring(numRowsIndex)):0); //0 means send all 786 boolean sortAscendingByDate = false; // sort default is descending 787 if(numReadings<0) // negative numbers means ascending 788 { 789 sortAscendingByDate = true; 790 numReadings *= -1; // now normalize it to be a psitive rowCount 791 } 792 String tableName = (numRowsWasSpecified?restPath.substring(tblIndex,numRowsIndex-1):restPath.substring(tblIndex)); 793 794 System.out.println("Dumping DB Table: "+tableName); 795 if(numRowsWasSpecified) System.out.println(" numRows: "+numReadings +" "+ 796 (sortAscendingByDate?"ascending":"descending")); 797 java.sql.ResultSet rs = null; 798 if(tableName.equalsIgnoreCase("reading")) 799 if(numRowsWasSpecified) 800 { 801 //rs = pEye_.dumpReadingTableToRS(sortAscendingByDate,(numReadings!=0?numReadings:-1));//dumpReadingTableToRS(); 802 } 803 else 804 { 805 //rs = pEye_.dumpReadingTableToRS(); 806 } 807 else if(tableName.equalsIgnoreCase("energy")) 808 if(numRowsWasSpecified) 809 { 810 //rs = pEye_.dumpEnergyTableToRS(sortAscendingByDate,(numReadings!=0?numReadings:-1));//dumpEnergyTableToRS(); 811 } 812 else 813 { 814 //rs = pEye_.dumpEnergyTableToRS(); 815 } 816 else if(tableName.equalsIgnoreCase("load_type")) 817 if(numRowsWasSpecified) 818 { 819 //rs = pEye_.dumpDBTableToRS("load_type",numReadings);//dumpLoadTypeTableToRS(); 820 } 821 else 822 { 823 //rs = pEye_.dumpLoadTypeTableToRS(); 824 } 825 else if(tableName.equalsIgnoreCase("load_device")) 826 if(numRowsWasSpecified) 827 { 828 //rs = pEye_.dumpDBTableToRS("load_device",numReadings);//dumpLoadDeviceTableToRS(); 829 } 830 else 831 { 832 //rs = pEye_.dumpLoadDeviceTableToRS(); 833 } 834 835 if(rs!=null) 836 { 837 ResultSetConverter rsc = new ResultSetConverter(rs); 838 if (returnXml) content = rsc.convertToXml().toXML().substring("<?xml version=\"1.0\"?>".length()); 839 else content = rsc.convertToJson().toString(); 840 StringBuilder sb = new StringBuilder("<RestResponse succeeded=\"true\">"); 841 /* Add In the response content */ 842 sb.append("<db table=\""+tableName+"\">"); 843 sb.append(content); 844 sb.append("</db>"); 845 846 sb.append("</RestResponse>"); 847 restResponse = sb.toString(); 848 } 849 } 850 catch(Exception ioEx) 851 { 852 restResponse = "<RestResponse succeeded=\"false\"></RestResponse>"; 853 } 854 } 855 } 856 857 return restResponse; 858 } 859 860 861 /** Checks if this Request is an AJAX request and prepares the response in XML format. 862 * @param req the servlet request 863 * @return a string holding the response value to be returned OR null if not an expected/Valid AJAX Request 864 **/ 865 private String checkForAjaxRequest(HttpServletRequest req) throws ServletException, IOException 866 { 867 String ajaxResponse = ""; 868 // was it a JQuery Ajax call for info... (such as eagleDBDir_) 869 if (debugOut!=null &&!debugOut.equals("") ) 870 { 871 debugOut_ = Boolean.parseBoolean(debugOut); 872 setDebugOut(debugOut_); 873 //pEye_.setDebugOut(debugOut_); 874 System.out.println("AjaxRestListener.doGet - debugOut_="+debugOut_); 875 ajaxResponse = ""+debugOut_; 876 } 877 else if (viewPortWidth!=0 ) 878 { 879 // do something with the passed parms 880 viewPortWidth_=viewPortWidth; 881 req.getSession().setAttribute(CLIENT_SETTING_NAME_VIEWPORTWIDTH, viewPortWidth); 882 ajaxResponse = ""+viewPortWidth_; 883 } 884 else if (viewPortHeight!=0 ) 885 { 886 // do something with the passed parms 887 viewPortHeight_=viewPortHeight; 888 req.getSession().setAttribute(CLIENT_SETTING_NAME_VIEWPORTHEIGHT, viewPortHeight); 889 ajaxResponse = ""+viewPortHeight_; 890 } 891 else if (browserName!=null &&!browserName.equals("") ) 892 { 893 req.getSession().setAttribute(CLIENT_SETTING_NAME_BROWSER_NAME, browserName); 894 ajaxResponse = ""+browserName; 895 } 896 else if (browserVersion!=null &&!browserVersion.equals("") ) 897 { 898 req.getSession().setAttribute(CLIENT_SETTING_NAME_BROWSER_VERSION, browserVersion); 899 ajaxResponse = ""+browserVersion; 900 } 901 // Ajax Call - lastFmPlayTrack 902 else if (lastFmPlayTrack!=null && !lastFmPlayTrack.equals("") ) 903 { 904 boolean useFullData = true; 905 System.out.println("Ajax Call - lastFmPlayTrack="+lastFmPlayTrack.trim()); 906 HttpSession session = req.getSession(true); 907 System.out.println(" ajaxParam Found: lastFmPlayTrack="+lastFmPlayTrack +" lastFmPlayArtist="+lastFmPlayArtist.trim()+" lastFmPlayAlbumArtist="+lastFmPlayAlbumArtist.trim()); 908 System.out.println(" AjaxRestListener JSessionID: "+session.getId() ); 909 910 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_PLAY_TRACK, lastFmPlayTrack); 911 if (lastFmPlayArtist!=null && !lastFmPlayArtist.equals("") ) 912 { 913 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_PLAY_ARTIST, lastFmPlayArtist.trim()); 914 } else useFullData = false; 915 if (lastFmPlayAlbumArtist!=null && !lastFmPlayAlbumArtist.equals("") ) 916 { 917 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_PLAY_ALBUM_ARTIST, lastFmPlayAlbumArtist.trim()); 918 } else useFullData = false; 919 if (lastFmPlayAlbum!=null && !lastFmPlayAlbum.equals("") ) 920 { 921 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_PLAY_ALBUM, lastFmPlayAlbum.trim()); 922 } else useFullData = false; 923 // Threaded call to send a play notification to last.fm 924 loginLastFM(); 925 //HttpSession session = request.getSession(); 926 session.setAttribute("AjaxRestListener.tunesHelper", tunesHelper); 927 928 if ( lastFMInit_) 929 { 930 if(useFullData) 931 { 932 tunesHelper.nowPlaying(lastFmPlayArtist.trim(), lastFmPlayTrack.trim(), 933 lastFmPlayTime, lastFmPlayDuration, 934 lastFmPlayAlbum.trim(), lastFmPlayAlbumArtist.trim(), 935 lastFmPlayTrackNum); 936 } 937 else 938 { 939 tunesHelper.nowPlaying(lastFmPlayArtist.trim(), lastFmPlayTrack.trim()); 940 } 941 ajaxResponse = ""+lastFmPlayAlbumArtist.trim()+"/"+lastFmPlayTrack.trim(); 942 } 943 else 944 { 945 ajaxResponse = "null/null"; 946 } 947 } 948 // Ajax Call - lastFmScrobbleTrack 949 else if (lastFmScrobbleTrack!=null &&!lastFmScrobbleTrack.equals("") && (lastFmLoveTrack==null || lastFmLoveTrack.equals(""))) 950 { 951 System.out.println("Ajax Call - lastFmScrobbleTrack="+lastFmScrobbleTrack.trim()); 952 HttpSession session = req.getSession(true); 953 System.out.println(" ajaxParam Found: lastFmScrobbleTrack="+lastFmScrobbleTrack.trim() +" lastFmScrobbleArtist="+lastFmScrobbleArtist.trim()); 954 System.out.println(" AjaxRestListener SessionID: "+session.getId() ); 955 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_TRACK, lastFmScrobbleTrack); 956 if (lastFmScrobbleAlbum !=null &&!lastFmScrobbleAlbum.equals("") ) 957 { 958 System.out.println(" ajaxParam Found: lastFmScrobbleAlbum="+lastFmScrobbleAlbum ); 959 req.getSession().setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ALBUM, lastFmScrobbleAlbum.trim()); 960 } 961 if (lastFmScrobbleArtist!=null &&!lastFmScrobbleArtist.equals("") ) 962 { 963 req.getSession().setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ARTIST, lastFmScrobbleArtist.trim()); 964 } 965 // Threaded call to send a scrobble notification to last.fm 966 loginLastFM(); 967 //HttpSession session = request.getSession(); 968 session.setAttribute("AjaxRestListener.tunesHelper", tunesHelper); 969 970 if ( lastFMInit_ && !lastFmScrobbleTrack.trim().equals(lastFmPreviousScrobbleTrack)) 971 { 972 lastFmPreviousScrobbleTrack = lastFmScrobbleTrack.trim(); 973 tunesHelper.scrobble(lastFmScrobbleArtist.trim(), lastFmScrobbleAlbum.trim(), lastFmScrobbleTrack.trim()); 974 ajaxResponse = ""+lastFmScrobbleArtist.trim()+"/"+lastFmScrobbleAlbum.trim()+"/"+lastFmScrobbleTrack.trim(); 975 } 976 else 977 { 978 ajaxResponse = "null/null"; 979 } 980 } 981 // Ajax Call - lastFmLoveTrack 982 else if (lastFmLoveTrack!=null && !lastFmLoveTrack.equals("") && lastFmScrobbleTrack!=null && !lastFmScrobbleTrack.equals("") ) 983 { 984 System.out.println("Ajax Call - lastFmLoveTrack="+lastFmLoveTrack.trim()); 985 HttpSession session = req.getSession(true); 986 if (lastFmScrobbleArtist!=null &&!lastFmScrobbleArtist.equals("") ) 987 { 988 req.getSession().setAttribute(CLIENT_SETTING_NAME_LASTFM_SCROBBLE_ARTIST, lastFmScrobbleArtist.trim()); 989 } 990 System.out.println(" ajaxParam Found: lastFmLoveTrack="+lastFmLoveTrack.trim()+ 991 "lastFmScrobbleTrack="+lastFmScrobbleTrack.trim() + 992 " lastFmScrobbleArtist="+lastFmScrobbleArtist.trim()); 993 System.out.println(" AjaxRestListener SessionID: "+session.getId() ); 994 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_LOVE_TRACK, lastFmLoveTrack.trim()); 995 // Threaded call to send a love notification to last.fm 996 loginLastFM(); 997 //HttpSession session = request.getSession(); 998 session.setAttribute("AjaxRestListener.tunesHelper", tunesHelper); 999 1000 if ( lastFMInit_) 1001 { 1002 //http://10.0.0.253/tunes/ajax/?lastFmLoveTrack=1&lastFmScrobbleTrack=18TillIDie&lastFmScrobbleArtist=BryanAdams 1003 ajaxResponse = tunesHelper.loveTrack(lastFmScrobbleArtist.trim(), lastFmScrobbleTrack.trim()); 1004 //ajaxResponse = ""+lastFmScrobbleArtist+"/"+lastFmScrobbleTrack; 1005 } 1006 else 1007 { 1008 ajaxResponse = "null/null"; 1009 } 1010 } 1011 // Ajax Call - lastFmUserRecent 1012 else if (lastFmUserRecent!=null && !lastFmUserRecent.equals("") ) 1013 { 1014 ajaxResponse = "null/null"; 1015 System.out.println("Ajax Call - lastFmUserRecent="+lastFmUserRecent.trim()); 1016 HttpSession session = req.getSession(true); 1017 System.out.println(" AjaxRestListener SessionID: "+session.getId() ); 1018 session.setAttribute(CLIENT_SETTING_NAME_LASTFM_USER_RECENT, lastFmUserRecent.trim()); 1019 // Threaded call to send a play notification to last.fm 1020 loginLastFM(); 1021 //HttpSession session = request.getSession(); 1022 session.setAttribute("AjaxRestListener.tunesHelper", tunesHelper); 1023 1024 if ( lastFMInit_) 1025 { 1026 //http://10.0.0.253/tunes/ajax/?lastFmLoveTrack=1&lastFmScrobbleTrack=18TillIDie&lastFmScrobbleArtist=BryanAdams 1027 de.umass.lastfm.Track [] recentTracks = tunesHelper.retrieveLastFmRecentSongs(lastFmUserRecent.trim()); 1028 1029 // return html 1030 if(recentTracks!=null) 1031 { 1032 int [] trackPlayCount = new int[recentTracks.length]; 1033 1034 Date pt = null; 1035 Calendar pc = null; 1036 //java.util.Date nowTime = new java.util.Date(); 1037 //String currTime = DateFormat.getDateInstance().format(nowTime); 1038 DateFormat dParser = new SimpleDateFormat("EEE MMM d HH:mm:ss z YYYY"); //Sat May 19 22:03:59 PDT 2018 1039 DateTimeFormatter dtParser = DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss zzz YYYY");//Sat May 19 22:03:59 PDT 2018 1040 //Date convertedDate = null; 1041 //String output = ""; 1042 ZonedDateTime zNow = ZonedDateTime.now(); 1043 LocalDateTime lNow = LocalDateTime.now(); 1044 LocalDateTime playedLDate = null;; 1045 ZonedDateTime playedZDate = null; 1046 Duration timeSincePlayed = null; 1047 String timeSincePlayedSTR = ""; 1048 boolean shade = true; 1049 1050 //ajaxResponse = ""+recentTracks.length+" recent tracks"; 1051 ajaxResponse = "<img src=\"images/lastfm_SquareLogo.png\" height=\"32\" width=\"32\" style=\"margin-top: 2px; margin-bottom: 2px; margin-left: 9px; margin-right: 20px; float: left;\">"+ 1052 " Recent Tracks: " + 1053 tunesHelper.retrieveLastFmSessionUsername() + 1054 " <img src=\""+tunesHelper.retrieveLastFmUserImageURL()+ 1055 "\" height=\"32\" width=\"32\">" ; 1056 ajaxResponse += "<div id=\"recentTracksTableDiv\"><table class=\"w3-left-align\">"; 1057 for (int i=0; i<15 ; i++) 1058 { 1059 trackPlayCount[i] = tunesHelper.retrieveLastfmTrackPlayCount(recentTracks[i]); 1060 if(!recentTracks[i].isNowPlaying() || i==0) 1061 { 1062 pt = recentTracks[i].getPlayedWhen(); //Sat May 19 22:03:59 PDT 2018 1063 //System.out.println( recentTracks[i].getName()+" last played: " + pt); 1064 pc = toCalendar(pt); 1065 //System.out.println( recentTracks[i].getName()+" last calendar: " + pc); 1066 //convertedDate = dParser.parse(playTime); 1067 //timeOutput = formatter.format(convertedDate); 1068 //of(int year, int month, int dayOfMonth, int hour, int minute, int second) 1069 playedLDate = 1070 LocalDateTime.of(pc.get(Calendar.YEAR) , 1071 pc.get(Calendar.MONTH)+1 , 1072 pc.get(Calendar.DAY_OF_MONTH) , 1073 pc.get(Calendar.HOUR_OF_DAY) , 1074 pc.get(Calendar.MINUTE) , 1075 pc.get(Calendar.SECOND)); 1076 1077 //playedLDate = LocalDateTime.parse(playTimeStr, dtParser); 1078 playedZDate = ZonedDateTime.of(playedLDate, zNow.getZone()); 1079 //System.out.println( recentTracks[i].getName()+" last playedZDate: " + playedZDate); 1080 timeSincePlayed = Duration.between(playedZDate, zNow); 1081 //System.out.println( recentTracks[i].getName()+" Minutes since played: " + timeSincePlayed.toMinutes()); 1082 timeSincePlayedSTR = ""+timeSincePlayed.toMinutes()+" mins"; 1083 if(timeSincePlayed.toMinutes()<1) timeSincePlayedSTR = " seconds ago"; 1084 else if(timeSincePlayed.toMinutes()>=120) timeSincePlayedSTR = ""+timeSincePlayed.toHours()+" hrs"; 1085 else if(timeSincePlayed.toMinutes()>=1440) timeSincePlayedSTR = ""+timeSincePlayed.toDays()+" days"; 1086 1087 String animSpeaker = 1088 "\n <span class=\"si-icon si-icon-volume\" data-icon-name=\"volume\"><svg height=\"64\" version=\"1.1\" width=\"64\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 64 64\">\n"+ 1089 " <desc>Created with Snap</desc><defs></defs>\n"+ 1090 " <g>\n"+ 1091 " <path style=\"opacity: 1;\" fill=\"#fff\" d=\"m 37.991813,22.751636 -3.083782,3.083783 c 1.588254,1.572528 2.571897,3.753462 2.571897,6.164853 0,2.410848 -0.983643,4.592324 -2.571897,6.16431 l 3.083782,3.083782 c 2.364757,-2.368011 3.82775,-5.637242 3.82775,-9.248093 0,-3.611392 -1.462993,-6.880083 -3.82775,-9.248636 z\" transform=\"matrix(0,0,0,0,22,32)\"></path>\n"+ 1092 " <path style=\"opacity: 1;\" fill=\"#fff\" d=\"m 50.496123,32 c 0,-6.005432 -2.440672,-11.440956 -6.383379,-15.369023 L 41.05987,19.68385 c 3.149937,3.15319 5.097703,7.506925 5.097703,12.31615 0,4.808682 -1.948309,9.162417 -5.097703,12.31615 l 3.052874,3.052873 C 48.055451,43.440956 50.496123,38.005431 50.496123,32 z\" transform=\"matrix(0,0,0,0,22,32)\"></path>\n"+ 1093 " <path style=\"opacity: 1;\" fill=\"#fff\" d=\"m 59.173768,32.000271 c 0,-8.402181 -3.412386,-16.006711 -8.925453,-21.505137 l -3.068057,3.068056 c 4.72843,4.713247 7.654417,11.233274 7.654417,18.437081 0,7.203264 -2.925987,13.723833 -7.654417,18.436538 l 3.068057,3.068057 c 5.513067,-5.497884 8.925453,-13.102957 8.925453,-21.504595 z\" transform=\"matrix(0,0,0,0,22,32)\"></path>\n"+ 1094 " <polygon fill=\"#fff\" points=\"21.085,66 44,87.208 44,12.791 21.517,34 0,34 0,66 \" transform=\"matrix(0.57539192,0,0,0.57539192,3.3431808,3.2306919)\"></polygon>\n"+ 1095 " </g>\n"+ 1096 " </svg></span>\n"; 1097 animSpeaker = ""; 1098 1099 if(recentTracks[i].isNowPlaying()) 1100 timeSincePlayedSTR = "<div>"+ 1101 "<img src=\"images/equalizerBars_anim.gif\" width=46 height=46 style=\"vertical-align:middle;margin-left: 12px;argin-bottom: 1px;margin-right: 5px;\"> " 1102 +animSpeaker+"<!--span style=\"\"><Playing now</span-->"+ 1103 "</div>"; 1104 1105 if(recentTracks[i].isNowPlaying()) 1106 ajaxResponse += "<tr style=\""+"background-color: #88e;"+"\">"; 1107 else 1108 ajaxResponse += "<tr style=\""+(shade?"background-color: #ccf;":"background-color: #ddf;")+"\">"; 1109 ajaxResponse += "<td style=\"width: 48px;height: 48px;text-align: center;vertical-align: middle;\"><img src=\""+recentTracks[i].getImageURL(de.umass.lastfm.ImageSize.SMALL)+"\"></td>"; 1110 ajaxResponse += "<td style=\"height: 48px;\"><b>"+recentTracks[i].getArtist()+"</b>, "+recentTracks[i].getAlbum()+"<br>"; 1111 ajaxResponse += "<a href=\""+recentTracks[i].getUrl()+"\" target=\"_blank\">"+recentTracks[i].getName()+"</a>"; 1112 ajaxResponse += "</td>"; 1113 ajaxResponse += "<td id=\"trackPlayCount\" align=\"right\" style=\"padding: 15px;color: #002266;width: 140px;height: 48px;\">"+trackPlayCount[i]; 1114 ajaxResponse += (trackPlayCount[i]>1?" plays</td>":" play</td>"); 1115 ajaxResponse += "<td style=\""+(recentTracks[i].isNowPlaying()?"":"padding: 15px;")+"width: 160px;height: 48px;\">"+timeSincePlayedSTR+"</td>"; 1116 ajaxResponse += "</tr>"; 1117 shade = !shade; 1118 } 1119 } 1120 1121 ajaxResponse += "</table></div>"; 1122 } 1123 1124 //ajaxResponse = ""+lastFmScrobbleArtist+"/"+lastFmScrobbleTrack; 1125 } 1126 } 1127 1128 return ajaxResponse; 1129 } 1130 1131 1132 private static Calendar toCalendar(Date date) 1133 { 1134 Calendar cal = Calendar.getInstance(); 1135 if(date!=null) cal.setTime(date); 1136 return cal; 1137 } 1138 1139 /** 1140 * Logs into the last.fm session with the already provided user/pass. 1141 * this method uses TunesHelper to do this. 1142 * 1143 * @return success or not 1144 **/ 1145 private boolean loginLastFM() 1146 { 1147 if(tunesHelper == null) tunesHelper = new TunesHelper(); 1148 /* should probably also use the lastFM user pass sent by some AJAX call. */ 1149 System.out.println("\n AjaxRestListener.loginLastFM() lastFmUserID_="+lastFmUserID_+" lastFmPassword_="+lastFmPassword_); 1150 tunesHelper.setLastFmUserID(lastFmUserID_); 1151 tunesHelper.setLastFmPassword(lastFmPassword_); 1152 1153 if (tunesHelper!=null) 1154 { 1155 if (!lastFmSessionKey.equals("") ) 1156 { 1157 if (tunesHelper.restoreLastFmUserSession(lastFmSessionKey)) 1158 { 1159 lastFMInit_ = true; 1160 } 1161 else 1162 { 1163 System.out.println("\n******** Ajax Login LastFM CANT Restre... re-Initing "); 1164 lastFMInit_ = tunesHelper.initLastFmUserSession(true, lastFmUserID_, lastFmPassword_); 1165 } 1166 } 1167 } 1168 if (!lastFMInit_)System.out.println("\n *************\n -> AjaxRestListener Login ERROR - Last.fm *************\n"); 1169 return lastFMInit_; 1170 } 1171 1172 1173 /** Prepares and returns basic info page about the server. **/ 1174 private void sendServletAdminPage(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException 1175 { 1176 ServletOutputStream out = res.getOutputStream(); 1177 ServletContext context = getServletContext(); 1178 java.util.Properties sysProps = System.getProperties(); 1179 TimeZone localTz = Calendar.getInstance().getTimeZone(); 1180 int offset = localTz.getRawOffset(); 1181 // shift Daylight savings hour if needed 1182 Date dateNow = new Date(); 1183 boolean dst = localTz.inDaylightTime(dateNow); 1184 int dstOffset = localTz.getDSTSavings(); 1185 //if(dst) offset = offset + dstOffset; 1186 1187 String prop = ""; 1188 1189 // Send Back a response to be presented to the users browser 1190 res.setContentType("text/html"); 1191 out.println("<html>\n"); 1192 out.println("<head>\n"); 1193 out.println("<title>Ajax / REST Listener - Servlet Console</title>\n"); 1194 out.println("<link rel=\"icon\""); 1195 out.println(" type=\"image/png\""); 1196 out.println(" href=\"images/20x20/Eagle_sml.png\" />"); 1197 out.println("<style>"); 1198 out.println("H1 { font-weight: bolder; background-color: #000033; color: #ffffbb; font-size: 200%}"); 1199 out.println("H2 { font-weight: bolder; color: #ffff99; font-size: 160%; text-decoration: underline}"); 1200 out.println("H3 { font-weight: bolder; color: #ffff44; font-size: 140%}"); 1201 out.println("H4, H5 { color: #ffffff }"); 1202 out.println("A { color: #ffaadd }"); 1203 out.println("DT { font-weight: bolder }"); 1204 out.println("LI { line-height: 125% }"); 1205 out.println("BODY { background-color: #101066; color: #ffff44; font-size: 100%; line-height: 110% }"); 1206 out.println(".val { color: #ffffff; font: \"Lucida Console\", Monaco, monospace }"); 1207 out.println(""); 1208 out.println(""); 1209 out.println(""); 1210 out.println("</style>"); 1211 1212 //out.println("<META HTTP-EQUIV=\"refresh\" content=\"2;URL=\"javascript:history.go(-2);\">\n"); 1213 out.println("</head>\n"); 1214 out.println("<body>"); 1215 out.println("<h1>Web<i>ARTS</i> Ajax / REST Listener</h1><h2>Servlet Console</h2>"); 1216 out.println(getServletInfo()); 1217 out.println(" <h3>Parameters</h3>"); 1218 out.println(" <ul>"); 1219 out.println(" <li>debug = <span class=\"val\">"+debugOut_+"</span></li>"); 1220 out.println("<br />"); 1221 out.println(" <li>Servlet Init Params:"); 1222 out.println(" <ul>"); 1223 1224 java.util.Enumeration <String> initEnum = getInitParameterNames(); 1225 String currParamName = ""; 1226 for (; initEnum.hasMoreElements();) 1227 { 1228 currParamName = initEnum.nextElement(); 1229 out.print(" <li>"); 1230 out.print(currParamName+" = <span class=\"val\">"+getInitParameter(currParamName)); 1231 out.println("</span></li>"); 1232 } 1233 out.println(" </ul>"); 1234 out.println(" </li>"); // servlet init params 1235 1236 out.println("<br />"); 1237 out.println(" <li>Context Params for "+context.getServletContextName()+":"); 1238 out.println(" <ul>"); 1239 out.print(" <li>"); 1240 out.print("ContextPath"+" = <span class=\"val\">"+context.getContextPath()); 1241 out.println("</span></li>"); 1242 out.print(" <li>"); 1243 out.print("Real Path For Context Root"+" = <span class=\"val\">"+context.getRealPath("/")); 1244 out.println("</span></li>"); 1245 out.println(" </ul>"); 1246 out.println(" </li>"); // CONTEXT params 1247 1248 out.println("<br />"); 1249 out.println(" <li>Context <b>Init</b> Params:"); 1250 out.println(" <ul>"); 1251 initEnum = context.getInitParameterNames(); 1252 currParamName = ""; 1253 for (; initEnum.hasMoreElements();) 1254 { 1255 currParamName = initEnum.nextElement(); 1256 out.print(" <li>"); 1257 out.print(currParamName+" = <span class=\"val\">"+context.getInitParameter(currParamName)); 1258 out.println("</span></li>"); 1259 } 1260 out.println(" </ul>"); 1261 out.println(" </li>"); // context init params 1262 1263 out.println(" </ul>"); 1264 1265 out.println("<br /><br />"); 1266 out.println("<h3>Server Status</h3>"); 1267 out.println(" <ul>"); 1268 out.println(" <li>Server name = <span class=\"val\">"+req.getServerName()+" ("+req.getLocalAddr()+")</span></li>"); 1269 out.println(" <li>Server port = <span class=\"val\">"+req.getServerPort()+"</span></li>"); 1270 out.println(" <li>WebApp Engine = <span class=\"val\">"+context.getServerInfo()+"</span></li>"); 1271 out.println(" <li>Supported Servlet Version = <span class=\"val\">"+context.getMajorVersion()+"."+context.getMinorVersion()+"</span></li>"); 1272 1273 if(context.getMajorVersion()>2 && context.getMinorVersion()>-1) 1274 out.println(" <ul><li>Effective Version = <span class=\"val\">"+ 1275 context.getEffectiveMajorVersion()+"."+context.getEffectiveMinorVersion()+"</span></li></ul>"); 1276 out.println(" </li>"); 1277 if(context.getMajorVersion()>2 && context.getMinorVersion()>0) 1278 { 1279 try { 1280 out.println(" <li>Logical Hostname = <span class=\"val\">"+context.getVirtualServerName()+"</span></li>"); 1281 } catch (Exception ex) {} 1282 } 1283 1284 out.println(" <li>System Properties\n <ul>"); 1285 prop = "java.vendor"; 1286 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1287 prop = "java.runtime.version"; 1288 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1289 prop = "java.version"; 1290 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1291 prop = "os.arch"; 1292 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1293 prop = "os.name"; 1294 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1295 prop = "os.version"; 1296 out.println(" <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>"); 1297 1298 out.println(" </ul>\n </li>"); 1299 1300 out.println("<br /><br />"); 1301 out.println("<h3>Client Request</h3>"); 1302 out.println(" <ul>"); 1303 out.println(" <li>Client/proxy Host = <span class=\"val\">"+req.getRemoteHost()+" ("+req.getRemoteAddr()+")</span></li>"); 1304 out.println(" <li>Client/proxy port = <span class=\"val\">"+req.getRemotePort()+"</span></li>"); 1305 out.println(" <li>Protocol = <span class=\"val\">"+req.getProtocol()+"</span></li>"); 1306 out.println(" </ul>"); 1307 1308 out.println("<br /><br />"); 1309 out.println("<h3>Client Parms Status</h3>"); 1310 out.println(" <ul>"); 1311 out.println(" <li>Browser = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_BROWSER_NAME)+" v"+ 1312 req.getSession().getAttribute(CLIENT_SETTING_NAME_BROWSER_VERSION)+"</span></li>"); 1313 out.println(" <li>Device Type = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_DEVICE_TYPE)+"</span></li>"); 1314 out.println(" <li>viewport.width = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_VIEWPORTWIDTH)+"</span></li>"); 1315 out.println(" <li>viewport.height= <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_VIEWPORTHEIGHT)+"</span></li>"); 1316 out.println(" </ul>"); 1317 out.println("<br /><br />"); 1318 out.println("\n</body>\n</html>"); 1319 } 1320}