docs: public static HsqlProperties parseURL(String url, boolean hasPrefix,
                                            boolean noPath) {
  
          String         urlImage   = url.toLowerCase(Locale.ENGLISH);
          HsqlProperties props      = new HsqlProperties();
          HsqlProperties extraProps = null;
          String         arguments  = null;
          int            pos        = 0;
  
          if (hasPrefix) {
              if (urlImage.startsWith(S_URL_PREFIX)) {
                  pos = S_URL_PREFIX.length();
              } else {
                  return props;
              }
          }
  
          String  type = null;
          int     port = 0;
          String  database;
          String  path;
          boolean isNetwork = false;
  
          props.setProperty("url", url);
  
          int postUrlPos = url.length();
  
          // postUrlPos is the END position in url String,
          // wrt what remains to be processed.
          // I.e., if postUrlPos is 100, url no longer needs to examined at
          // index 100 or later.
          int semiPos = url.indexOf(';', pos);
  
          if (semiPos > -1) {
              arguments  = urlImage.substring(semiPos + 1, urlImage.length());
              postUrlPos = semiPos;
              extraProps = HsqlProperties.delimitedArgPairsToProps(arguments,
                      "=", ";", null);
  
              /** @todo 1.9.0 - check if properties have valid names / values */
              props.addProperties(extraProps);
          }
  
          if (postUrlPos == pos + 1 && urlImage.startsWith(S_DOT, pos)) {
              type = S_DOT;
          } else if (urlImage.startsWith(S_MEM, pos)) {
              type = S_MEM;
          } else if (urlImage.startsWith(S_FILE, pos)) {
              type = S_FILE;
          } else if (urlImage.startsWith(S_RES, pos)) {
              type = S_RES;
          } else if (urlImage.startsWith(S_ALIAS, pos)) {
              type = S_ALIAS;
          } else if (urlImage.startsWith(S_HSQL, pos)) {
              type      = S_HSQL;
              port      = ServerConstants.SC_DEFAULT_HSQL_SERVER_PORT;
              isNetwork = true;
          } else if (urlImage.startsWith(S_HSQLS, pos)) {
              type      = S_HSQLS;
              port      = ServerConstants.SC_DEFAULT_HSQLS_SERVER_PORT;
              isNetwork = true;
          } else if (urlImage.startsWith(S_HTTP, pos)) {
              type      = S_HTTP;
              port      = ServerConstants.SC_DEFAULT_HTTP_SERVER_PORT;
              isNetwork = true;
          } else if (urlImage.startsWith(S_HTTPS, pos)) {
              type      = S_HTTPS;
              port      = ServerConstants.SC_DEFAULT_HTTPS_SERVER_PORT;
              isNetwork = true;
          }
  
          if (type == null) {
              type = S_FILE;
          } else if (type == S_DOT) {
              type = S_MEM;
  
              // keep pos
          } else {
              pos += type.length();
          }
  
          props.setProperty("connection_type", type);
  
          if (isNetwork) {
  
              // First capture 3 segments:  host + port + path
              String pathSeg  = null;
              String hostSeg  = null;
              String portSeg  = null;
              int    slashPos = url.indexOf('/', pos);
  
              if (slashPos > 0 && slashPos < postUrlPos) {
                  pathSeg = url.substring(slashPos, postUrlPos);
  
                  // N.b. pathSeg necessarily begins with /.
                  postUrlPos = slashPos;
              }
  
              // Assertion
              if (postUrlPos <= pos) {
                  return null;
              }
  
              // Processing different for ipv6 host address and all others:
              if (url.charAt(pos) == '[') {
  
                  // ipv6
                  int endIpv6 = url.indexOf(']', pos + 2);
  
                  // Notice 2 instead of 1 to require non-empty addr segment
                  if (endIpv6 < 0 || endIpv6 >= postUrlPos) {
                      return null;
  
                      // Wish could throw something with a useful message for user
                      // here.
                  }
  
                  hostSeg = urlImage.substring(pos + 1, endIpv6);
  
                  if (postUrlPos > endIpv6 + 1) {
                      portSeg = url.substring(endIpv6 + 1, postUrlPos);
                  }
              } else {
  
                  // non-ipv6
                  int colPos = url.indexOf(':', pos + 1);
  
                  // Notice + 1 to require non-empty addr segment
                  hostSeg = urlImage.substring(pos, (colPos > 0) ? colPos
                                                                 : postUrlPos);
  
                  if (colPos > -1 && postUrlPos > colPos + 1) {
  
                      // portSeg will be non-empty, but could contain just ":"
                      portSeg = url.substring(colPos, postUrlPos);
                  }
              }
  
              // At this point, the entire url has been parsed into
              // hostSeg + portSeg + pathSeg.
              if (portSeg != null) {
                  if (portSeg.length() < 2 || portSeg.charAt(0) != ':') {
  
                      // Wish could throw something with a useful message for user
                      // here.
                      return null;
                  }
  
                  try {
                      port = Integer.parseInt(portSeg.substring(1));
                  } catch (NumberFormatException e) {
  
                      // System.err.println("NFE for (" + portSeg + ')'); debug
                      return null;
                  }
              }
  
              if (noPath) {
                  path     = "";
                  database = pathSeg;
              } else if (pathSeg == null) {
                  path     = "/";
                  database = "";
              } else {
                  int lastSlashPos = pathSeg.lastIndexOf('/');
  
                  if (lastSlashPos < 1) {
                      path = "/";
                      database =
                          pathSeg.substring(1).toLowerCase(Locale.ENGLISH);
                  } else {
                      path     = pathSeg.substring(0, lastSlashPos);
                      database = pathSeg.substring(lastSlashPos + 1);
                  }
              }
  
              /* Just for debug.  Remove once stable:
              System.err.println("Host seg (" + hostSeg + "), Port val (" + port
                      + "), Path val (" + pathSeg + "), path (" + path
                      + "), db (" + database + ')');
               */
              props.setProperty("port", port);
              props.setProperty("host", hostSeg);
              props.setProperty("path", path);
  
              if (!noPath && extraProps != null) {
                  String filePath = extraProps.getProperty("filepath");
  
                  if (filePath != null && database.length() != 0) {
                      database += ";" + filePath;
                  }
              }
          } else {
              if (type == S_MEM || type == S_RES) {
                  database = urlImage.substring(pos, postUrlPos).toLowerCase();
  
                  if (type == S_RES) {
                      if (database.indexOf('/') != 0) {
                          database = '/' + database;
                      }
                  }
              } else {
                  database = url.substring(pos, postUrlPos);
              }
  
              if (database.length() == 0) {
                  return null;
              }
          }
  
          props.setProperty("database", database);
  
          return props;
      }