432a9a88b76f52b06a987c1b011b11df3507ddb1
[bgpcep.git] / bgp / util / src / main / java / org / opendaylight / protocol / bgp / util / HexDumpBGPFileParser.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.protocol.bgp.util;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Strings;
13 import com.google.common.collect.Lists;
14 import com.google.common.io.CharStreams;
15
16 import java.io.File;
17 import java.io.FileInputStream;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.InputStreamReader;
21 import java.util.List;
22
23 import javax.annotation.concurrent.Immutable;
24
25 import org.apache.commons.codec.DecoderException;
26 import org.apache.commons.codec.binary.Hex;
27 import org.opendaylight.protocol.util.ByteArray;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Read text file, parse BGP messages. File can contain comments or other data. BGP messages are detected using 16 ff
33  * marker. New lines and spaces are ignored. Use {@link ByteArray#bytesToHexString(byte[])} for serializing bytes to
34  * this format.
35  */
36 @Immutable
37 public final class HexDumpBGPFileParser {
38     private static final int MINIMAL_LENGTH = 19;
39     private static final Logger LOG = LoggerFactory.getLogger(HexDumpBGPFileParser.class);
40     private static final String FF_16 = Strings.repeat("FF", 16);
41
42     private HexDumpBGPFileParser() {
43
44     }
45
46     public static List<byte[]> parseMessages(final File file) throws IOException {
47         Preconditions.checkArgument(file != null, "Filename cannot be null");
48         return parseMessages(new FileInputStream(file));
49     }
50
51     public static List<byte[]> parseMessages(final InputStream is) throws IOException {
52         Preconditions.checkNotNull(is);
53         try (InputStreamReader isr = new InputStreamReader(is)) {
54             return parseMessages(CharStreams.toString(isr));
55         } finally {
56             is.close();
57         }
58     }
59
60     public static List<byte[]> parseMessages(final String c) {
61         final String content = clearWhiteSpaceToUpper(c);
62         // search for 16 FFs
63
64         final List<byte[]> messages = Lists.newLinkedList();
65         int idx = content.indexOf(FF_16, 0);
66         while (idx > -1) {
67             // next 2 bytes are length
68             final int lengthIdx = idx + 16 * 2;
69             final int messageIdx = lengthIdx + 4;
70             final String hexLength = content.substring(lengthIdx, messageIdx);
71             byte[] byteLength = null;
72             try {
73                 byteLength = Hex.decodeHex(hexLength.toCharArray());
74             } catch (final DecoderException e) {
75                 throw new IllegalArgumentException("Failed to decode message length", e);
76             }
77             final int length = ByteArray.bytesToInt(byteLength);
78             final int messageEndIdx = idx + length * 2;
79
80             // Assert that message is longer than minimum 19(header.length == 19)
81             // If length in BGP message would be 0, loop would never end
82             Preconditions.checkArgument(length >= MINIMAL_LENGTH, "Invalid message at index " + idx + ", length atribute is lower than "
83                     + MINIMAL_LENGTH);
84
85             final String hexMessage = content.substring(idx, messageEndIdx);
86             byte[] message = null;
87             try {
88                 message = Hex.decodeHex(hexMessage.toCharArray());
89             } catch (final DecoderException e) {
90                 new IllegalArgumentException("Failed to decode message body", e);
91             }
92             messages.add(message);
93             idx = messageEndIdx;
94             idx = content.indexOf(FF_16, idx);
95         }
96         LOG.info("Succesfully extracted {} messages", messages.size());
97         return messages;
98     }
99
100     @VisibleForTesting
101     static String clearWhiteSpaceToUpper(final String line) {
102         return line.replaceAll("\\s", "").toUpperCase();
103     }
104 }