Beispiel #1
0
  // Check if DatagramChannel.send while connected can include
  // address without throwing
  private static void test1() throws Exception {

    DatagramChannel sndChannel = DatagramChannel.open();
    sndChannel.socket().bind(null);
    InetSocketAddress sender =
        new InetSocketAddress(InetAddress.getLocalHost(), sndChannel.socket().getLocalPort());

    DatagramChannel rcvChannel = DatagramChannel.open();
    rcvChannel.socket().bind(null);
    InetSocketAddress receiver =
        new InetSocketAddress(InetAddress.getLocalHost(), rcvChannel.socket().getLocalPort());

    rcvChannel.connect(sender);
    sndChannel.connect(receiver);

    ByteBuffer bb = ByteBuffer.allocate(256);
    bb.put("hello".getBytes());
    bb.flip();
    int sent = sndChannel.send(bb, receiver);
    bb.clear();
    rcvChannel.receive(bb);
    bb.flip();
    CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
    if (!cb.toString().startsWith("h")) throw new RuntimeException("Test failed");

    rcvChannel.close();
    sndChannel.close();
  }
Beispiel #2
0
  // Check if the datagramsocket adaptor can send with a packet
  // that has not been initialized with an address; the legacy
  // datagram socket will send in this case
  private static void test2() throws Exception {
    DatagramChannel sndChannel = DatagramChannel.open();
    sndChannel.socket().bind(null);
    InetSocketAddress sender =
        new InetSocketAddress(InetAddress.getLocalHost(), sndChannel.socket().getLocalPort());

    DatagramChannel rcvChannel = DatagramChannel.open();
    rcvChannel.socket().bind(null);
    InetSocketAddress receiver =
        new InetSocketAddress(InetAddress.getLocalHost(), rcvChannel.socket().getLocalPort());

    rcvChannel.connect(sender);
    sndChannel.connect(receiver);

    byte b[] = "hello".getBytes("UTF-8");
    DatagramPacket pkt = new DatagramPacket(b, b.length);
    sndChannel.socket().send(pkt);

    ByteBuffer bb = ByteBuffer.allocate(256);
    rcvChannel.receive(bb);
    bb.flip();
    CharBuffer cb = Charset.forName("US-ASCII").newDecoder().decode(bb);
    if (!cb.toString().startsWith("h")) throw new RuntimeException("Test failed");

    // Check that the pkt got set with the target address;
    // This is legacy behavior
    if (!pkt.getSocketAddress().equals(receiver)) throw new RuntimeException("Test failed");

    rcvChannel.close();
    sndChannel.close();
  }
 public static void main(String[] arguments) {
   try {
     // read byte data into a byte buffer
     String data = "friends.dat";
     FileInputStream inData = new FileInputStream(data);
     FileChannel inChannel = inData.getChannel();
     long inSize = inChannel.size();
     ByteBuffer source = ByteBuffer.allocate((int) inSize);
     inChannel.read(source, 0);
     source.position(0);
     System.out.println("Original byte data:");
     for (int i = 0; source.remaining() > 0; i++) {
       System.out.print(source.get() + " ");
     }
     // convert byte data into character data
     source.position(0);
     Charset ascii = Charset.forName("US-ASCII");
     CharsetDecoder toAscii = ascii.newDecoder();
     CharBuffer destination = toAscii.decode(source);
     destination.position(0);
     System.out.println("\n\nNew character data:");
     for (int i = 0; destination.remaining() > 0; i++) {
       System.out.print(destination.get());
     }
     System.out.println();
   } catch (FileNotFoundException fne) {
     System.out.println(fne.getMessage());
   } catch (IOException ioe) {
     System.out.println(ioe.getMessage());
   }
 }
Beispiel #4
0
 static boolean check(CharsetDecoder dec, byte[] bytes, boolean direct, int[] flow) {
   int inPos = flow[0];
   int inLen = flow[1];
   int outPos = flow[2];
   int outLen = flow[3];
   int expedInPos = flow[4];
   int expedOutPos = flow[5];
   CoderResult expedCR = (flow[6] == 0) ? CoderResult.UNDERFLOW : CoderResult.OVERFLOW;
   ByteBuffer bbf;
   CharBuffer cbf;
   if (direct) {
     bbf = ByteBuffer.allocateDirect(inPos + bytes.length);
     cbf = ByteBuffer.allocateDirect((outPos + outLen) * 2).asCharBuffer();
   } else {
     bbf = ByteBuffer.allocate(inPos + bytes.length);
     cbf = CharBuffer.allocate(outPos + outLen);
   }
   bbf.position(inPos);
   bbf.put(bytes).flip().position(inPos).limit(inPos + inLen);
   cbf.position(outPos);
   dec.reset();
   CoderResult cr = dec.decode(bbf, cbf, false);
   if (cr != expedCR || bbf.position() != expedInPos || cbf.position() != expedOutPos) {
     System.out.printf("Expected(direct=%5b): [", direct);
     for (int i : flow) System.out.print(" " + i);
     System.out.println(
         "]  CR=" + cr + ", inPos=" + bbf.position() + ", outPos=" + cbf.position());
     return false;
   }
   return true;
 }
