private Reader markableReader(Reader r, long l) throws SQLException {
    if (r.markSupported() && l < 0) {
      boolean marked = true;
      try {
        r.mark(1000000);
      } catch (IOException e) {
        marked = false;
      }
      if (marked) return r;
    }

    StringBuffer sb = new StringBuffer();
    int dim = l >= 0 ? (int) l : 4096;
    char[] cb = new char[dim];
    int rd;
    try {

      while ((rd = r.read(cb)) >= 0) {
        sb.append(Arrays.copyOf(cb, rd));
        if (l >= 0) break;
      }
      StringReader sr = new StringReader(sb.toString());
      sr.mark(1000000);
      return sr;
    } catch (IOException e) {
      throw new SQLException(e);
    }
  }
 /**
  * Marks the current position in this input stream. A subsequent call to the <code>reset</code>
  * method repositions this stream at the last marked position so that subsequent reads re-read the
  * same chars.
  *
  * <p>The <code>readlimit</code> argument tells this input stream to allow that many chars to be
  * read before the mark position gets invalidated.
  *
  * <p>The general contract of mark is that, if the method <code>markSupported</code> returns
  * <code>true</code>, the stream somehow remembers all the chars read after the call to mark and
  * stands ready to supply those same chars again if and whenever the method <code>reset</code> is
  * called. However, the stream is not required to remember any data at all if more than <code>
  * readlimit</code> chars are read from the stream before <code>reset</code> is called.
  *
  * @param readlimit The maximum limit of chars that can be read before the mark position becomes
  *     invalid.
  */
 public void mark(int readlimit) {
   try {
     in.mark(readlimit * 2);
   } catch (Exception e) {
     System.err.println(e);
   }
 }
    public byte[] decode(String code) {
      ByteArrayOutputStream baos = new ByteArrayOutputStream((code.length() * 3 / 4));

      StringReader sr;

      if (code.endsWith(Character.toString(padding))) {
        sr = new StringReader(code.substring(0, code.indexOf(padding)));
      } else {
        sr = new StringReader(code);
      }

      char[] c = new char[4];
      int[] b = new int[4];
      int len;
      try {
        int count = 0;
        while ((len = sr.read(c, 0, 4)) == 4) {
          b[0] = decode[c[0]];
          b[1] = decode[c[1]];
          b[2] = decode[c[2]];
          b[3] = decode[c[3]];

          baos.write(((b[0] & 0x3f) << 2) | ((b[1] & 0x30) >> 4));
          baos.write(((b[1] & 0x0f) << 4) | ((b[2] & 0x3c) >> 2));
          baos.write(((b[2] & 0x03) << 6) | (b[3] & 0x3f));

          count++;
          if (count == 19) {
            sr.mark(1);
            count = 0;

            if (sr.read() != 10) {
              sr.reset();
            }
          }
        }

        b[0] = decode[c[0]];
        b[1] = decode[c[1]];
        b[2] = decode[c[2]];
        b[3] = decode[c[3]];

        if (len == 2) {
          baos.write(((b[0] & 0x3f) << 2) | ((b[1] & 0x30) >> 4));
        } else if (len == 3) {
          baos.write(((b[0] & 0x3f) << 2) | ((b[1] & 0x30) >> 4));
          baos.write(((b[1] & 0x0f) << 4) | ((b[2] & 0x3c) >> 2));
        }

        return baos.toByteArray();
      } catch (java.io.IOException e) {
        return null;
      } catch (RuntimeException e) {
        return null;
      }
    }
  public static void main(String argv[]) throws Exception {

    StringReader in = new StringReader("aaaaaaaaaaaaaaa");
    try {
      in.mark(-1);
    } catch (IllegalArgumentException e) {
      return;
    }
    throw new Exception(" Negative marklimit value should throw an exception");
  }