public void doGet(HttpServletRequest request, HttpServletResponse response) {
    log.info("doGet(): " + UsageLog.setupRequestContext(request));
    // System.out.printf("opendap doGet: req=%s%n%s%n", ServletUtil.getRequest(request),
    // ServletUtil.showRequestDetail(this, request));

    String path = null;

    ReqState rs = getRequestState(request, response);

    try {
      path = request.getPathInfo();
      log.debug("doGet path={}", path);

      if (thredds.servlet.Debug.isSet("showRequestDetail"))
        log.debug(ServletUtil.showRequestDetail(this, request));

      if (path == null) {
        log.info(
            "doGet(): "
                + UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_NOT_FOUND, -1));
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
        return;
      }

      if (baseURI == null) { // first time, set baseURI
        URI reqURI = ServletUtil.getRequestURI(request);
        // Build base URI from request (rather than hard-coding "/thredds/dodsC/").
        String baseUriString = request.getContextPath() + request.getServletPath() + "/";
        baseURI = reqURI.resolve(baseUriString);
        log.debug("doGet(): baseURI was set = {}", baseURI);
      }

      if (path.endsWith("latest.xml")) {
        DataRootHandler.getInstance().processReqForLatestDataset(this, request, response);
        return;
      }

      // Redirect all catalog requests at the root level.
      if (path.equals("/") || path.equals("/catalog.html") || path.equals("/catalog.xml")) {
        ServletUtil.sendPermanentRedirect(ServletUtil.getContextPath() + path, request, response);
        return;
      }

      // Make sure catalog requests match a dataRoot before trying to handle.
      if (path.endsWith("/") || path.endsWith("/catalog.html") || path.endsWith("/catalog.xml")) {
        if (!DataRootHandler.getInstance().hasDataRootMatch(path)) {
          log.info(
              "doGet(): "
                  + UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_NOT_FOUND, -1));
          response.sendError(HttpServletResponse.SC_NOT_FOUND);
          return;
        }

        if (!DataRootHandler.getInstance().processReqForCatalog(request, response))
          log.error(
              "doGet(): "
                  + UsageLog.closingMessageForRequestContext(
                      ServletUtil.STATUS_FORWARD_FAILURE, -1));

        return;
      }

      if (rs != null) {
        String dataSet = rs.getDataSet();
        String requestSuffix = rs.getRequestSuffix();

        if ((dataSet == null) || dataSet.equals("/") || dataSet.equals("")) {
          doGetDIR(rs);
        } else if (requestSuffix.equalsIgnoreCase("blob")) {
          doGetBLOB(rs);
        } else if (requestSuffix.equalsIgnoreCase("close")) {
          doClose(rs);
        } else if (requestSuffix.equalsIgnoreCase("dds")) {
          doGetDDS(rs);
        } else if (requestSuffix.equalsIgnoreCase("das")) {
          doGetDAS(rs);
        } else if (requestSuffix.equalsIgnoreCase("ddx")) {
          doGetDDX(rs);
        } else if (requestSuffix.equalsIgnoreCase("dods")) {
          doGetDAP2Data(rs);
        } else if (requestSuffix.equalsIgnoreCase("asc")
            || requestSuffix.equalsIgnoreCase("ascii")) {
          doGetASC(rs);
        } else if (requestSuffix.equalsIgnoreCase("info")) {
          doGetINFO(rs);
        } else if (requestSuffix.equalsIgnoreCase("html")
            || requestSuffix.equalsIgnoreCase("htm")) {
          doGetHTML(rs);
        } else if (requestSuffix.equalsIgnoreCase("ver")
            || requestSuffix.equalsIgnoreCase("version")
            || dataSet.equalsIgnoreCase("/version")
            || dataSet.equalsIgnoreCase("/version/")) {
          doGetVER(rs);
        } else if (dataSet.equalsIgnoreCase("/help")
            || dataSet.equalsIgnoreCase("/help/")
            || dataSet.equalsIgnoreCase("/" + requestSuffix)
            || requestSuffix.equalsIgnoreCase("help")) {
          doGetHELP(rs);
        } else {
          sendErrorResponse(response, HttpServletResponse.SC_BAD_REQUEST, "Unrecognized request");
          return;
        }

      } else {
        sendErrorResponse(response, HttpServletResponse.SC_BAD_REQUEST, "Unrecognized request");
        return;
      }

      log.info(UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_OK, -1));

      // plain ol' 404
    } catch (FileNotFoundException e) {
      sendErrorResponse(response, HttpServletResponse.SC_NOT_FOUND, e.getMessage());

      // DAP2Exception bad url
    } catch (BadURLException e) {
      log.info(UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_BAD_REQUEST, -1));
      response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
      dap2ExceptionHandler(e, rs);

      // all other DAP2Exception
    } catch (DAP2Exception de) {
      int status =
          (de.getErrorCode() == DAP2Exception.NO_SUCH_FILE)
              ? HttpServletResponse.SC_NOT_FOUND
              : HttpServletResponse.SC_BAD_REQUEST;
      if ((de.getErrorCode() != DAP2Exception.NO_SUCH_FILE) && (de.getErrorMessage() != null))
        log.debug(de.getErrorMessage());
      log.info(UsageLog.closingMessageForRequestContext(status, -1));
      response.setStatus(status);
      dap2ExceptionHandler(de, rs);

      // parsing, usually the CE
    } catch (ParseException pe) {
      log.info(UsageLog.closingMessageForRequestContext(HttpServletResponse.SC_BAD_REQUEST, -1));
      response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
      parseExceptionHandler(pe, response);

      // 403 - request too big
    } catch (UnsupportedOperationException e) {
      sendErrorResponse(response, HttpServletResponse.SC_FORBIDDEN, e.getMessage());

    } catch (java.net.SocketException e) {
      log.info("SocketException: " + e.getMessage(), e);
      log.info(UsageLog.closingMessageForRequestContext(ServletUtil.STATUS_CLIENT_ABORT, -1));

    } catch (IOException e) {
      String eName =
          e.getClass().getName(); // dont want compile time dependency on ClientAbortException
      if (eName.equals("org.apache.catalina.connector.ClientAbortException")) {
        log.debug("ClientAbortException: " + e.getMessage());
        log.info(UsageLog.closingMessageForRequestContext(ServletUtil.STATUS_CLIENT_ABORT, -1));
        return;
      }

      log.error("path= " + path, e);
      sendErrorResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());

      // everything else
    } catch (Throwable t) {
      log.error("path= " + path, t);
      t.printStackTrace();
      sendErrorResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, t.getMessage());
    }
  }
  /**
   * ************************************************************************ Default handler for
   * OPeNDAP ascii requests. Returns OPeNDAP DAP2 data in comma delimited ascii columns for
   * ingestion into some not so OPeNDAP enabled application such as MS-Excel. Accepts constraint
   * expressions in exactly the same way as the regular OPeNDAP dataserver.
   *
   * @param request
   * @param response
   * @param dataSet
   * @throws opendap.dap.DAP2Exception
   * @throws ParseException
   */
  public void sendASCII(HttpServletRequest request, HttpServletResponse response, String dataSet)
      throws DAP2Exception, ParseException {

    if (Debug.isSet("showResponse"))
      System.out.println(
          "Sending OPeNDAP ASCII Data For: "
              + dataSet
              + "    CE: '"
              + request.getQueryString()
              + "'");

    String requestURL, ce;
    DConnect2 url;
    DataDDS dds;

    if (request.getQueryString() == null) {
      ce = "";
    } else {
      ce = "?" + request.getQueryString();
    }

    int suffixIndex = request.getRequestURL().toString().lastIndexOf(".");

    requestURL = request.getRequestURL().substring(0, suffixIndex);

    if (Debug.isSet("showResponse")) {
      System.out.println("New Request URL Resource: '" + requestURL + "'");
      System.out.println("New Request Constraint Expression: '" + ce + "'");
    }

    try {

      if (_Debug) System.out.println("Making connection to .dods service...");
      url = new DConnect2(requestURL, true);

      if (_Debug) System.out.println("Requesting data...");
      dds = url.getData(ce, null, new asciiFactory());

      if (_Debug) System.out.println(" ASC DDS: ");
      if (_Debug) dds.print(System.out);

      PrintWriter pw = new PrintWriter(response.getOutputStream());
      PrintWriter pwDebug = new PrintWriter(System.out);

      if (dds != null) {
        dds.print(pw);
        pw.println("---------------------------------------------");

        String s = "";
        Enumeration e = dds.getVariables();

        while (e.hasMoreElements()) {
          BaseType bt = (BaseType) e.nextElement();
          if (_Debug) ((toASCII) bt).toASCII(pwDebug, true, null, true);
          // bt.toASCII(pw,addName,getNAme(),true);
          ((toASCII) bt).toASCII(pw, true, null, true);
        }
      } else {

        String betterURL =
            request.getRequestURL().substring(0, request.getRequestURL().lastIndexOf("."))
                + ".dods?"
                + request.getQueryString();

        pw.println("-- ASCII RESPONSE HANDLER PROBLEM --");
        pw.println("");
        pw.println("The ASCII response handler was unable to obtain requested data set.");
        pw.println("");
        pw.println("Because this handler calls it's own OPeNDAP server to get the requested");
        pw.println("data the source error is obscured.");
        pw.println("");
        pw.println("To get a better idea of what is going wrong, try requesting the URL:");
        pw.println("");
        pw.println("    " + betterURL);
        pw.println("");
        pw.println("And then look carefully at the returned document. Note that if you");
        pw.println("are using a browser to access the URL the returned document will");
        pw.println("more than likely be treated as a download and written to your");
        pw.println("local disk. It should be a file with the extension \".dods\"");
        pw.println("");
        pw.println("Locate it, open it with a text editor, and find your");
        pw.println("way to happiness and inner peace.");
        pw.println("");
      }

      // pw.println("</pre>");
      pw.flush();
      if (_Debug) pwDebug.flush();

    } catch (FileNotFoundException fnfe) {
      System.out.println("OUCH! FileNotFoundException: " + fnfe.getMessage());
      fnfe.printStackTrace(System.out);
    } catch (MalformedURLException mue) {
      System.out.println("OUCH! MalformedURLException: " + mue.getMessage());
      mue.printStackTrace(System.out);
    } catch (IOException ioe) {
      System.out.println("OUCH! IOException: " + ioe.getMessage());
      ioe.printStackTrace(System.out);
    } catch (Throwable t) {
      System.out.println("OUCH! Throwable: " + t.getMessage());
      t.printStackTrace(System.out);
    }

    if (_Debug) System.out.println(" GetAsciiHandler done");
  }