Beispiel #5
0
 static byte[] encode(char[] cc, Charset cs, boolean testDirect, Time t) throws Exception {
   ByteBuffer bbf;
   CharBuffer cbf;
   CharsetEncoder enc = cs.newEncoder();
   String csn = cs.name();
   if (testDirect) {
     bbf = ByteBuffer.allocateDirect(cc.length * 4);
     cbf = ByteBuffer.allocateDirect(cc.length * 2).asCharBuffer();
     cbf.put(cc).flip();
   } else {
     bbf = ByteBuffer.allocate(cc.length * 4);
     cbf = CharBuffer.wrap(cc);
   }
   CoderResult cr = null;
   long t1 = System.nanoTime() / 1000;
   for (int i = 0; i < iteration; i++) {
     cbf.rewind();
     bbf.clear();
     enc.reset();
     cr = enc.encode(cbf, bbf, true);
   }
   long t2 = System.nanoTime() / 1000;
   t.t = (t2 - t1) / iteration;
   if (cr != CoderResult.UNDERFLOW) {
     System.out.println("ENC-----------------");
     int pos = cbf.position();
     System.out.printf("  cr=%s, cbf.pos=%d, cc[pos]=%x%n", cr.toString(), pos, cc[pos] & 0xffff);
     throw new RuntimeException("Encoding err: " + csn);
   }
   byte[] bb = new byte[bbf.position()];
   bbf.flip();
   bbf.get(bb);
   return bb;
 }
  protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
    int mark = src.position();

    if (needsMark) {
      if (dst.remaining() < 2) return CoderResult.OVERFLOW;
      put(BYTE_ORDER_MARK, dst);
      needsMark = false;
    }

    try {
      while (src.hasRemaining()) {
        char c = src.get();
        if (!Surrogate.is(c)) {
          if (dst.remaining() < 2) return CoderResult.OVERFLOW;
          mark++;
          put(c, dst);
          continue;
        }
        int d = sgp.parse(c, src);
        if (d < 0) return sgp.error();
        if (dst.remaining() < 4) return CoderResult.OVERFLOW;
        mark += 2;
        put(Surrogate.high(d), dst);
        put(Surrogate.low(d), dst);
      }
      return CoderResult.UNDERFLOW;
    } finally {
      src.position(mark);
    }
  }
  /**
   * Creates a string in a specfied character set.
   *
   * @param value String constant, must not be null
   * @param charsetName Name of the character set, may be null
   * @param collation Collation, may be null
   * @throws IllegalCharsetNameException If the given charset name is illegal
   * @throws UnsupportedCharsetException If no support for the named charset is available in this
   *     instance of the Java virtual machine
   * @throws RuntimeException If the given value cannot be represented in the given charset
   */
  public NlsString(String value, String charsetName, SqlCollation collation) {
    assert value != null;
    if (null != charsetName) {
      charsetName = charsetName.toUpperCase();
      this.charsetName = charsetName;
      String javaCharsetName = SqlUtil.translateCharacterSetName(charsetName);
      if (javaCharsetName == null) {
        throw new UnsupportedCharsetException(charsetName);
      }
      this.charset = Charset.forName(javaCharsetName);
      CharsetEncoder encoder = charset.newEncoder();

      // dry run to see if encoding hits any problems
      try {
        encoder.encode(CharBuffer.wrap(value));
      } catch (CharacterCodingException ex) {
        throw RESOURCE.charsetEncoding(value, javaCharsetName).ex();
      }
    } else {
      this.charsetName = null;
      this.charset = null;
    }
    this.collation = collation;
    this.value = value;
  }
Beispiel #8
0
 public static void main(String args[]) throws Exception {
   String s = "abc\uD800\uDC00qrst"; // Valid surrogate
   char[] c = s.toCharArray();
   CharsetEncoder enc =
       Charset.forName("ISO8859_1").newEncoder().onUnmappableCharacter(CodingErrorAction.REPLACE);
   /* Process the first 4 characters, including the high surrogate
   which should be stored */
   ByteBuffer bb = ByteBuffer.allocate(10);
   CharBuffer cb = CharBuffer.wrap(c);
   cb.limit(4);
   enc.encode(cb, bb, false);
   cb.limit(7);
   enc.encode(cb, bb, true);
   byte[] first = bb.array();
   for (int i = 0; i < 7; i++)
     System.err.printf("[%d]=%d was %d\n", i, (int) first[i] & 0xffff, (int) c[i] & 0xffff);
 }
 public static void main(String[] args) throws Exception {
   // 创建简体中文对应的Charset
   Charset cn = Charset.forName("GBK");
   // 获取cn对象对应的编码器和解码器
   CharsetEncoder cnEncoder = cn.newEncoder();
   CharsetDecoder cnDecoder = cn.newDecoder();
   // 创建一个CharBuffer对象
   CharBuffer cbuff = CharBuffer.allocate(8);
   cbuff.put('孙');
   cbuff.put('悟');
   cbuff.put('空');
   cbuff.flip();
   // 将CharBuffer中的字符序列转换成字节序列
   ByteBuffer bbuff = cnEncoder.encode(cbuff);
   // 循环访问ByteBuffer中的每个字节
   for (int i = 0; i < bbuff.capacity(); i++) {
     System.out.print(bbuff.get(i) + " ");
   }
   // 将ByteBuffer的数据解码成字符序列
   System.out.println("\n" + cnDecoder.decode(bbuff));
 }
