1/*
2 * Copyright (c) 2012, 2013, 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
25import java.io.UnsupportedEncodingException;
26import java.util.Arrays;
27import java.util.HashMap;
28import java.util.Map;
29import java.util.logging.ConsoleHandler;
30import java.util.logging.Level;
31import java.util.logging.Logger;
32
33/**
34 * Utility methods for parsing raw JDP packets.
35 *
36 * @author Alex Schenkman
37 */
38public 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}
143