anchor.diff:      long _lastUpdate = new Date().getTime();
   
       public RateMeter(int rateLimit, int rateLimitPeriod){
  -      this._rate = (double) rateLimit / rateLimitPeriod / 60;
  -      this._countCap = rateLimit;
  +        this._rate = (double) rateLimit / rateLimitPeriod / 60;
  +        this._countCap = rateLimit;
       }
   
       //called when rate-limited endpoint is invoked
       public boolean click() {
  -      long ts = (new Date().getTime() - _lastUpdate) / 1000;
  -      this._lastUpdate = new Date().getTime();
  -      //assuming uniform distribution of requests over time,
  -      //reducing the counter according to # of seconds passed
  -      //since last invocation
  -      this._count = Math.max(0, this._count - ts * this._rate);
  -      if (this._count <= this._countCap) {
  -        //good to proceed
  -        this._count++;
  -        return true;
  -      }
  -      return false;
  +        long ts = (new Date().getTime() - _lastUpdate) / 1000;
  +        this._lastUpdate = new Date().getTime();
  +        //assuming uniform distribution of requests over time,
  +        //reducing the counter according to # of seconds passed
  +        //since last invocation
  +        this._count = Math.max(0, this._count - ts * this._rate);
  +        if (this._count <= this._countCap) {
  +            //good to proceed
  +            this._count++;
  +            return true;
  +        }
  +        return false;
       }
   
       public boolean canBeCleaned() {
  -      long ts = (new Date().getTime() - this._lastUpdate) / 1000;
  -      return this._count - ts * this._rate <= 0;
  -    }
  -
  -  }
  -
  -  private String PROXY_REFERER = "http://localhost/proxy.jsp";
  -  private static String DEFAULT_OAUTH = "https://www.arcgis.com/sharing/oauth2/";
  -  private static int CLEAN_RATEMAP_AFTER = 10000;
  -
  -  //setReferer if real referer exist
  -  private void setReferer(String r){
  +        long ts = (new Date().getTime() - this._lastUpdate) / 1000;
  +        return this._count - ts * this._rate <= 0;
  +    }
  +
  +}
  +
  +private String PROXY_REFERER = "http://localhost/proxy.jsp";
  +private static String DEFAULT_OAUTH = "https://www.arcgis.com/sharing/oauth2/";
  +private static int CLEAN_RATEMAP_AFTER = 10000;
  +
  +//setReferer if real referer exist
  +private void setReferer(String r){
       PROXY_REFERER = r;
  -  }
  -
  -  private byte[] readRequestPostBody(HttpServletRequest request) throws IOException{
  +}
  +
  +private byte[] readRequestPostBody(HttpServletRequest request) throws IOException{
       int clength = request.getContentLength();
       if(clength > 0) {
  -      byte[] bytes = new byte[clength];
  -      DataInputStream dataIs = new DataInputStream(request.getInputStream());
  -
  -      dataIs.readFully(bytes);
  -      dataIs.close();
  -      return bytes;
  +        byte[] bytes = new byte[clength];
  +        DataInputStream dataIs = new DataInputStream(request.getInputStream());
  +
  +        dataIs.readFully(bytes);
  +        dataIs.close();
  +        return bytes;
       }
   
       return new byte[0];
  -  }
  -
  -  private HttpURLConnection forwardToServer(HttpServletRequest request, String uri, byte[] postBody) throws IOException{
  +}
  +
  +private HttpURLConnection forwardToServer(HttpServletRequest request, String uri, byte[] postBody) throws IOException{
       Enumeration headerNames = request.getHeaderNames();
       HashMap<String, String> mapHeaderInfo = new HashMap<String, String>();
  -
       while (headerNames.hasMoreElements()) {
         String key = (String) headerNames.nextElement();
         String value = request.getHeader(key);
         if (!key.equalsIgnoreCase("host")) mapHeaderInfo.put(key, value);
       }
  -
       return
               postBody.length > 0 ?
                       doHTTPRequest(uri, postBody, "POST", mapHeaderInfo) :
                       doHTTPRequest(uri, request.getMethod());
  -  }
  -
  -  private boolean fetchAndPassBackToClient(HttpURLConnection con, HttpServletResponse clientResponse, boolean ignoreAuthenticationErrors) throws IOException{
  +}
  +
  +private boolean fetchAndPassBackToClient(HttpURLConnection con, HttpServletResponse clientResponse, boolean ignoreAuthenticationErrors) throws IOException{
       if (con!=null){
  -      Map<String, List<String>> headerFields = con.getHeaderFields();
  -
  -      Set<String> headerFieldsSet = headerFields.keySet();
  -      Iterator<String> hearerFieldsIter = headerFieldsSet.iterator();
  -
  -      while (hearerFieldsIter.hasNext()){
  -        String headerFieldKey = hearerFieldsIter.next();
  -        List<String> headerFieldValue = headerFields.get(headerFieldKey);
  -        StringBuilder sb = new StringBuilder();
  -        for (String value : headerFieldValue) {
  -          sb.append(value);
  -          sb.append("");
  -        }
  -        if (headerFieldKey != null) clientResponse.addHeader(headerFieldKey, sb.toString());
  -      }
  -
  -      InputStream byteStream;
  -      if (con.getResponseCode() >= 400 && con.getErrorStream() != null){
  -        if (ignoreAuthenticationErrors && (con.getResponseCode() == 498 || con.getResponseCode() == 499)) return true;
  -        byteStream = con.getErrorStream();
  -      }else{
  -        byteStream = con.getInputStream();
  -      }
  -
  -      clientResponse.setStatus(con.getResponseCode());
  -
  -      ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  -      final int length = 5000;
  -
  -      byte[] bytes = new byte[length];
  -      int bytesRead = 0;
  -
  -      while ((bytesRead = byteStream.read(bytes, 0, length)) > 0) {
  -        buffer.write(bytes, 0, bytesRead);
  -      }
  -      buffer.flush();
  -
  -      byte[] byteResponse = buffer.toByteArray();
  -      OutputStream ostream = clientResponse.getOutputStream();
  -      ostream.write(byteResponse);
  -      ostream.close();
  -      byteStream.close();
  +        Map<String, List<String>> headerFields = con.getHeaderFields();
  +
  +        Set<String> headerFieldsSet = headerFields.keySet();
  +        Iterator<String> hearerFieldsIter = headerFieldsSet.iterator();
  +
  +        while (hearerFieldsIter.hasNext()){
  +            String headerFieldKey = hearerFieldsIter.next();
  +            List<String> headerFieldValue = headerFields.get(headerFieldKey);
  +            StringBuilder sb = new StringBuilder();
  +            for (String value : headerFieldValue) {
  +                sb.append(value);
  +                sb.append("");
  +            }
  +            if (headerFieldKey != null) clientResponse.addHeader(headerFieldKey, sb.toString());
  +        }
  +
  +        InputStream byteStream;
  +        if (con.getResponseCode() >= 400 && con.getErrorStream() != null){
  +            if (ignoreAuthenticationErrors && (con.getResponseCode() == 498 || con.getResponseCode() == 499)) return true;
  +            byteStream = con.getErrorStream();
  +        }else{
  +            byteStream = con.getInputStream();
  +        }
  +
  +        clientResponse.setStatus(con.getResponseCode());
  +
  +        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  +        final int length = 5000;
  +
  +        byte[] bytes = new byte[length];
  +        int bytesRead = 0;
  +
  +        while ((bytesRead = byteStream.read(bytes, 0, length)) > 0) {
  +            buffer.write(bytes, 0, bytesRead);
  +        }
  +        buffer.flush();
  +
  +        byte[] byteResponse = buffer.toByteArray();
  +        OutputStream ostream = clientResponse.getOutputStream();
  +        ostream.write(byteResponse);
  +        ostream.close();
  +        byteStream.close();
       }
       return false;
  -  }
  -
  -  private boolean passHeadersInfo(Map mapHeaderInfo, HttpURLConnection con) {
  -
  +}
  +
  +private boolean passHeadersInfo(Map mapHeaderInfo, HttpURLConnection con) {
       Iterator it = mapHeaderInfo.entrySet().iterator();
       while (it.hasNext()) {
         Map.Entry pair = (Map.Entry)it.next();
  
positive.code:     String[] allowedReferers;
  
      public ServerUrl[] getServerUrls() {
        return this.serverUrls;
      }
      public void setServerUrls(ServerUrl[] value){
        this.serverUrls = value;
      }
  
      public boolean getMustMatch(){
        return this.mustMatch;
      }
      public void setMustMatch(boolean value){
        this.mustMatch = value;
      }
  
      public String[] getAllowedReferers(){
        return this.allowedReferers;
      }
      public void setAllowedReferers(String[] value){
        this.allowedReferers = value;
      }
  
      public String getLogFile(){
        return this.logFile;
      }
      public void setLogFile(String value){
        this.logFile = value;
      }
  
      public String getLogLevel(){
        return this.logLevel;
      }
      public void setLogLevel(String value){
        this.logLevel = value;
      }
  
      public ServerUrl getConfigServerUrl(String uri) {
        //split request URL to compare with allowed server URLs
        String[] uriParts = uri.split("(/)|(\\?)");
        String[] configUriParts = new String[] {};
  
        for (ServerUrl su : serverUrls) {
          //if a relative path is specified in the proxy configuration file, append what's in the request itself
          if (!su.getUrl().startsWith("http"))
            su.setUrl(new StringBuilder(su.getUrl()).insert(0, uriParts[0]).toString());
  
          configUriParts = su.getUrl().split("/");
  
          //if the request has less parts than the config, don't allow
          if (configUriParts.length > uriParts.length) continue;
  
          int i = 1;
          //skip comparing the protocol, so that either http or https is considered valid
          for (i = 1; i < configUriParts.length; i++)
          {
            if (!configUriParts[i].toLowerCase().equals(uriParts[i].toLowerCase()) ) break;
          }
          if (i == configUriParts.length)
          {
            //if the urls don't match exactly, and the individual matchAll tag is 'false', don't allow
            if (configUriParts.length == uriParts.length || su.getMatchAll())
              return su;
          }
        }
  
        if (this.mustMatch)
          return null;//if nothing match and mustMatch is true, return null
        else
          return new ServerUrl(uri); //if mustMatch is false send the server URL back that is the same the uri to pass thru
      }
  
      public static boolean isUrlPrefixMatch(String prefix, String uri){
        return uri.toLowerCase().startsWith(prefix.toLowerCase()) ||
                uri.toLowerCase().replace("https://","http://").startsWith(prefix.toLowerCase()) ||
                uri.toLowerCase().substring(uri.indexOf("//")).startsWith(prefix.toLowerCase());
      }
    }
  
    public static class ServerUrl {
      String url;
      boolean matchAll;
      String oauth2Endpoint;
  
negative.code: java.text.SimpleDateFormat" %>
  
  <!-- ----------------------------------------------------------
   *
   * JSP proxy client
   *
   * Version 1.1 beta
   * See https://github.com/Esri/resource-proxy for more information.
   *
  ----------------------------------------------------------- -->
  
  <%! final String version = "1.1 Beta";   %>
  
  <%!
  public static class RateMeter {
      double _rate; //internal rate is stored in requests per second
      int _countCap;
      double _count = 0;
  