Beispiel #10
0
 static CoderResult decodeCR(byte[] bb, Charset cs, boolean testDirect) throws Exception {
   CharsetDecoder dec = cs.newDecoder();
   ByteBuffer bbf;
   CharBuffer cbf;
   if (testDirect) {
     bbf = ByteBuffer.allocateDirect(bb.length);
     cbf = ByteBuffer.allocateDirect(bb.length * 2).asCharBuffer();
     bbf.put(bb).flip();
   } else {
     bbf = ByteBuffer.wrap(bb);
     cbf = CharBuffer.allocate(bb.length);
   }
   CoderResult cr = null;
   for (int i = 0; i < iteration; i++) {
     bbf.rewind();
     cbf.clear();
     dec.reset();
     cr = dec.decode(bbf, cbf, true);
   }
   return cr;
 }
Beispiel #11
0
 static CoderResult encodeCR(char[] cc, Charset cs, boolean testDirect) throws Exception {
   ByteBuffer bbf;
   CharBuffer cbf;
   CharsetEncoder enc = cs.newEncoder();
   if (testDirect) {
     bbf = ByteBuffer.allocateDirect(cc.length * 4);
     cbf = ByteBuffer.allocateDirect(cc.length * 2).asCharBuffer();
     cbf.put(cc).flip();
   } else {
     bbf = ByteBuffer.allocate(cc.length * 4);
     cbf = CharBuffer.wrap(cc);
   }
   CoderResult cr = null;
   for (int i = 0; i < iteration; i++) {
     cbf.rewind();
     bbf.clear();
     enc.reset();
     cr = enc.encode(cbf, bbf, true);
   }
   return cr;
 }
