예제 #1
0
  private boolean encodeObject(Object object) throws IOException {

    if (object instanceof BEncodableObject) {
      object = ((BEncodableObject) object).toBencodeObject();
    }

    if (object instanceof String || object instanceof Float) {

      String tempString =
          (object instanceof String) ? (String) object : String.valueOf((Float) object);

      // usually this is simpler to encode by hand as chars < 0x80 map directly in UTF-8

      boolean simple = true;

      int char_count = tempString.length();

      byte[] encoded = new byte[char_count];

      for (int i = 0; i < char_count; i++) {

        char c = tempString.charAt(i);

        if (c < 0x80) {

          encoded[i] = (byte) c;

        } else {

          simple = false;

          break;
        }
      }

      if (simple) {

        writeInt(char_count);

        writeChar(':');

        writeBytes(encoded);

      } else {

        ByteBuffer bb = Constants.DEFAULT_CHARSET.encode(tempString);

        writeInt(bb.limit());

        writeChar(':');

        writeByteBuffer(bb);
      }

    } else if (object instanceof Map) {

      Map tempMap = (Map) object;

      SortedMap tempTree = null;

      // unfortunately there are some occasions where we want to ensure that
      // the 'key' of the map is not mangled by assuming its UTF-8 encodable.
      // In particular the response from a tracker scrape request uses the
      // torrent hash as the KEY. Hence the introduction of the type below
      // to allow the constructor of the Map to indicate that the keys should
      // be extracted using a BYTE_ENCODING

      boolean byte_keys = object instanceof ByteEncodedKeyHashMap;

      // write the d
      writeChar('d');

      // are we sorted?
      if (tempMap instanceof TreeMap) {

        tempTree = (TreeMap) tempMap;

      } else {
        tempTree = new TreeMap(tempMap);
      }

      Iterator it = tempTree.entrySet().iterator();

      while (it.hasNext()) {

        Map.Entry entry = (Map.Entry) it.next();

        Object o_key = entry.getKey();

        Object value = entry.getValue();

        if (value != null) {
          if (o_key instanceof byte[]) {
            encodeObject(o_key);
            if (!encodeObject(value)) encodeObject("");
          } else if (o_key instanceof String) {
            String key = (String) o_key;
            if (byte_keys) {
              try {
                encodeObject(Constants.BYTE_CHARSET.encode(key));
                if (!encodeObject(value)) encodeObject("");
              } catch (UnsupportedEncodingException e) {
                throw (new IOException("BEncoder: unsupport encoding: " + e.getMessage()));
              }
            } else {
              encodeObject(key); // Key goes in as UTF-8
              if (!encodeObject(value)) encodeObject("");
            }
          } else
            Debug.out(
                "Attempt to encode an unsupported map key type: "
                    + object.getClass()
                    + ";value="
                    + object);
        }
      }

      writeChar('e');

    } else if (object instanceof List) {

      List tempList = (List) object;

      // write out the l

      writeChar('l');

      for (int i = 0; i < tempList.size(); i++) {

        encodeObject(tempList.get(i));
      }

      writeChar('e');

    } else if (object instanceof Long) {

      Long tempLong = (Long) object;
      // write out the l
      writeChar('i');
      writeLong(tempLong.longValue());
      writeChar('e');
    } else if (object instanceof Integer) {

      Integer tempInteger = (Integer) object;
      // write out the l
      writeChar('i');
      writeInt(tempInteger.intValue());
      writeChar('e');

    } else if (object instanceof byte[]) {

      byte[] tempByteArray = (byte[]) object;
      writeInt(tempByteArray.length);
      writeChar(':');
      if (url_encode) {
        writeBytes(
            URLEncoder.encode(
                    new String(tempByteArray, Constants.BYTE_ENCODING), Constants.BYTE_ENCODING)
                .getBytes());
      } else {
        writeBytes(tempByteArray);
      }

    } else if (object instanceof ByteBuffer) {

      ByteBuffer bb = (ByteBuffer) object;
      writeInt(bb.limit());
      writeChar(':');
      writeByteBuffer(bb);

    } else if (object == null) {

      // ideally we'd bork here but I don't want to run the risk of breaking existing stuff so just
      // log

      Debug.out("Attempt to encode a null value: sofar=" + getEncodedSoFar());
      return false;

    } else {

      Debug.out(
          "Attempt to encode an unsupported entry type: " + object.getClass() + ";value=" + object);
      return false;
    }

    return true;
  }