1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 import java.io.UnsupportedEncodingException;
  26 import java.util.Arrays;
  27 import java.util.HashMap;
  28 import java.util.Map;
  29 import java.util.logging.ConsoleHandler;
  30 import java.util.logging.Level;
  31 import java.util.logging.Logger;
  32 
  33 /**
  34  * Utility methods for parsing raw JDP packets.
  35  *
  36  * @author Alex Schenkman
  37  */
  38 public class JdpTestUtil {
  39 
  40     static final int HEADER_SIZE = 4 + 2;   // magic + protocol version
  41 
  42     /**
  43      * Reads two bytes, starting at the given position,
  44      * and converts them into an int.
  45      *
  46      * @param data
  47      * @param pos
  48      * @return
  49      */
  50     static int decode2ByteInt(byte[] data, int pos) {
  51         return (((data[pos] & 0xFF) << 8) | (data[pos + 1] & 0xFF));
  52     }
  53 
  54     /**
  55      * Reads four bytes, starting at the given position,
  56      * and converts them into an int.
  57      *
  58      * @param data
  59      * @param pos
  60      * @return
  61      */
  62     static int decode4ByteInt(byte[] data, int pos) {
  63         int result = data[pos + 3] & 0xFF;
  64         result = result | ((data[pos + 2] & 0xFF) << 8);
  65         result = result | ((data[pos + 1] & 0xFF) << 16);
  66         result = result | ((data[pos] & 0xFF) << 24);
  67         return result;
  68     }
  69 
  70     /**
  71      * Reads an entry from the given byte array, starting at the given position.
  72      * This is an internal function used by @see readRawPayload(byte[] rawPayload, int size).
  73      * <p/>
  74      * The format of an entry is:
  75      * 2 bytes with the size of the following string.
  76      * n bytes of characters.
  77      *
  78      * @param data
  79      * @param pos
  80      * @return
  81      * @throws UnsupportedEncodingException
  82      */
  83     static String decodeEntry(byte[] data, int pos)
  84             throws UnsupportedEncodingException {
  85 
  86         int size = JdpTestUtil.decode2ByteInt(data, pos);
  87         pos = pos + 2;
  88         byte[] raw = Arrays.copyOfRange(data, pos, pos + size);
  89         return new String(raw, "UTF-8");
  90     }
  91 
  92     /**
  93      * Builds a Map with the payload, from the raw data.
  94      *
  95      * @param rawData
  96      * @return
  97      * @throws UnsupportedEncodingException
  98      */
  99     static Map<String, String> readPayload(byte[] rawData)
 100             throws UnsupportedEncodingException {
 101 
 102         int totalSize = rawData.length;
 103         int payloadSize = totalSize - HEADER_SIZE;
 104         byte[] rawPayload = Arrays.copyOfRange(rawData, HEADER_SIZE, HEADER_SIZE + payloadSize);
 105         Map<String, String> payload = readRawPayload(rawPayload, payloadSize);
 106         return payload;
 107     }
 108 
 109     /**
 110      * Builds a map from the payload's raw data.
 111      * This is an internal function used by @see readPayload(byte[] rawData)
 112      *
 113      * @param rawPayload
 114      * @param size
 115      * @return
 116      * @throws UnsupportedEncodingException
 117      */
 118     static Map<String, String> readRawPayload(byte[] rawPayload, int size)
 119             throws UnsupportedEncodingException {
 120 
 121         String key, value;
 122         Map<String, String> payload = new HashMap<String, String>();
 123 
 124         for (int pos = 0; pos < size; ) {
 125             key = decodeEntry(rawPayload, pos);
 126             pos = pos + 2 + key.length();
 127             value = decodeEntry(rawPayload, pos);
 128             pos = pos + 2 + value.length();
 129 
 130             payload.put(key, value);
 131         }
 132         return payload;
 133     }
 134 
 135     static void enableConsoleLogging(Logger log, Level level) throws SecurityException {
 136         ConsoleHandler handler = new ConsoleHandler();
 137         handler.setLevel(level);
 138         log.addHandler(handler);
 139         log.setLevel(level);
 140     }
 141 
 142 }