Beispiel #12
0
 @Override
 int read(final TextInput ti) throws IOException {
   int c = -1;
   while (++c < 4) {
     final int ch = ti.readByte();
     if (ch < 0) break;
     cache[c] = (byte) ch;
     outc.position(0);
     inc.position(0);
     inc.limit(c + 1);
     csd.reset();
     final CoderResult cr = csd.decode(inc, outc, true);
     if (cr.isMalformed()) continue;
     // return character
     int i = 0;
     final int os = outc.position();
     for (int o = 0; o < os; ++o) i |= outc.get(o) << (o << 3);
     return i;
   }
   return c == 0 ? -1 : invalid();
 }
  /**
   * Writes any remaining output to the output buffer and resets the converter to its initial state.
   *
   * @param output char array to receive flushed output.
   * @param outStart start writing to output array at this offset.
   * @param outEnd stop writing to output array at this offset (exclusive).
   * @exception MalformedInputException if the output to be flushed contained a partial or invalid
   *     multibyte character sequence. flush will write what it can to the output buffer and reset
   *     the converter before throwing this exception. An additional call to flush is not required.
   * @exception ConversionBufferFullException if output array is filled before all the output can be
   *     flushed. flush will write what it can to the output buffer and remember its state. An
   *     additional call to flush with a new output buffer will conclude the operation.
   */
  public int flush(char[] output, int outStart, int outEnd)
      throws MalformedInputException, ConversionBufferFullException {

    byteOff = charOff = 0;
    if (outStart >= outEnd || outStart >= output.length) throw new ConversionBufferFullException();
    if (dst != null && dst.array() == output) dst.position(outStart).limit(outEnd);
    else dst = CharBuffer.wrap(output, outStart, outEnd - outStart);

    CoderResult cr = null;
    try {
      if (src != null) cr = decoder.decode((ByteBuffer) src.clear(), dst, true);
      assert !cr.isUnmappable();
      if (cr.isMalformed()) {
        badInputLength = cr.length();
        reset();
        throw new MalformedInputException();
      }
    } catch (IllegalStateException ise) {
      if (src != null) cr = decoder.reset().decode(src, dst, true);
    }
    try {
      cr = decoder.flush(dst);
    } catch (Exception e) {
      assert false;
    } finally {
      byteOff = 0;
      charOff = dst.position();
      src = null;
    }
    if (cr.isOverflow()) throw new ConversionBufferFullException();

    // Return the length written to the output buffer
    if (cr.isUnderflow()) {
      int written = charOff - outStart;
      reset();
      return written;
    }
    assert false;
    return -1; // should be never reached
  }
  /**
   * Converts an array of bytes containing characters in an external encoding into an array of
   * Unicode characters. This method allows a buffer by buffer conversion of a data stream. The
   * state of the conversion is saved between calls to convert. Among other things, this means
   * multibyte input sequences can be split between calls. If a call to convert results in an
   * exception, the conversion may be continued by calling convert again with suitably modified
   * parameters. All conversions should be finished with a call to the flush method.
   *
   * @return the number of bytes written to output.
   * @param input byte array containing text to be converted.
   * @param inStart begin conversion at this offset in input array.
   * @param inEnd stop conversion at this offset in input array (exclusive).
   * @param output character array to receive conversion result.
   * @param outStart start writing to output array at this offset.
   * @param outEnd stop writing to output array at this offset (exclusive).
   * @exception MalformedInputException if the input buffer contains any sequence of bytes that is
   *     illegal for the input character set.
   * @exception UnknownCharacterException for any character that that cannot be converted to
   *     Unicode. Thrown only when converter is not in substitution mode.
   * @exception ConversionBufferFullException if output array is filled prior to converting all the
   *     input.
   */
  public int convert(byte[] input, int inStart, int inEnd, char[] output, int outStart, int outEnd)
      throws UnknownCharacterException, MalformedInputException, ConversionBufferFullException {

    byteOff = inStart;
    charOff = outStart;
    // throw exceptions compatible to legacy ByteToCharXxx converters
    if (inStart >= inEnd) return 0;
    if (inStart >= input.length) throw new ArrayIndexOutOfBoundsException(inStart);
    if (outStart >= outEnd || outStart >= output.length) throw new ConversionBufferFullException();

    if (src != null && src.array() == input) src.position(inStart).limit(inEnd);
    else src = ByteBuffer.wrap(input, inStart, inEnd - inStart);
    if (dst != null && dst.array() == output) dst.position(outStart).limit(outEnd);
    else dst = CharBuffer.wrap(output, outStart, outEnd - outStart);

    CoderResult cr;
    try {
      cr = decoder.decode(src, dst, false);
    } catch (IllegalStateException ise) {
      cr = decoder.reset().decode(src, dst, false);
    } finally {
      byteOff = src.position();
      charOff = dst.position();
    }
    if (cr.isUnmappable()) {
      badInputLength = cr.length();
      throw new UnknownCharacterException();
    }
    if (cr.isMalformed()) {
      badInputLength = cr.length();
      throw new MalformedInputException();
    }
    if (cr.isOverflow()) throw new ConversionBufferFullException();

    // Return the length written to the output buffer
    if (cr.isUnderflow()) return charOff - outStart;
    return -1; // should be never reached
  }
  /**
   * Check if the first X characters of a byte stream match a String.
   *
   * @param data The byte array to process
   * @param pattern The String to match
   * @return True if the pattern was found, false otherwise
   */
  private static boolean bytesEqualsString(byte[] data, String pattern) {
    byte[] bytes = new byte[pattern.length()];
    Charset csets = Charset.forName("US-ASCII");
    boolean fin = false;
    int currChar = 0;

    // remove any CR and/or LF characters at the beginning of the article
    // data
    while (!fin) {
      if (currChar >= data.length) break;

      byte in = data[currChar];
      ByteBuffer bb = ByteBuffer.wrap(new byte[] {(byte) in});
      CharBuffer cb = csets.decode(bb);
      char c = cb.charAt(0);

      if (data.length > 0 && (c == '\n' || c == '\r')) currChar++;
      else fin = true;

      if (data.length == 0) fin = true;
    }

    // extract bytes (chars) to check from article data
    for (int i = 0; i < bytes.length && i < data.length; i++, currChar++) {
      byte in = data[currChar];
      bytes[i] = (byte) in;
    }

    // decode byte data to characters
    ByteBuffer bb = ByteBuffer.wrap(bytes);
    CharBuffer cb = csets.decode(bb);

    // compare these characters to the pattern String
    for (int i = 0; i < pattern.length(); i++) if (cb.charAt(i) != pattern.charAt(i)) return false;

    return true;
  }
  static void testMixed(Charset cs) throws Throwable {
    CharsetDecoder dec =
        cs.newDecoder()
            .onMalformedInput(CodingErrorAction.REPLACE)
            .onUnmappableCharacter(CodingErrorAction.REPLACE);
    CharsetEncoder enc =
        cs.newEncoder()
            .onMalformedInput(CodingErrorAction.REPLACE)
            .onUnmappableCharacter(CodingErrorAction.REPLACE);
    List<Integer> cps = new ArrayList<>(0x10000);
    int off = 0;
    int cp = 0;
    while (cp < 0x10000) {
      if (enc.canEncode((char) cp)) {
        cps.add(cp);
      }
      cp++;
    }
    Collections.shuffle(cps);
    char[] bmpCA = new char[cps.size()];
    for (int i = 0; i < cps.size(); i++) bmpCA[i] = (char) (int) cps.get(i);
    String bmpStr = new String(bmpCA);
    // getBytes(csn);
    byte[] bmpBA = bmpStr.getBytes(cs.name());
    ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA));
    byte[] baNIO = new byte[bf.limit()];
    bf.get(baNIO, 0, baNIO.length);
    if (!Arrays.equals(bmpBA, baNIO)) {
      throw new RuntimeException("getBytes(csn) failed  -> " + cs.name());
    }

    // getBytes(cs);
    bmpBA = bmpStr.getBytes(cs);
    if (!Arrays.equals(bmpBA, baNIO))
      throw new RuntimeException("getBytes(cs) failed  -> " + cs.name());

    // new String(csn);
    String strSC = new String(bmpBA, cs.name());
    String strNIO = dec.reset().decode(ByteBuffer.wrap(bmpBA)).toString();
    if (!strNIO.equals(strSC)) {
      throw new RuntimeException("new String(csn) failed  -> " + cs.name());
    }

    // new String(cs);
    strSC = new String(bmpBA, cs);
    if (!strNIO.equals(strSC)) throw new RuntimeException("new String(cs) failed  -> " + cs.name());
  }
