001/*
002 *  $Id: RestRequestListener.java 1250 2018-03-15 04:14:41Z tgutwin $
003 *  $HeadURL: svn://svn.webarts.bc.ca/open/trunk/www/PowerEYE/WEB-INF/src/ca/bc/webarts/servlet/RestRequestListener.java $
004 *  $Revision: 1250 $
005 *  $LastChangedDate: 2018-03-14 21:14:41 -0700 (Wed, 14 Mar 2018) $
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.tools.eiscp.Eiscp;
026import ca.bc.webarts.tools.eiscp.IscpCommands;
027import ca.bc.webarts.tools.lednet.LedNetProxy;
028import ca.bc.webarts.widgets.Util;
029import ca.bc.webarts.widgets.ResultSetConverter;
030
031import com.oreilly.servlet.ParameterParser;
032import com.oreilly.servlet.ParameterNotFoundException;
033import com.oreilly.servlet.ServletUtils;
034
035import java.text.DecimalFormat;
036import java.io.BufferedReader;
037import java.io.File;
038import java.io.FileNotFoundException;
039import java.io.FileOutputStream;
040import java.io.FileReader;
041import java.io.FileWriter;
042import java.io.FileInputStream;
043import java.io.IOException;
044import java.io.InputStream;
045import java.io.OutputStream;
046import java.net.InetAddress;
047import java.net.MalformedURLException;
048import java.net.URL;
049import java.net.UnknownHostException;
050import java.util.Calendar;
051import java.util.Date;
052import java.util.Enumeration;
053import java.util.TimeZone;
054import java.util.zip.ZipEntry;
055import java.util.zip.ZipOutputStream;
056
057import javax.servlet.*;
058import javax.servlet.http.HttpServlet;
059import javax.servlet.http.*;
060
061import javax.json.Json;
062
063/**
064 * This class is a listener, implemented as a servlet, for general messages that get http 'post'ed.
065 * it gets mapped to listener at a URL like: http://localhost/powereye/eagle.<br /><br />I have also implemented
066 * the doGet method to provide a way to receive commands back that will get sent back to the caller in the http
067 * responses .<br /><br />This class is part of WebAPP and a number of classes to help
068 * process the messages. See also ca.bc.webarts.tools.lednet.LedNetProxy<br />
069 *
070 * @author     tgutwin
071 * @created    Jan 14, 2020
072 */
073public class RestRequestListener extends javax.servlet.http.HttpServlet
074{
075  // implements SingleThreadModel
076
077  /** Class constant. **/
078  protected static final String className_ = "RestRequestListener";
079  private final static String SYSTEM_FILE_SEPERATOR = File.separator;
080  /**  Version String.  */
081  private final static String SERVLET_VERSION = Util.spacesToCapsInString("0.0.1");
082
083  public static final String CLIENT_SETTING_NAME_VIEWPORTWIDTH = "clientSetting.viewPortWidth";
084  public static final String CLIENT_SETTING_NAME_VIEWPORTHEIGHT = "clientSetting.viewPortHeight";
085  public static final String CLIENT_SETTING_NAME_BROWSER_NAME = "clientSetting.browserName";
086  public static final String CLIENT_SETTING_NAME_BROWSER_VERSION = "clientSetting.browserVersion";
087  public static final String CLIENT_SETTING_NAME_DEVICE_TYPE = "clientSetting.deviceType";
088  public static final int REST_TYPE_LED = 1;
089  public static final int REST_TYPE_EISCP = 2;
090
091  /**  Build String. (yymmddhhss)  */
092  private final static String BUILD_TAG = "18032819";
093
094  private static String webServerHostName_ = "localhost";
095
096  /** The Helper classes. **/
097  private LedNetProxy led_ = null;
098  String ledenetIP_ = "";
099  int ledenetPort_ = 0;
100  int rest_type_ = 0;
101  private static Eiscp eiscp_ =  new Eiscp(null, 0);
102  private boolean debugOut_ = false;
103  protected static Log log_= Log.getInstance();
104
105  // parameters
106  String rgbw_="0a0a0a00";
107
108  /**
109   *  Gets the ServletInfo attribute of the JavaMailServlet object
110   *
111   * @return    The ServletInfo value
112   */
113  public String getServletInfo()
114  {
115    final String methodName = "getServletInfo";
116    return "WebARTS Design RestRequestListener servlet. Version:" + SERVLET_VERSION +
117        "  Build:" + BUILD_TAG;
118  }
119
120
121  /**
122   * The one time servlet init stuff goes here. It sets the derbyDBDir based on the following prioritized varables:
123   * <ol><li>context init param: derbyDBDir</li><li>servlet init param (from web.xml): derbyDBDir</li>
124   * <li>default hardcoded variable: derbyDBDir</li></ol>If defined in multiple places, the higher priority item will
125   * be used.
126   **/
127  public void init()
128  {
129    System.out.println("\n~~~~~~~~\n~~~~~~~~\nInitializing webarts.servlet.RestRequestListener\n~~~~~~~~\n~~~~~~~~");
130
131    boolean notFoundInit = true;
132    boolean notFoundContext = true;
133    java.util.Enumeration <String> initEnum = getInitParameterNames();
134    for (; notFoundInit && initEnum.hasMoreElements();)
135    {
136      if(initEnum.nextElement().equals("ledenetIP"))
137      {
138        notFoundInit = false;
139        /* Do something with the init param */
140        ledenetIP_ = getInitParameter("ledenetIP");
141        System.out.println("\n~~~~~~~~\n     INIT ServletParam: ledenetIP_="+ledenetIP_);
142      }
143      else if(initEnum.nextElement().equals("ledenetPort"))
144      {
145        notFoundInit = false;
146        /* Do something with the init param */
147        try
148        {
149          ledenetPort_ = Integer.parseInt(getInitParameter("ledenetPort_"));
150          System.out.println("\n~~~~~~~~\n     INIT ServletParam: ledenetPort_="+ledenetPort_);
151        }
152        catch (Exception ex)
153        { // use defaults
154          System.out.println("\n~~~~~~~~\n     INIT ServletParam: ledenetPort_ parse ERROR");
155        }
156      }
157    }
158
159    //also check context
160    initEnum = getServletConfig().getServletContext().getInitParameterNames();
161    for (; notFoundContext && initEnum.hasMoreElements();)
162    {
163      if(initEnum.nextElement().equals("ledenetIP"))
164      {
165        notFoundContext = false;
166        /* Do something with the init param */
167        ledenetIP_ = getServletConfig().getServletContext().getInitParameter("ledenetIP");
168        System.out.println("\n~~~~~~~~\n     INIT ContextParam: ledenetIP_="+ledenetIP_);
169      }
170      else if(initEnum.nextElement().equals("ledenetPort"))
171      {
172        notFoundInit = false;
173        /* Do something with the init param */
174        try
175        {
176          ledenetPort_ = Integer.parseInt(getInitParameter("ledenetPort_"));
177          System.out.println("\n~~~~~~~~\n     INIT ServletParam: ledenetPort_="+ledenetPort_);
178        }
179        catch (Exception ex)
180        { // use defaults
181          System.out.println("\n~~~~~~~~\n     INIT ServletParam: ledenetPort_ parse ERROR");
182        }
183      }
184    }
185
186    if(notFoundInit && notFoundContext )
187    {
188      /* Set the default values */
189      //eagleDBDir_ = pEye_.getDerbyDBDir();
190    }
191
192    try
193    {
194      webServerHostName_ = InetAddress.getLocalHost().getHostName();
195    }
196    catch (UnknownHostException ex)
197    {
198      webServerHostName_ = "localhost";
199    }
200
201    led_ = new LedNetProxy();// this inits the helper, which inits the EagleDB and retrieves its settings
202    //eiscp_ = new Eiscp(null, 0);  // instantiate when needed because the connectionshould always be closed
203
204
205  }
206
207
208  /**  Override to close up the persister * */
209  public void destroy()
210  {
211    super.destroy();
212  }
213
214
215
216  /**
217   * Returns the value of debugOut_.
218   */
219  public boolean getDebugOut()
220  {
221    return debugOut_;
222  }
223
224
225  /**
226   * Sets the value of debugOut_.
227   * @param debugOut The value to assign debugOut_.
228   */
229  public void setDebugOut(boolean debugOut)
230  {
231    this.debugOut_ = debugOut;
232    log_.setLogLevel((debugOut_?log_.DEBUG:log_.MINOR));
233  }
234
235
236  private void streamZIP(OutputStream servletOut, String dataName, InputStream dataStream)
237  {
238    String[] dataNames = {dataName};
239    InputStream[] dataStreams = {dataStream};
240    streamZIP(servletOut, dataNames,dataStreams);
241  }
242
243
244  /**
245   * streams to a zipped out stream (without creating a file).
246   * from: http://www.coderanch.com/t/276892/java-io/java/Stream-data-ZipOutputStream
247   * @param servletOutput is the stream to zip into
248   * @param dataNames are the pseudo fileNames that will get created in the zip (pseudo file) stream
249   * @param dataStreams the data to zip
250   **/
251  private void streamZIP(OutputStream servletOut,
252                        String[] dataNames,
253                        InputStream[] dataStreams)
254  {
255    ZipOutputStream zos = new ZipOutputStream(servletOut);
256    final int DATA_BLOCK_SIZE = 2048;
257    int byteCount;
258    byte[] data;
259
260    try
261    {
262      for(int i = 0; i < dataNames.length; i++)
263      {
264        ZipEntry ze = new ZipEntry(dataNames[i]);
265        zos.putNextEntry(ze);
266        data = new byte[DATA_BLOCK_SIZE];
267
268        while((byteCount = dataStreams[i].read(data, 0, DATA_BLOCK_SIZE)) != -1)
269        {
270          zos.write(data, 0, byteCount);
271        }
272
273        zos.flush();
274        zos.closeEntry();
275        dataStreams[i].close();
276      }
277      zos.close();
278    }
279    catch(Exception e)
280    {
281      System.err.println("Problem streaming zip data " + e.toString());
282    }
283  }
284
285
286  private void parseParams(HttpServletRequest req)
287  {
288    ParameterParser parser = new ParameterParser(req);
289    debugOut_ = parser.getBooleanParameter("debugOut", false);
290    rgbw_ = parser.getStringParameter("rgbw", "");
291
292    /*
293    reInitCache =  parser.getIntParameter("reInitCache",0);
294    shutdownDB = parser.getStringParameter("shutdownDB", "");
295    restartDB = parser.getStringParameter("restartDB", "");
296    sendFastPoll = parser.getStringParameter("setFastPoll", "");
297    fastPollFreq =  parser.getIntParameter("fastPollFreq",0);
298    fastPollDur =  parser.getIntParameter("fastPollDur",0);
299    viewPortWidth =  parser.getIntParameter("viewPortWidth",0);
300    viewPortHeight =  parser.getIntParameter("viewPortHeight",0);
301    eagleDBDir = parser.getStringParameter("eagleDBDir","");
302    browserName = parser.getStringParameter("clientBrowser","");
303    browserVersion = parser.getStringParameter("clientBrowserVersion","");
304    deviceType = parser.getStringParameter("clientDeviceType","");
305    isyEnabled = parser.getStringParameter("isyEnabled", "");
306    dstEnabled = parser.getStringParameter("dstEnabled", "");
307    isyHostname = parser.getStringParameter("isyHostname","");
308    isyLoginID = parser.getStringParameter("isyLoginID","");
309    isyLoginPassword = parser.getStringParameter("isyLoginPassword","");
310    notifyISY = parser.getStringParameter("notifyISY", "");
311    requestLastEnergy = parser.getStringParameter("requestLastEnergy", "").trim();
312    requestLastDemand = parser.getStringParameter("requestLastDemand", "").trim();
313    requestRecentDemand = parser.getStringParameter("requestRecentDemand", "").trim();
314    requestCurrentPrice = parser.getStringParameter("requestCurrentPrice", "").trim();
315    isyDeviceOn = parser.getStringParameter("isyDeviceOn", "");
316    isyDeviceOff = parser.getStringParameter("isyDeviceOff", "");
317    isyDeviceToggle = parser.getStringParameter("isyDeviceToggle", "");
318    */
319   }
320
321
322  /**
323   *  This method handles the "GET" submission - SHOULD NEVER be called by the Eagle it is used for Ajax calls to set
324   * webApp parameters using JQuery
325   * and to send commands back to the eagle on next message posted.
326   *
327   * @param  req                   Description of the Parameter
328   * @param  res                   Description of the Parameter
329   * @exception  ServletException  Description of the Exception
330   * @exception  IOException       Description of the Exception
331   */
332  public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
333  {
334    parseParams(req);
335
336    ServletOutputStream out = res.getOutputStream();
337    String conPath = req.getContextPath();
338    String restPath = req.getPathInfo();  // basically anything added to the end of the URL is considered a RESt request
339
340    boolean ajaxCall = false;
341    boolean restRequest = false;
342    String ajaxResponse = "";
343    String restResponse = null;
344
345    res.setStatus(HttpServletResponse.SC_OK);  // default ids OK,, set again lower downif NOT
346
347    ajaxResponse = checkForAjaxRequest(req);
348    if (!ajaxResponse.equals("")) ajaxCall=true;
349
350    if(!ajaxCall) restResponse = checkForRestRequest(req);
351    System.out.println("  **** checkForRestRequest: restResponse="+(restResponse!=null?restResponse:"null"));
352    if (restResponse!=null && !restResponse.equals("")) restRequest=true;
353
354    /* * * * * *  * * * * * EMPTY * * * * *  * * * * *  */
355    /* ***********************************************  */
356    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
357    {
358      sendAdminPage(req, res);
359    }
360
361    res.setContentType("text/plain");
362    if(ajaxCall)
363    {
364      if(rest_type_==REST_TYPE_LED) res.setContentType("application/xml");
365      else if(rest_type_==REST_TYPE_EISCP) res.setContentType("application/json");
366      if(out!=null  )
367      {
368        if (debugOut_)
369          System.out.println("AJAX REPLY("+ajaxResponse.length()+")="+ajaxResponse);
370        out.print(ajaxResponse);
371      }
372      else
373        System.out.println("HttpServletResponse.ServletOutputStream is NOT ready");
374    }
375    else if(restRequest)
376    {
377      if(rest_type_==REST_TYPE_LED) res.setContentType("application/xml");
378      else if(rest_type_==REST_TYPE_EISCP) res.setContentType("application/json");
379      if(restResponse!=null && !restResponse.equals(""))
380      {
381        res.setStatus(HttpServletResponse.SC_OK);
382      }
383      else
384      {
385        res.setStatus(HttpServletResponse.SC_NOT_FOUND);
386        //restResponse = "<RestResponse succeeded=\"false\"><status>404</status></RestResponse>";
387        String respStr = "404";
388        restResponse = "{\n \"success\": false,\n \"status\": \""+respStr+"\"\n}";
389
390      }
391      if(out!=null  )
392      {
393        if (debugOut_)
394          System.out.println("REST REPLY("+restResponse.length()+")="+restResponse);
395        out.print(restResponse);
396      }
397      else
398        System.out.println("HttpServletResponse.ServletOutputStream is NOT ready");
399    }
400    out.flush();
401    res.flushBuffer();
402  }
403
404
405  /**
406   *  This method handles the "POST" submission - the default way the a listener works.
407   * send a MessageCommand in the body of the reply to send a command back to the Eagle.
408   * You can tell this servlet to send a command by calling it using a parameter:<br />
409   * setFastPoll=true/false
410   * getFastPoll=true/false
411   * getHistoryData=true/false
412   * getProfileData=true/false
413   * setPollInterval=IntegerSeconds
414   *
415   * @param  req                   Description of Parameter
416   * @param  res                   Description of Parameter
417   * @exception  ServletException  Description of Exception
418   * @exception  IOException       Description of Exception
419   */
420  public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
421  {
422
423    StringBuffer postBody = new StringBuffer("");
424    String line = null;
425   // try
426   // {
427      BufferedReader reader = req.getReader();
428      while ((line = reader.readLine()) != null)
429        postBody.append(line+"\n");
430
431      // Do something with the posted message
432      // send it to the led_
433      String helperReply = "";   //  do something with the postBody    //led_.sendOnOffCommand(postBody.toString());
434
435      // send back an empty reply
436      if ((helperReply==null || helperReply.equals("")) )
437      {
438        // send back a 200 with an empty body
439        res.setStatus(HttpServletResponse.SC_OK);
440        res.setContentLength(0);
441        helperReply = "";
442        if (debugOut_) System.out.println("RestRequestListener.doPost:emptyreply from newMessage");
443      }
444      else
445      {
446        // send back the pEyeReply as the body
447        res.setStatus(HttpServletResponse.SC_OK);
448        res.setContentLength(helperReply.length());
449        if (debugOut_) System.out.println("RestRequestListener.doPost: led_ helper reply existed");
450      }
451
452      helperReply = "\n"+helperReply;
453      res.setContentType("application/xml");
454      res.setStatus(HttpServletResponse.SC_OK);
455      res.setContentLength(helperReply.length());
456
457      ServletOutputStream out = res.getOutputStream();
458      if(out!=null  )
459      {
460        if (debugOut_) System.out.println("Attempting to HttpServletResponse REPLY("+helperReply.length()+")="+helperReply);
461        out.print(helperReply);
462        out.flush();
463      }
464      else
465        System.out.println("HttpServletResponse.ServletOutputStream is NOT ready");
466
467      res.flushBuffer();
468
469      /*
470    }
471    catch (Exception e)
472    {
473      //report an error
474      e.printStackTrace();
475    }
476    */
477  }
478
479
480  /** Parses the passed in request and performs any requested services.  **/
481  private synchronized String checkForRestRequest(HttpServletRequest req) throws ServletException, IOException
482  {
483    String restResponse = null;
484    String servletPath = req.getServletPath();
485    String restPath = req.getPathInfo();  // basically anything added to the end of the URL is considered a RESt request
486    String pre = "/";
487    String preLedENet = "/led";
488    String preEiscp = "/eiscp";
489
490    System.out.println("\ncheckForRestRequest:  servletPath="+servletPath);
491    System.out.println("checkForRestRequest:  restPath="+restPath);
492
493    DecimalFormat dfp = new DecimalFormat( "##0" );
494    DecimalFormat dfe = new DecimalFormat( "###0.000" );
495
496    if (servletPath.equals(preLedENet) && restPath!=null && !restPath.equals("") )
497    {
498      rest_type_=REST_TYPE_LED;
499      if(restPath.equals("/colour/red"))
500      {
501        restResponse = "<RestResponse succeeded=\"true\"><colour r=\"255\" g=\"0\" b=\"0\" w=\"0\" >"+
502                        led_.sendColourCommand(255,0,0,0,false,true)+
503                        "</colour></RestResponse>";
504      }
505      else if(restPath.equals("/colour/blue"))
506      {
507        restResponse = "<RestResponse succeeded=\"true\"><colour r=\"0\" g=\"0\" b=\"255\" w=\"0\" >"+
508                        led_.sendColourCommand(0,0,255,0,false,true)+
509                        "</colour></RestResponse>";
510      }
511      else if(restPath.startsWith("/colour/green"))
512      {
513        restResponse = "<RestResponse succeeded=\"true\"><colour r=\"0\" g=\"255\" b=\"0\" w=\"0\" >"+
514                        led_.sendColourCommand(0,255,0,0,false,true)+
515                        "</colour></RestResponse>";
516      }
517      else if(restPath.startsWith("/colour/purple"))
518      {
519        restResponse = "<RestResponse succeeded=\"true\"><colour r=\"5\" g=\"0\" b=\"10\" w=\"0\" >"+
520                        led_.sendColourCommand(5,0,10,0,false,true)+
521                        "</colour></RestResponse>";
522      }
523      else if(restPath.startsWith("/rgbw"))
524      {
525        rgbw_ = restPath.substring("/rgbw/".length());
526        System.out.println("\nRGBW="+rgbw_);
527        System.out.println(" r="+rgbw_.substring(0,2) +" = "+led_.convertHexToString(rgbw_.substring(0,2),true));
528
529        int r = 0;int g = 0;int b = 0;int w = 0;
530        try { r = Integer.parseInt(led_.convertHexToString(rgbw_.substring(0,2),true));}catch (Exception ex) {} // use defaults
531        try { g = Integer.parseInt(led_.convertHexToString(rgbw_.substring(2,4),true));}catch (Exception ex) {} // use defaults
532        try { b = Integer.parseInt(led_.convertHexToString(rgbw_.substring(4,6),true));}catch (Exception ex) {} // use defaults
533        try { if(rgbw_.length()>7) w= Integer.parseInt(led_.convertHexToString(rgbw_.substring(6,8),true));}
534        catch (Exception ex) {} // use defaults
535
536        if(!"".equals(rgbw_))
537        {
538
539          restResponse = "<RestResponse succeeded=\"true\"><rgbw r=\""+r+"\" g=\""+g+"\" b=\""+b+"\" w=\""+w+"\" >"+
540                          led_.sendColourCommand(r,g,b,w,false,true)+
541                          "</rgbw></RestResponse>";
542        }
543      }
544
545      else if(restPath.startsWith("/on"))
546      {
547        restResponse = "<RestResponse succeeded=\"true\"><on>"+
548                        led_.sendOnOffCommand(true,true)+
549                        "</on></RestResponse>";
550      }
551      else if(restPath.startsWith("/off"))
552      {
553        restResponse = "<RestResponse succeeded=\"true\"><off>"+
554                        led_.sendOnOffCommand(false,true)+
555                        "</off></RestResponse>";
556      }
557    }
558    /* Now the eISCP requests */
559    /* ********************** */
560    else if (servletPath.equals(preEiscp) && restPath!=null && !restPath.equals("") )
561    {
562      rest_type_=REST_TYPE_EISCP;
563
564      // Parse the command
565      int command = -1;
566      String commandNameStr = restPath.substring(1, (restPath.indexOf("/",1) !=-1? restPath.indexOf("/",1) : restPath.length())).toUpperCase();
567      System.out.println("EISCP command: "+commandNameStr);
568      String commandParamStr = "";
569      String queryResponse = "";
570      String resp = "";
571
572      //eiscp_ = new Eiscp(null, 0);
573      connectToEiscp();   // gets a new connection and waits if needed
574      IscpCommands iscp = IscpCommands.getInstance();
575
576      // Fix a few alias short rest requests
577      if(commandNameStr.toUpperCase().equalsIgnoreCase("ON") || commandNameStr.toUpperCase().equalsIgnoreCase("OFF"))
578        commandNameStr="POWER_"+commandNameStr;
579
580      command = iscp.getCommand(commandNameStr);  //returns -1 if not found
581
582      if (commandNameStr.equalsIgnoreCase("MULTIPLE"))
583      {
584        /* Special case command needs to parse a parameter. */
585        // for example  /eiscp/MULTIPLE/5/VOLUME_DOWN
586        // the volume parameter gets interpretted as a HEX value, so sending a 45 means 36
587        String paramStr = restPath.toUpperCase().substring(("/MULTIPLE/").length());  //   "45";  //parse out a parameter
588        System.out.println("EISCP MULTIPLE restPath: "+restPath.toUpperCase());
589        System.out.println("               paramStr: "+paramStr);
590        int mult = Integer.parseInt(paramStr.substring(0, paramStr.indexOf("/",1)));
591
592        commandNameStr = paramStr.substring(paramStr.indexOf("/",1)+1);
593        command = iscp.getCommand(commandNameStr);
594
595        System.out.println("       MULTIPLE ["+mult+"] command: "+commandNameStr +" ("+iscp.getCommandStr(command)+")");
596        eiscp_.sendCommandMultipleTimes(command, mult, false);   //true);
597      }
598      /* Special case VOLUME_SET command needs to parse a parameter. */
599      //    /eiscp/VOLUME_SET/45
600      else if ( command == iscp.VOLUME_SET )
601      {
602        String paramStr = restPath.substring(("/VOLUME_SET/").length());  //   "45";  //parse out a parameter
603        eiscp_.setVolume(Integer.parseInt(paramStr));
604        resp=queryResponse.trim();
605        System.out.println("   ="+ iscp.getCommandName(resp));
606        restResponse = "<RestResponse succeeded=\"true\"><eiscp command=\""+commandNameStr+"\" param=\""+paramStr+"\" >"+
607                        resp+
608                        "</eiscp></RestResponse>";
609        // Switch to Using JSON
610        restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
611                       " \"param\": "+paramStr+","+
612                       " \"response\": \""+resp+"\"\n}";
613
614      }
615      // NETUSB
616      else if( commandNameStr.toUpperCase().startsWith("NETUSB_"))
617      {
618         // NETUSB  Queries
619        if(commandNameStr.toUpperCase().endsWith("QUERY") )
620        {
621          //send the command and get the response
622          queryResponse = eiscp_.sendQueryCommand(command, false, false); // false means DON't return all
623          resp=queryResponse.trim();
624          System.out.print("\nNETUSB_ quries Responses: \n  " +resp);
625          if (resp!=null && !resp.equals(""))
626          {
627              restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
628                             " \"response\": \""+resp+"\"\n}";
629              System.out.println("restResponse:   \n"+restResponse+"\n");
630          }
631        }
632        else   // any of the other NETUSB stuff
633        {
634          //send the command and
635          // FOR now get the response
636          queryResponse = eiscp_.sendQueryCommand(command, false, true); // last true means return all packet results
637          //resp=queryResponse.trim();
638          resp=eiscp_.decipherNetUsbResponse(command, queryResponse);
639          System.out.print("\nNETUSB_ Responses: \n  " +resp);
640          if (resp!=null && !resp.equals(""))
641          {
642              restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
643                             " \"response\": "+resp+"\n}";
644              System.out.println("restResponse:   \n"+restResponse+"\n");
645          }
646        }
647      }
648      /* It is a query command so send AND parse response */
649      else if(   commandNameStr.toUpperCase().endsWith("QUERY")
650              || commandNameStr.toUpperCase().endsWith("TOGGLE")
651             )
652      {
653        //send the command and get the response
654        queryResponse = eiscp_.sendQueryCommand(command, false, false);  // false means DON't return all
655        resp=queryResponse.trim();
656        System.out.print("\neiscp QUERYorTOGGLE RestResponses: \n  " +resp);
657        if (resp!=null && !resp.equals(""))
658        {
659          if (command==iscp.VOLUME_QUERY)
660          {
661            System.out.println("Deciphered:   "+eiscp_.decipherVolumeResponse(resp));
662            System.out.println("   ="+ iscp.getCommandName(resp));
663            // Switch to Using JSON
664            restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
665                           " \"response\": \""+eiscp_.deciherVolumeResponseToDecimal(resp)+"\"\n}";
666            System.out.println("restResponse:   \n"+restResponse+"\n");
667          }
668          else if (command==iscp.SOURCE_QUERY )
669          {
670            System.out.println("   ="+ iscp.getCommandName(resp));
671            System.out.println("SOURCE_QUERY SOURCE_QUERY SOURCE_QUERY SOURCE_QUERY SOURCE_QUERY SOURCE_QUERY ");
672            restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
673                           " \"source\": \""+iscp.getCommandName(resp)+"\"\n}";
674          }
675          else if (command==iscp.LISTEN_MODE_QUERY ||
676                   command==iscp.AUDIO_INFO_QUERY ||
677                   command==iscp.MUTE_QUERY ||
678                   command==iscp.VIDEO_INFO_QUERY ||
679                   command==iscp.VIDEO_WIDE_QUERY ||
680                   command==iscp.TUNING_DIRECT_QUERY ||
681                   command==iscp.TUNING_PRESET_QUERY||
682                   command==iscp.MUTE_TOGGLE
683                 )
684          {
685            System.out.println("   ="+ iscp.getCommandName(resp));
686            restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
687                           //" \"param\":"+paramStr+"\"\n"+
688                           " \"response\": \""+resp+"\"\n}";
689          }
690          else
691          {
692            System.out.println("   ="+ iscp.getCommandName(resp));
693            restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
694                           //" \"param\":"+paramStr+"\"\n"+
695                           " \"response\": \""+resp+"\"\n}";
696          }
697        }
698        else
699          System.out.println("\nEMPTY");
700      }
701      else if( commandNameStr.toUpperCase().startsWith("DUMP"))
702      {
703        resp = eiscp_.getCommandList();
704        restResponse = "<RestResponse succeeded=\"true\"><eiscp command=\""+commandNameStr+"\" >"+
705                        //"<![CDATA["+resp+"]]>"+
706                        resp+
707                        "</eiscp></RestResponse>";
708            restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
709                           //" \"param\":"+paramStr+"\"\n"+
710                           " \"response\": \""+resp+"\"\n}";
711      }
712      else   //if(commandNameStr.equalsIgnoreCase("POWER_ON") || commandNameStr.equals("POWER_OFF"))
713      {
714        /* It is a basic change setting command (with no response) */
715        resp="none";
716        eiscp_.sendCommand(command);
717        restResponse = "<RestResponse succeeded=\"true\"><eiscp command=\""+commandNameStr+"\" >"+
718                        resp+
719                        "</eiscp></RestResponse>";
720        restResponse = "{\n \"success\": true,\n \"eiscpCommand\": \""+commandNameStr+"\",\n"+
721                           //" \"param\":"+paramStr+"\"\n"+
722                           " \"response\": \""+resp+"\"\n}";
723      }
724      //eiscp_.closeSocket();
725    } //eiscp rest
726    else
727    {
728      System.out.println(" ....  RestRequestListener: BAD request");
729      if (servletPath.equals(preEiscp))
730      {
731        restResponse = "{\n \"success\": false,\n \"eiscpCommand\": \""+(restPath!=null?restPath:"none")+"\",\n"+
732                           " \"response\": \""+"none"+"\"\n}";
733      }
734    }
735
736    return restResponse;
737  }
738
739
740  private void connectToEiscp()
741  {
742    //if(eiscp_.isConnected()) Util.sleep(250);
743    eiscp_.connectSocket();
744  }
745
746
747  private String checkForAjaxRequest(HttpServletRequest req) throws ServletException, IOException
748  {
749    String ajaxResponse = "";
750        // was  it a JQuery Ajax call for info...  (such as eagleDBDir_)
751    /*
752    if (eagleDBDir!=null &&!eagleDBDir.equals("") )
753    {
754      eagleDBDir_=eagleDBDir;
755      // do something with the passed parms
756      pEye_.setDerbyDBDir(eagleDBDir_);
757      ajaxResponse = eagleDBDir_;
758    }
759    else if (reInitCache>0 )
760    {
761        reInitCache_ = reInitCache;
762        pEye_.initReadingsCache(reInitCache_);
763        System.out.println("PowerEYEListener.doGet - reInitCache_="+reInitCache_);
764        ajaxResponse = ""+reInitCache_;
765    }
766    else if (debugOut!=null &&!debugOut.equals("") )
767    {
768        debugOut_ =  Boolean.parseBoolean(debugOut);
769        setDebugOut(debugOut_);
770        pEye_.setDebugOut(debugOut_);
771        System.out.println("PowerEYEListener.doGet - debugOut_="+debugOut_);
772        ajaxResponse = ""+debugOut_;
773    }
774    else if (isyEnabled!=null &&!isyEnabled.equals("") )
775    {
776        isyEnabled_ =  Boolean.parseBoolean(isyEnabled);
777        pEye_.setIsyEnabled(isyEnabled_);
778        if (isyEnabled_) pEye_.initISY();
779        System.out.println("PowerEYEListener.doGet - isyEnabled_="+isyEnabled_);
780        ajaxResponse = (pEye_.isIsyConnected()?pEye_.getIsyConfigNameIdStr():"not configured");
781    }
782    else if (dstEnabled!=null &&!dstEnabled.equals("") )
783    {
784        dstEnabled_ =  Boolean.parseBoolean(dstEnabled);
785        pEye_.setForceDSTAdjustment(dstEnabled_);
786        System.out.println("PowerEYEListener.doGet - dstEnabled_="+dstEnabled_);
787        ajaxResponse = ""+dstEnabled_;
788    }
789    else if (shutdownDB!=null &&!shutdownDB.equals("") )
790    {
791        shutdownDB_ =  Boolean.parseBoolean(shutdownDB);
792        System.out.println("PowerEYEListener.doGet - shutdownDB_="+shutdownDB_);
793        pEye_.closePersister();
794        ajaxResponse = ""+shutdownDB_;
795    }
796    else if (restartDB!=null &&!restartDB.equals("") )
797    {
798        restartDB_ =  Boolean.parseBoolean(restartDB);
799        System.out.println("PowerEYEListener.doGet - restartDB_="+restartDB_);
800        if(restartDB_) pEye_.restartDerbyDB();
801        ajaxResponse = ""+restartDB_;
802    }
803    else if (sendFastPoll!=null &&!sendFastPoll.equals("") )
804    {
805        sendFastPoll_ =  Boolean.parseBoolean(sendFastPoll);
806        System.out.println("PowerEYEListener.doGet - sendFastPoll_="+sendFastPoll_);
807        ajaxResponse = ""+sendFastPoll_;
808    }
809    else if (notifyISY!=null &&!notifyISY.equals("") )
810    {
811        notifyISY_ =  Boolean.parseBoolean(notifyISY);
812        setDebugOut(notifyISY_);
813        pEye_.setNotifyISY(notifyISY_);
814        System.out.println("PowerEYEListener.doGet - notifyISY_="+notifyISY_);
815        ajaxResponse = ""+notifyISY_;
816    }
817    else if (isyHostname!=null &&!isyHostname.equals("") )
818    {
819      pEye_.setIsyEnabled(true);
820        isyHostname_ =  isyHostname.trim();
821        System.out.println("PowerEYEListener.doGet - > > > > > > isyHostname_="+isyHostname_);
822        pEye_.setIsyHostname(isyHostname_);
823        ajaxResponse = (pEye_.isIsyConnected()?pEye_.getIsyConfigNameIdStr():"not configured");
824    }
825    else if (isyLoginID!=null &&!isyLoginID.equals("") )
826    {
827      pEye_.setIsyEnabled(true);
828        isyLoginID_ =  isyLoginID.trim();
829        System.out.println("PowerEYEListener.doGet - > > > > > > isyLoginID_="+isyLoginID_);
830        pEye_.setIsyLoginID(isyLoginID_);
831        ajaxResponse = ""+(pEye_.isIsyConnected()?pEye_.getIsyConfigNameIdStr():"not configured");
832    }
833    else if (isyLoginPassword!=null &&!isyLoginPassword.equals("") )
834    {
835      pEye_.setIsyEnabled(true);
836        isyLoginPassword_ =  isyLoginPassword.trim();
837        System.out.println("PowerEYEListener.doGet - > > > > > > isyLoginPassword_="+isyLoginPassword_);
838        pEye_.setIsyLoginPassword(isyLoginPassword_);
839        ajaxResponse = (pEye_.isIsyConnected()?pEye_.getIsyConfigNameIdStr():"not configured");
840    }
841    else if (isyDeviceOff!=null &&!isyDeviceOff.equals("") )
842    {
843        isyDeviceOff_ =  isyDeviceOff.trim();
844        System.out.println("PowerEYEListener.doGet - isyDeviceOff_="+isyDeviceOff_);
845        pEye_.sendIsyDeviceOff(isyDeviceOff_);
846        ajaxResponse = ""+isyDeviceOff_;
847    }
848    else if (isyDeviceOn!=null &&!isyDeviceOn.equals("") )
849    {
850        isyDeviceOn_ =  isyDeviceOn.trim();
851        System.out.println("PowerEYEListener.doGet - isyDeviceOn_="+isyDeviceOn_);
852        pEye_.sendIsyDeviceOn(isyDeviceOn_);
853        ajaxResponse = ""+isyDeviceOn_;
854    }
855    else if (isyDeviceToggle!=null &&!isyDeviceToggle.equals("") )
856    {
857        isyDeviceToggle_ =  isyDeviceToggle.trim();
858        System.out.println("PowerEYEListener.doGet - isyDeviceToggle_="+isyDeviceToggle_);
859        pEye_.sendIsyDeviceToggle(isyDeviceToggle_);
860        ajaxResponse = ""+isyDeviceToggle_;
861    }
862    else if (viewPortWidth!=0 )
863    {
864      // do something with the passed parms
865      viewPortWidth_=viewPortWidth;
866      req.getSession().setAttribute(CLIENT_SETTING_NAME_VIEWPORTWIDTH, viewPortWidth);
867      ajaxResponse = ""+viewPortWidth_;
868    }
869    else if (viewPortHeight!=0 )
870    {
871      // do something with the passed parms
872      viewPortHeight_=viewPortHeight;
873      req.getSession().setAttribute(CLIENT_SETTING_NAME_VIEWPORTHEIGHT, viewPortHeight);
874      ajaxResponse = ""+viewPortHeight_;
875    }
876    else if (browserName!=null &&!browserName.equals("") )
877    {
878      req.getSession().setAttribute(CLIENT_SETTING_NAME_BROWSER_NAME, browserName);
879      ajaxResponse = ""+browserName;
880    }
881    else if (browserVersion!=null &&!browserVersion.equals("") )
882    {
883      req.getSession().setAttribute(CLIENT_SETTING_NAME_BROWSER_VERSION, browserVersion);
884      ajaxResponse = ""+browserVersion;
885    }
886    else if (deviceType!=null &&!deviceType.equals("") )
887    {
888      req.getSession().setAttribute(CLIENT_SETTING_NAME_DEVICE_TYPE, deviceType);
889      ajaxResponse = ""+deviceType;
890    }
891    else if (requestLastEnergy!=null &&!requestLastEnergy.equals("") && requestLastEnergy.equals("true") )
892    {
893      DecimalFormat dfe = new DecimalFormat( "0.00" );
894      double meterReading  = pEye_.getCurrentMeterRead();
895      ajaxResponse = dfe.format(meterReading);
896    }
897    else if (requestLastDemand!=null &&!requestLastDemand.equals("") && requestLastDemand.equals("true") )
898    {
899      DecimalFormat dfp = new DecimalFormat( "0" );
900      double lastDemandReading  = pEye_.getCurrentDemand();
901      ajaxResponse = dfp.format(lastDemandReading);
902    }
903    else if (requestCurrentPrice!=null &&!requestCurrentPrice.equals("") && requestCurrentPrice.equals("true") )
904    {
905      DecimalFormat dfp = new DecimalFormat( "0.00" );
906      double currentPrice  = pEye_.getCurrentPrice();
907      ajaxResponse = dfp.format(currentPrice);
908    }
909    else if (maxSqlResultSetRows!=null &&!maxSqlResultSetRows.equals("") )
910    {
911      int maxRows = Integer.parseInt(maxSqlResultSetRows);
912      pEye_.maxSqlResultSetRows_ = maxRows;
913      System.out.println("PowerEYEListener.doGet AJAX - maxSqlResultSetRows_="+pEye_.maxSqlResultSetRows_);
914      ajaxResponse = ""+maxRows;
915    }
916
917    */
918    return ajaxResponse;
919  }
920
921
922  private void sendAdminPage(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
923  {
924    ServletOutputStream out = res.getOutputStream();
925    ServletContext context = getServletContext();
926    java.util.Properties sysProps = System.getProperties();
927    TimeZone localTz = Calendar.getInstance().getTimeZone();
928    int offset = localTz.getRawOffset();
929    // shift Daylight savings hour if needed
930    Date dateNow = new Date();
931    boolean dst = localTz.inDaylightTime(dateNow) ;
932    int dstOffset = localTz.getDSTSavings();
933    //if(dst) offset = offset + dstOffset;
934
935    String prop = "";
936
937      // Send Back a response to be presented to the users browser
938      res.setContentType("text/html");
939      out.println("<!DOCTYPE html>\n");
940      out.println("<html>\n");
941      out.println("<head>\n");
942      out.println("<title>Rest Request Listener - Servlet Console</title>\n");
943      out.println("<meta charset=\"UTF-8\">");
944
945      out.println("<link rel=\"icon\"");
946      out.println("     type=\"image/png\"");
947      out.println("     href=\"images/20x20/Eagle_sml.png\" />");
948      out.println("<style>");
949      out.println("H1 { font-weight: bolder; background-color: #000033; color: #ffffbb;  font-size: 200%}");
950      out.println("H2 { font-weight: bolder; color: #ffff99;  font-size: 160%; text-decoration: underline}");
951      out.println("H3 { font-weight: bolder; color: #ffff44;  font-size: 140%}");
952      out.println("H4, H5 { color: #ffffff }");
953      out.println("A { color: #ffaadd }");
954      out.println("DT { font-weight: bolder }");
955      out.println("LI { line-height: 125% }");
956      out.println("BODY { background-color: #101066; color: #ffff44; font-size: 100%; line-height: 110% }");
957      out.println(".val { color: #ffffff; font: \"Lucida Console\", Monaco, monospace  }");
958      out.println("");
959      out.println("");
960      out.println("");
961      out.println("</style>");
962
963      //out.println("<META HTTP-EQUIV=\"refresh\" content=\"2;URL=\"javascript:history.go(-2);\">\n");
964      out.println("</head>\n");
965      out.println("<body>");
966      out.println("<h1>RestRequestListener API Listener</h1><h2>Servlet Console</h2>");
967      out.println("<a href=\""+req.getContextPath()+"\">REST WebAPP</a><br />");
968      out.println(" <h3>Parameters</h3>");
969      out.println("  <ul>");
970      out.println("    <li>debug          = <span class=\"val\">"+debugOut_+"</span></li>");
971      out.println("<br />");
972      out.println("    <li>Servlet Init Params:");
973      out.println("        <ul>");
974
975      java.util.Enumeration <String> initEnum = getInitParameterNames();
976      String currParamName = "";
977      for (; initEnum.hasMoreElements();)
978      {
979        currParamName = initEnum.nextElement();
980        out.print("            <li>");
981        out.print(currParamName+" = <span class=\"val\">"+getInitParameter(currParamName));
982        out.println("</span></li>");
983      }
984      out.println("       </ul>");
985      out.println("    </li>"); // servlet init params
986
987      out.println("<br />");
988      out.println("    <li>Context Params for "+context.getServletContextName()+":");
989      out.println("        <ul>");
990        out.print("          <li>");
991        out.print("ContextPath"+" = <span class=\"val\">"+req.getContextPath());
992        out.println("</span></li>");
993        out.print("          <li>");
994        out.print("Real Path For Context Root"+" = <span class=\"val\">"+context.getRealPath("/"));
995        out.println("</span></li>");
996      out.println("       </ul>");
997      out.println("  </li>"); // CONTEXT  params
998
999      out.println("<br />");
1000      out.println("  <li>Context <b>Init</b> Params:");
1001      out.println("      <ul>");
1002      initEnum = context.getInitParameterNames();
1003      currParamName = "";
1004      for (; initEnum.hasMoreElements();)
1005      {
1006        currParamName = initEnum.nextElement();
1007        out.print("          <li>");
1008        out.print(currParamName+" = <span class=\"val\">"+context.getInitParameter(currParamName));
1009        out.println("</span></li>");
1010      }
1011      out.println("       </ul>");
1012      out.println("    </li>"); // context init params
1013
1014      out.println("  </ul>");
1015
1016      out.println("<br /><br />");
1017      out.println("<h3>Server Status</h3>");
1018      out.println("  <ul>");
1019      out.println("    <li>Server name = <span class=\"val\">"+req.getServerName()+" ("+req.getLocalAddr()+")</span></li>");
1020      out.println("    <li>Server port = <span class=\"val\">"+req.getServerPort()+"</span></li>");
1021      out.println("    <li>WebApp Engine = <span class=\"val\">"+context.getServerInfo()+"</span></li>");
1022      out.println("    <li>Supported Servlet Version = <span class=\"val\">"+context.getMajorVersion()+"."+context.getMinorVersion()+"</span>");
1023
1024      if(context.getMajorVersion()>2 && context.getMinorVersion()>-1)
1025          out.println("      <ul><li>Effective Version = <span class=\"val\">"+
1026                      context.getEffectiveMajorVersion()+"."+context.getEffectiveMinorVersion()+"</span></li></ul>");
1027      out.println("      </li>");
1028      if(context.getMajorVersion()>2 && context.getMinorVersion()>0)
1029      {
1030        try {
1031          out.println("    <li>Logical Hostname = <span class=\"val\">"+context.getVirtualServerName()+"</span></li>");
1032        } catch (Exception ex) {}
1033      }
1034
1035      out.println("    <li>System Properties\n      <ul>");
1036      prop = "java.vendor";
1037      out.println("       <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>");
1038      prop = "java.runtime.version";
1039      out.println("       <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>");
1040      prop = "java.version";
1041      out.println("       <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>");
1042      prop = "os.arch";
1043      out.println("       <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>");
1044      prop = "os.name";
1045      out.println("       <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>");
1046      prop = "os.version";
1047      out.println("       <li>"+prop+" = <span class=\"val\">"+sysProps.getProperty(prop)+"</span></li>");
1048
1049      out.println("      <li>Test Links<span class=\"val\">"+context.getServerInfo()+"</span></li>");
1050
1051      out.println("      </ul>\n      </li>");
1052
1053      out.println("    <li>Time Details\n      <ul>");
1054      out.println("        <li>Time = <span class=\"val\">"+(dateNow).toString()+"</span></li>");
1055      out.println("        <li>Timezone = <span class=\"val\">"+localTz.getDisplayName()+"</span></li>");
1056      out.println("        <li>Timezone Offset from UTC (hrs)= <span class=\"val\">"+(offset/60/60/1000)+"</span></li>");// in milliseconds offset
1057      out.println("        <li>Within Daylight Savings period? = <span class=\"val\">"+dst+"</span></li>");
1058      out.println("        <li>Additional Daylight Savings offest (hrs) = <span class=\"val\">"+(dstOffset/60/60/1000)+"</span></li>");
1059      out.println("        <li>Total offest from UTC (hrs) = <span class=\"val\">"+((offset+dstOffset)/60/60/1000)+"</span></li>");
1060      out.println("      </ul>\n      </li>");
1061
1062      out.println("      <li>Test Links\n      <ul>");
1063      out.println("       <li><a href=\""+req.getContextPath()+"/rest/energy/calculated\">Calculated Energy Data</a></li>");
1064      out.println("        </ul>\n      </li>");
1065
1066      out.println("  </ul>");
1067
1068      out.println("<br /><br />");
1069      out.println("<h3>Client Request</h3>");
1070      out.println("  <ul>");
1071      out.println("    <li>Client/proxy Host = <span class=\"val\">"+req.getRemoteHost()+" ("+req.getRemoteAddr()+")</span></li>");
1072      out.println("    <li>Client/proxy port = <span class=\"val\">"+req.getRemotePort()+"</span></li>");
1073      out.println("    <li>Protocol = <span class=\"val\">"+req.getProtocol()+"</span></li>");
1074      out.println("  </ul>");
1075
1076      out.println("<br /><br />");
1077      out.println("<h3>Client Parms Status</h3>");
1078      out.println("  <ul>");
1079      out.println("    <li>Browser = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_BROWSER_NAME)+" v"+
1080                  req.getSession().getAttribute(CLIENT_SETTING_NAME_BROWSER_VERSION)+"</span></li>");
1081      out.println("    <li>Device Type = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_DEVICE_TYPE)+"</span></li>");
1082      out.println("    <li>viewport.width = <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_VIEWPORTWIDTH)+"</span></li>");
1083      out.println("    <li>viewport.height= <span class=\"val\">"+req.getSession().getAttribute(CLIENT_SETTING_NAME_VIEWPORTHEIGHT)+"</span></li>");
1084      out.println("  </ul>");
1085      out.println("<br /><br />");
1086      out.println("\n</body>\n</html>");
1087  }
1088}