Beispiel #17
0
  /** Generic Decoder. */
  private static final class Generic extends TextDecoder {
    /** Input cache. */
    private final byte[] cache = new byte[4];
    /** Input buffer. */
    private final ByteBuffer inc = ByteBuffer.wrap(cache);
    /** Output buffer. */
    private final CharBuffer outc = CharBuffer.wrap(new char[4]);
    /** Charset decoder. */
    private final CharsetDecoder csd;

    /**
     * Constructor.
     *
     * @param enc encoding
     * @throws IOException I/O exception
     */
    private Generic(final String enc) throws IOException {
      try {
        csd = Charset.forName(enc).newDecoder();
      } catch (final Exception ex) {
        throw new EncodingException(ex);
      }
    }

    @Override
    int read(final TextInput ti) throws IOException {
      int c = -1;
      while (++c < 4) {
        final int ch = ti.readByte();
        if (ch < 0) break;
        cache[c] = (byte) ch;
        outc.position(0);
        inc.position(0);
        inc.limit(c + 1);
        csd.reset();
        final CoderResult cr = csd.decode(inc, outc, true);
        if (cr.isMalformed()) continue;
        // return character
        int i = 0;
        final int os = outc.position();
        for (int o = 0; o < os; ++o) i |= outc.get(o) << (o << 3);
        return i;
      }
      return c == 0 ? -1 : invalid();
    }
  }
Beispiel #18
0
 static char[] decode(byte[] bb, Charset cs, boolean testDirect, Time t) throws Exception {
   String csn = cs.name();
   CharsetDecoder dec = cs.newDecoder();
   ByteBuffer bbf;
   CharBuffer cbf;
   if (testDirect) {
     bbf = ByteBuffer.allocateDirect(bb.length);
     cbf = ByteBuffer.allocateDirect(bb.length * 2).asCharBuffer();
     bbf.put(bb);
   } else {
     bbf = ByteBuffer.wrap(bb);
     cbf = CharBuffer.allocate(bb.length);
   }
   CoderResult cr = null;
   long t1 = System.nanoTime() / 1000;
   for (int i = 0; i < iteration; i++) {
     bbf.rewind();
     cbf.clear();
     dec.reset();
     cr = dec.decode(bbf, cbf, true);
   }
   long t2 = System.nanoTime() / 1000;
   t.t = (t2 - t1) / iteration;
   if (cr != CoderResult.UNDERFLOW) {
     System.out.println("DEC-----------------");
     int pos = bbf.position();
     System.out.printf(
         "  cr=%s, bbf.pos=%d, bb[pos]=%x,%x,%x,%x%n",
         cr.toString(),
         pos,
         bb[pos++] & 0xff,
         bb[pos++] & 0xff,
         bb[pos++] & 0xff,
         bb[pos++] & 0xff);
     throw new RuntimeException("Decoding err: " + csn);
   }
   char[] cc = new char[cbf.position()];
   cbf.flip();
   cbf.get(cc);
   return cc;
 }
/**
 * Serializes a <code>DBObject</code> into a string that can be sent to the database.
 *
 * <p>There is a pool of available encoders. Create a new one as follows:
 *
 * <blockquote>
 *
 * </pre>
 *
 * ByteEncoder encoder = ByteEncoder.get(); // try forever until an encoder is available </pre>
 *
 * </blockquote>
 *
 * <p>Each key/value pair in the <code>DBObject</code> is encoded in the following format:
 *
 * <blockquote>
 *
 * <i>&lt;type (</i><code>byte</code><i>)&gt;&lt;name (</i><code>String</code></i>)&gt;&lt;0 (</i>
 * <code>byte</code><i>)&gt;&lt;data (serialized data)&gt;</i>
 *
 * </blockquote>
 *
 * For example:
 *
 * <blockquote>
 *
 * &lt;<code>NUMBER</code>&gt;&lt;name&gt;0&lt;double&gt; <code>// NUMBER = 1</code><br>
 * &lt;<code>STRING</code>&gt;&lt;name&gt;0&lt;len&gt;&lt;string&gt;0 <code>// STRING = 2</code>
 *
 * </blockquote>
 */
public class ByteEncoder extends Bytes {

  static final boolean DEBUG = Boolean.getBoolean("DEBUG.BE");

  // things that won't get sent in the scope
  static final Set<String> BAD_GLOBALS = new HashSet<String>();

  static {
    BAD_GLOBALS.add("db");
    BAD_GLOBALS.add("local");
    BAD_GLOBALS.add("core");
    BAD_GLOBALS.add("args"); // TODO: should we get rid of this
    BAD_GLOBALS.add("obj"); // TODO: get rid of this
  }

  /**
   * Whether a given field is generated by the db for use by the db
   *
   * @param o an object to check
   * @return whether the object is a db field
   */
  public static boolean dbOnlyField(Object o) {
    if (o == null) return false;

    if (o instanceof String) return dbOnlyField(o.toString());

    return false;
  }

  /**
   * Whether a given field is generated by the db for use by the db
   *
   * @param s a string to check
   * @return whether the string is a db field
   */
  public static boolean dbOnlyField(String s) {
    return s.equals("_ns") || s.equals("_save") || s.equals("_update");
  }

  /**
   * Fetches a new <code>ByteEncoder</code> from the pool of available <code>ByteEncoder</code>s.
   *
   * @return a new <code>ByteEncoder</code>
   */
  public static ByteEncoder get() {
    return _pool.get();
  }

  /**
   * Get the current position of this ByteEncoder
   *
   * @return
   */
  public long getPosition() {
    return _buf.position();
  }

  /**
   * Get the remaining capacity of this ByteEncoder
   *
   * @return
   */
  public long getRemaining() {
    return _buf.remaining();
  }

  /** Resets and returns this encoder to the pool. */
  protected void done() {
    reset();
    _pool.done(this);
  }

  static final SimplePool<ByteEncoder> _pool =
      new SimplePool<ByteEncoder>("ByteEncoders", NUM_ENCODERS, NUM_ENCODERS * 2) {
        protected ByteEncoder createNew() {
          if (D) System.out.println("creating new ByteEncoder");
          return new ByteEncoder();
        }

        protected long memSize(ByteEncoder d) {
          return d._buf.capacity() + (2 * MAX_STRING) + 1024;
        }
      };

  // ----

  private ByteEncoder() {
    _buf = ByteBuffer.allocateDirect(MAX_OBJECT_SIZE + 2048);
    _buf.order(Bytes.ORDER);
  }

  /**
   * Returns the bytes in the bytebuffer. Attempts to leave the bytebuffer in the same state. Note
   * that mark, if set, is lost.
   *
   * @return array of bytes
   */
  public byte[] getBytes() {

    int pos = _buf.position();
    int limit = _buf.limit();

    flip();

    byte[] arr = new byte[_buf.limit()];

    _buf.get(arr);

    flip();

    _buf.position(pos);
    _buf.limit(limit);

    return arr;
  }

  /** Returns encoder to its starting state, ready to encode an object. */
  protected void reset() {
    _buf.position(0);
    _buf.limit(_buf.capacity());
    _flipped = false;
    _dontRef.clear();
  }

  /** Switches the encoder from being write-only to being read-only. */
  protected void flip() {
    _buf.flip();
    _flipped = true;
  }

  /**
   * Encodes a <code>DBObject</code>. This is for the higher level api calls
   *
   * <p>If encoding an object fails, the buffer will be reset to the position prior to this put call
   * and a BufferOverflowException will be thrown
   *
   * @param o the object to encode
   * @return the number of characters in the encoding
   */
  public int putObject(DBObject o) {

    _buf.mark();

    try {
      return putObject(null, o);
    } catch (BufferOverflowException bof) {
      // reset to marked offset and wipe any written data
      _buf.reset();
      _buf.put(new byte[_buf.remaining()]);
      _buf.reset();

      throw new BufferOverflowException();
    }
  }

  /** this is really for embedded objects */
  private int putObject(String name, DBObject o) {
    if (o == null) throw new NullPointerException("can't save a null object");

    if (DEBUG)
      System.out.println(
          "putObject : " + name + " [" + o.getClass() + "]" + " # keys " + o.keySet().size());

    if (_flipped) throw new IllegalStateException("already flipped");
    final int start = _buf.position();

    byte myType = OBJECT;
    if (o instanceof List) myType = ARRAY;

    if (_handleSpecialObjects(name, o)) return _buf.position() - start;

    if (name != null) {
      _put(myType, name);
    }

    final int sizePos = _buf.position();
    _buf.putInt(0); // leaving space for this.  set it at the end

    List transientFields = null;

    if (myType == OBJECT) {
      if (o.containsField("_id")) _putObjectField("_id", o.get("_id"));

      {
        Object temp = o.get("_transientFields");
        if (temp instanceof List) transientFields = (List) temp;
      }
    }

    for (String s : o.keySet()) {

      if (s.equals("_id")) continue;

      if (transientFields != null && transientFields.contains(s)) continue;

      Object val = o.get(s);

      _putObjectField(s, val);
    }
    _buf.put(EOO);

    _buf.putInt(sizePos, _buf.position() - sizePos);
    return _buf.position() - start;
  }

  private void _putObjectField(String name, Object val) {

    if (dbOnlyField(name) || name.equals("_transientFields")) return;

    if (DEBUG) System.out.println("\t put thing : " + name);

    if (name.equals("$where") && val instanceof String) {
      _put(CODE, name);
      _putValueString(val.toString());
      return;
    }

    val = Bytes.applyEncodingHooks(val);

    if (val == null) putNull(name);
    else if (val instanceof Date) putDate(name, (Date) val);
    else if (val instanceof Number) putNumber(name, (Number) val);
    else if (val instanceof String) putString(name, val.toString());
    else if (val instanceof ObjectId) putObjectId(name, (ObjectId) val);
    else if (val instanceof DBObject) putObject(name, (DBObject) val);
    else if (val instanceof Boolean) putBoolean(name, (Boolean) val);
    else if (val instanceof Pattern) putPattern(name, (Pattern) val);
    else if (val instanceof DBRegex) {
      putDBRegex(name, (DBRegex) val);
    } else if (val instanceof Map) putMap(name, (Map) val);
    else if (val instanceof List) putList(name, (List) val);
    else if (val instanceof byte[]) putBinary(name, (byte[]) val);
    else if (val instanceof DBBinary) putBinary(name, (DBBinary) val);
    else if (val.getClass().isArray()) putList(name, Arrays.asList((Object[]) val));
    else if (val instanceof DBPointer) {

      // temporary - there's the notion of "special object" , but for simple level 0...
      DBPointer r = (DBPointer) val;
      putDBPointer(name, r._ns, (ObjectId) r._id);
    } else if (val instanceof DBRefBase) {
      putDBRef(name, (DBRefBase) val);
    } else if (val instanceof DBSymbol) {
      putSymbol(name, (DBSymbol) val);
    } else if (val instanceof DBUndefined) {
      putUndefined(name);
    } else if (val instanceof DBTimestamp) {
      putTimestamp(name, (DBTimestamp) val);
    } else throw new IllegalArgumentException("can't serialize " + val.getClass());
  }

  private void putList(String name, List l) {
    _put(ARRAY, name);
    final int sizePos = _buf.position();
    _buf.putInt(0);

    for (int i = 0; i < l.size(); i++) _putObjectField(String.valueOf(i), l.get(i));

    _buf.put(EOO);
    _buf.putInt(sizePos, _buf.position() - sizePos);
  }

  private void putMap(String name, Map m) {
    _put(OBJECT, name);
    final int sizePos = _buf.position();
    _buf.putInt(0);

    for (Object key : m.keySet()) _putObjectField(key.toString(), m.get(key));

    _buf.put(EOO);
    _buf.putInt(sizePos, _buf.position() - sizePos);
  }

  private boolean _handleSpecialObjects(String name, DBObject o) {

    if (o == null) return false;

    if (o instanceof DBCollection) {
      DBCollection c = (DBCollection) o;
      putDBPointer(name, c.getName(), Bytes.COLLECTION_REF_ID);
      return true;
    }

    if (!_dontRefContains(o) && name != null && o instanceof DBPointer) {
      DBPointer r = (DBPointer) o;
      putDBPointer(name, r._ns, (ObjectId) r._id);
      return true;
    }

    if (!(o instanceof List) && o.get(Bytes.NO_REF_HACK) != null) {
      o.removeField(Bytes.NO_REF_HACK);
      return false;
    }

    if (!_dontRefContains(o) && name != null && !(o instanceof List) && cameFromDB(o)) {
      putDBPointer(name, o.get("_ns").toString(), (ObjectId) (o.get("_id")));
      return true;
    }

    return false;
  }

  protected int putNull(String name) {
    int start = _buf.position();
    _put(NULL, name);
    return _buf.position() - start;
  }

  protected int putUndefined(String name) {
    int start = _buf.position();
    _put(UNDEFINED, name);
    return _buf.position() - start;
  }

  protected int putTimestamp(String name, DBTimestamp ts) {
    int start = _buf.position();
    _put(TIMESTAMP, name);
    _buf.putInt(ts.getTime());
    _buf.putInt(ts.getInc());
    return _buf.position() - start;
  }

  protected int putBoolean(String name, Boolean b) {
    int start = _buf.position();
    _put(BOOLEAN, name);
    _buf.put(b ? (byte) 0x1 : (byte) 0x0);
    return _buf.position() - start;
  }

  protected int putDate(String name, Date d) {
    int start = _buf.position();
    _put(DATE, name);
    _buf.putLong(d.getTime());
    return _buf.position() - start;
  }

  protected int putNumber(String name, Number n) {
    int start = _buf.position();
    if (n instanceof Integer) {
      _put(NUMBER_INT, name);
      _buf.putInt(n.intValue());
    } else if (n instanceof Long) {
      _put(NUMBER_LONG, name);
      _buf.putLong(n.longValue());
    } else {
      _put(NUMBER, name);
      _buf.putDouble(n.doubleValue());
    }
    return _buf.position() - start;
  }

  protected void putBinary(String name, byte[] data) {

    _put(BINARY, name);
    _buf.putInt(4 + data.length);

    _buf.put(B_BINARY);
    _buf.putInt(data.length);
    int before = _buf.position();
    _buf.put(data);
    int after = _buf.position();

    com.mongodb.util.MyAsserts.assertEquals(after - before, data.length);
  }

  protected void putBinary(String name, DBBinary val) {
    _put(BINARY, name);
    _buf.putInt(val._data.length);
    _buf.put(val._type);
    _buf.put(val._data);
  }

  protected int putSymbol(String name, DBSymbol s) {
    return _putString(name, s.getSymbol(), SYMBOL);
  }

  protected int putString(String name, String s) {
    return _putString(name, s, STRING);
  }

  private int _putString(String name, String s, byte type) {
    int start = _buf.position();
    _put(type, name);
    _putValueString(s);
    return _buf.position() - start;
  }

  protected int putObjectId(String name, ObjectId oid) {
    int start = _buf.position();
    _put(OID, name);
    _buf.putInt(oid._time);
    _buf.putInt(oid._machine);
    _buf.putInt(oid._inc);
    return _buf.position() - start;
  }

  protected int putDBPointer(String name, String ns, ObjectId oid) {
    int start = _buf.position();
    _put(REF, name);

    _putValueString(ns);
    _buf.putInt(oid._time);
    _buf.putInt(oid._machine);
    _buf.putInt(oid._inc);

    return _buf.position() - start;
  }

  protected void putDBRef(String name, DBRefBase ref) {
    _put(OBJECT, name);
    final int sizePos = _buf.position();
    _buf.putInt(0);

    _putObjectField("$ref", ref.getRef());
    _putObjectField("$id", ref.getId());

    _buf.put(EOO);
    _buf.putInt(sizePos, _buf.position() - sizePos);
  }

  private int putDBRegex(String name, DBRegex regex) {

    int start = _buf.position();
    _put(REGEX, name);
    _put(regex.getPattern());

    String options = regex.getOptions();

    TreeMap<Character, Character> sm = new TreeMap<Character, Character>();

    for (int i = 0; i < options.length(); i++) {
      sm.put(options.charAt(i), options.charAt(i));
    }

    StringBuffer sb = new StringBuffer();

    for (char c : sm.keySet()) {
      sb.append(c);
    }

    _put(sb.toString());
    return _buf.position() - start;
  }

  private int putPattern(String name, Pattern p) {
    int start = _buf.position();
    _put(REGEX, name);
    _put(p.pattern());
    _put(patternFlags(p.flags()));
    return _buf.position() - start;
  }

  // ----------------------------------------------

  /** Encodes the type and key. */
  private void _put(byte type, String name) {
    _buf.put(type);
    _put(name);
  }

  void _putValueString(String s) {
    int lenPos = _buf.position();
    _buf.putInt(0); // making space for size
    int strLen = _put(s);
    _buf.putInt(lenPos, strLen);
  }

  int _put(String name) {

    _cbuf.position(0);
    _cbuf.limit(_cbuf.capacity());
    _cbuf.append(name);

    _cbuf.flip();
    final int start = _buf.position();
    _encoder.encode(_cbuf, _buf, false);

    _buf.put((byte) 0);

    return _buf.position() - start;
  }

  boolean _dontRefContains(Object o) {
    if (_dontRef.size() == 0) return false;
    return _dontRef.peek().contains(o);
  }

  private final CharBuffer _cbuf = CharBuffer.allocate(MAX_STRING);
  private final CharsetEncoder _encoder = _utf8.newEncoder();
  private Stack<IdentitySet> _dontRef = new Stack<IdentitySet>();

  private boolean _flipped = false;
  final ByteBuffer _buf;
}
Beispiel #20
0
 // we assume out is large enough for this conversion
 // returns number of filled chars in out buffer
 public int convert(byte[] in, int inOffset, int inLength, char[] out) {
   final ByteBuffer inBuffer = ByteBuffer.wrap(in, inOffset, inLength);
   final CharBuffer outBuffer = CharBuffer.wrap(out, 0, out.length);
   myDecoder.decode(inBuffer, outBuffer, false);
   return outBuffer.position();
 }
  static void test(Charset cs, char[] bmpCA, byte[] sbBA) throws Throwable {
    String bmpStr = new String(bmpCA);
    CharsetDecoder dec =
        cs.newDecoder()
            .onMalformedInput(CodingErrorAction.REPLACE)
            .onUnmappableCharacter(CodingErrorAction.REPLACE);
    CharsetEncoder enc =
        cs.newEncoder()
            .onMalformedInput(CodingErrorAction.REPLACE)
            .onUnmappableCharacter(CodingErrorAction.REPLACE);

    // getBytes(csn);
    byte[] baSC = bmpStr.getBytes(cs.name());
    ByteBuffer bf = enc.reset().encode(CharBuffer.wrap(bmpCA));
    byte[] baNIO = new byte[bf.limit()];
    bf.get(baNIO, 0, baNIO.length);
    if (!Arrays.equals(baSC, baNIO))
      throw new RuntimeException("getBytes(csn) failed  -> " + cs.name());

    // getBytes(cs);
    baSC = bmpStr.getBytes(cs);
    if (!Arrays.equals(baSC, baNIO))
      throw new RuntimeException("getBytes(cs) failed  -> " + cs.name());

    // new String(csn);
    String strSC = new String(sbBA, cs.name());
    String strNIO = dec.reset().decode(ByteBuffer.wrap(sbBA)).toString();

    if (!strNIO.equals(strSC))
      throw new RuntimeException("new String(csn) failed  -> " + cs.name());

    // new String(cs);
    strSC = new String(sbBA, cs);
    if (!strNIO.equals(strSC)) throw new RuntimeException("new String(cs) failed  -> " + cs.name());

    // encode unmappable surrogates
    if (enc instanceof sun.nio.cs.ArrayEncoder && cs.contains(Charset.forName("ASCII"))) {
      if (cs.name().equals("UTF-8")
          || // utf8 handles surrogates
          cs.name().equals("CESU-8")) // utf8 handles surrogates
      return;
      enc.replaceWith(new byte[] {(byte) 'A'});
      sun.nio.cs.ArrayEncoder cae = (sun.nio.cs.ArrayEncoder) enc;

      String str = "ab\uD800\uDC00\uD800\uDC00cd";
      byte[] ba = new byte[str.length() - 2];
      int n = cae.encode(str.toCharArray(), 0, str.length(), ba);
      if (n != 6 || !"abAAcd".equals(new String(ba, cs.name())))
        throw new RuntimeException("encode1(surrogates) failed  -> " + cs.name());

      ba = new byte[str.length()];
      n = cae.encode(str.toCharArray(), 0, str.length(), ba);
      if (n != 6 || !"abAAcd".equals(new String(ba, 0, n, cs.name())))
        throw new RuntimeException("encode2(surrogates) failed  -> " + cs.name());
      str = "ab\uD800B\uDC00Bcd";
      ba = new byte[str.length()];
      n = cae.encode(str.toCharArray(), 0, str.length(), ba);
      if (n != 8 || !"abABABcd".equals(new String(ba, 0, n, cs.name())))
        throw new RuntimeException("encode3(surrogates) failed  -> " + cs.name());
      /* sun.nio.cs.ArrayDeEncoder works on the assumption that the
         invoker (StringCoder) allocates enough output buf, utf8
         and double-byte coder does not check the output buffer limit.
      ba = new byte[str.length() - 1];
      n = cae.encode(str.toCharArray(), 0, str.length(), ba);
      if (n != 7 || !"abABABc".equals(new String(ba, 0, n, cs.name()))) {
          throw new RuntimeException("encode4(surrogates) failed  -> "
                                     + cs.name());
      }
      */
    }
  }