import java.util.LinkedHashMap;
import java.util.Map;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.controller.sal.utils.EtherTypes;
/**
* Class that represents the Ethernet frame objects
- *
- *
*/
public class Ethernet extends Packet {
private static final String DMAC = "DestinationMACAddress";
put(ETHT, new ImmutablePair<Integer, Integer>(96, 16));
}
};
- private Map<String, byte[]> fieldValues;
+ private final Map<String, byte[]> fieldValues;
/**
* Default constructor that creates and sets the HashMap
return this;
}
- @Override
- public int hashCode() {
- return HashCodeBuilder.reflectionHashCode(this);
- }
-
- @Override
- public boolean equals(Object obj) {
- return EqualsBuilder.reflectionEquals(this, obj);
- }
-
}
import java.util.LinkedHashMap;
import java.util.Map;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.sal.utils.NetUtils;
/**
* Class that represents the ICMP packet objects
- *
- *
*/
public class ICMP extends Packet {
- private static final String TYPECODE = "TypeCode";
+ private static final String TYPE = "Type";
private static final String CODE = "Code";
- private static final String HEADERCHECKSUM = "HeaderChecksum";
+ private static final String CHECKSUM = "Checksum";
private static final String IDENTIFIER = "Identifier";
private static final String SEQNUMBER = "SequenceNumber";
private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
private static final long serialVersionUID = 1L;
-
{
- put(TYPECODE, new ImmutablePair<Integer, Integer>(0, 8));
+ put(TYPE, new ImmutablePair<Integer, Integer>(0, 8));
put(CODE, new ImmutablePair<Integer, Integer>(8, 8));
- put(HEADERCHECKSUM, new ImmutablePair<Integer, Integer>(16, 16));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(16, 16));
put(IDENTIFIER, new ImmutablePair<Integer, Integer>(32, 16));
put(SEQNUMBER, new ImmutablePair<Integer, Integer>(48, 16));
-
}
};
hdrFieldsMap = fieldValues;
}
- private Map<String, byte[]> fieldValues;
+ private final Map<String, byte[]> fieldValues;
@Override
public void setHeaderField(String headerField, byte[] readValue) {
}
/**
- * Sets the TypeCode of ICMP for the current ICMP object instance
- * @param short - typeCode
- * @return ICMP
+ * Sets the type for the current ICMP message
+ *
+ * @param type
+ * The ICMP message type
+ * @return This ICMP object
+ */
+ public ICMP setType(byte type) {
+ byte[] icmpType = BitBufferHelper.toByteArray(type);
+ fieldValues.put(TYPE, icmpType);
+ return this;
+ }
+
+ /**
+ * Sets the ICMP code (type subtype) for the current ICMP object instance
+ *
+ * @param code
+ * The ICMP message type subtype
+ * @return This ICMP object
*/
- public ICMP setTypeCode(short typeCode) {
- byte[] icmpTypeCode = BitBufferHelper.toByteArray(typeCode);
- fieldValues.put(TYPECODE, icmpTypeCode);
+ public ICMP setCode(byte code) {
+ byte[] icmpCode = BitBufferHelper.toByteArray(code);
+ fieldValues.put(CODE, icmpCode);
return this;
}
*/
public ICMP setChecksum(short checksum) {
byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum);
- fieldValues.put(HEADERCHECKSUM, icmpChecksum);
+ fieldValues.put(CHECKSUM, icmpChecksum);
return this;
}
return this;
}
+ /**
+ * Gets the header size in bits
+ * @return The ICMP header size in bits
+ */
@Override
- public int hashCode() {
- return HashCodeBuilder.reflectionHashCode(this);
+ public int getHeaderSize() {
+ return 64;
+ }
+
+ /**
+ * Computes the ICMP checksum on the serialized ICMP message
+ *
+ * @param serialized
+ * The data stream
+ * @param start
+ * The byte index on the data stream from which the ICMP packet
+ * starts
+ * @return The checksum
+ */
+ short computeChecksum(byte[] data, int start) {
+ int sum = 0, carry = 0, finalSum = 0;
+ int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte
+ + rawPayload.length;
+ int checksumStartByte = start + getfieldOffset(CHECKSUM)
+ / NetUtils.NumBitsInAByte;
+
+ for (int i = start; i <= (end - 1); i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ if (i == checksumStartByte) {
+ continue;
+ }
+ StringBuffer sbuffer = new StringBuffer();
+ sbuffer.append(String.format("%02X", data[i]));
+ if (i < (data.length - 1)) {
+ sbuffer.append(String.format("%02X", data[i + 1]));
+ }
+ sum += Integer.valueOf(sbuffer.toString(), 16);
+ }
+ carry = (sum >> 16) & 0xFF;
+ finalSum = (sum & 0xFFFF) + carry;
+ return (short) ~((short) finalSum & 0xFFFF);
+ }
+
+ @Override
+ protected void postSerializeCustomOperation(byte[] serializedBytes)
+ throws PacketException {
+ byte[] checkSum = BitBufferHelper
+ .toByteArray(computeChecksum(serializedBytes, 0));
+ try {
+ BitBufferHelper.setBytes(serializedBytes, checkSum,
+ getfieldOffset(CHECKSUM), getfieldnumBits(CHECKSUM));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
}
@Override
- public boolean equals(Object obj) {
- return EqualsBuilder.reflectionEquals(this, obj);
+ protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
+ short computedChecksum = computeChecksum(data, endBitOffset / NetUtils.NumBitsInAByte);
+ short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
+
+ if (computedChecksum != actualChecksum) {
+ corrupted = true;
+ }
+ }
+
+ /**
+ * Gets the checksum value stored
+ * @return the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
}
}
import java.util.Map;
import java.util.Random;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.controller.sal.utils.IPProtocols;
/**
* Class that represents the IPv4 packet objects
- *
- *
*/
public class IPv4 extends Packet {
protected static final Logger logger = LoggerFactory
- .getLogger(IPv4.class);
+ .getLogger(IPv4.class);
private static final String VERSION = "Version";
private static final String HEADERLENGTH = "HeaderLength";
private static final String DIFFSERV = "DiffServ";
}
};
- private Map<String, byte[]> fieldValues;
+ private final Map<String, byte[]> fieldValues;
+
/**
* Default constructor that sets the version to 4, headerLength to 5,
fieldValues = new HashMap<String, byte[]>();
hdrFieldCoordMap = fieldCoordinates;
hdrFieldsMap = fieldValues;
+ corrupted = false;
setVersion((byte) 4);
setHeaderLength((byte) 5);
setDiffServ((byte) 0);
+ setECN((byte) 0);
setIdentification(generateId());
setFlags((byte) 2);
setFragmentOffset((short) 0);
- setECN((byte) 0);
}
/**
fieldValues = new HashMap<String, byte[]>();
hdrFieldCoordMap = fieldCoordinates;
hdrFieldsMap = fieldValues;
+ corrupted = false;
setVersion((byte) 4);
setHeaderLength((byte) 5);
setDiffServ((byte) 0);
+ setECN((byte) 0);
setIdentification(generateId());
setFlags((byte) 2);
setFragmentOffset((short) 0);
- setECN((byte) 0);
}
/**
}
/**
- * Gets the header length in bits, from the header length stored and options if any
- * @return HeaderLength to serialize code
+ * Gets the header size in bits
+ * @return The number of bits constituting the header
*/
@Override
public int getHeaderSize() {
int headerLen = this.getHeaderLen();
- if (headerLen == 0)
+ if (headerLen == 0) {
headerLen = 20;
+ }
byte[] options = hdrFieldsMap.get(OPTIONS);
- if (options != null)
+ if (options != null) {
headerLen += options.length;
+ }
return headerLen * NetUtils.NumBitsInAByte;
-
}
/**
}
/**
- * Computes the header checksum
- * @param byte[] hdrBytes - serialized bytes
- * @param int endBitOffset - end bit Offset
- * @return short - the computed checksum
+ * Computes the IPv4 header checksum on the passed stream of bytes
+ * representing the packet
+ *
+ * @param data
+ * The byte stream
+ * @param offset
+ * The byte offset from where the IPv4 packet starts
+ * @return The computed checksum
*/
- private short computeChecksum(byte[] hdrBytes, int endByteOffset) {
- int startByteOffset = endByteOffset - getHeaderLen();
+ short computeChecksum(byte[] data, int start) {
+ int end = start + getHeaderLen();
short checkSum = (short) 0;
int sum = 0, carry = 0, finalSum = 0;
int parsedHex = 0;
- int checksumStartByte = startByteOffset + getfieldOffset(CHECKSUM)
- / NetUtils.NumBitsInAByte;
+ int checksumStart = start
+ + (getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte);
- for (int i = startByteOffset; i <= (endByteOffset - 1); i = i + 2) {
- //Skip, if the current bytes are checkSum bytes
- if (i == checksumStartByte)
+ for (int i = start; i <= (end - 1); i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ if (i == checksumStart) {
continue;
+ }
StringBuffer sbuffer = new StringBuffer();
- sbuffer.append(String.format("%02X", hdrBytes[i]));
- if (i < (hdrBytes.length - 1))
- sbuffer.append(String.format("%02X", hdrBytes[i + 1]));
+ sbuffer.append(String.format("%02X", data[i]));
+ if (i < (data.length - 1)) {
+ sbuffer.append(String.format("%02X", data[i + 1]));
+ }
parsedHex = Integer.valueOf(sbuffer.toString(), 16);
sum += parsedHex;
carry = (sum >> 16) & 0xFF;
finalSum = (sum & 0xFFFF) + carry;
checkSum = (short) ~((short) finalSum & 0xFFFF);
- return checkSum;
- }
-
- @Override
- public int hashCode() {
- return HashCodeBuilder.reflectionHashCode(this);
- }
- @Override
- public boolean equals(Object obj) {
- return EqualsBuilder.reflectionEquals(this, obj);
+ return checkSum;
}
@Override
byte[] options = getOptions();
return ((options == null) ? 0 : (options.length - getHeaderLen()));
}
- return (((Pair<Integer, Integer>) hdrFieldCoordMap.get(fieldName))
- .getRight());
+ return hdrFieldCoordMap.get(fieldName).getRight();
}
@Override
/**
* Method to perform post serialization - like computation of checksum of serialized header
- * @param serializedBytes
+ * @param data
* @return void
* @Exception throws PacketException
*/
- protected void postSerializeCustomOperation(byte[] serializedBytes)
+ protected void postSerializeCustomOperation(byte[] data)
throws PacketException {
- int startOffset = this.getfieldOffset(CHECKSUM);
- int numBits = this.getfieldnumBits(CHECKSUM);
- byte[] checkSum = BitBufferHelper.toByteArray(computeChecksum(
- serializedBytes, serializedBytes.length));
+
+ // Recompute the total length field here
+ byte[] totalLength = BitBufferHelper.toByteArray((short) data.length);
try {
- BitBufferHelper.setBytes(serializedBytes, checkSum, startOffset,
- numBits);
+ BitBufferHelper.setBytes(data, totalLength, getfieldOffset(TOTLENGTH),
+ getfieldnumBits(TOTLENGTH));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+
+ // Now compute the Header Checksum
+ byte[] checkSum = BitBufferHelper.toByteArray(computeChecksum(data, 0));
+
+ try {
+ BitBufferHelper.setBytes(data, checkSum, getfieldOffset(CHECKSUM),
+ getfieldnumBits(CHECKSUM));
} catch (BufferException e) {
throw new PacketException(e.getMessage());
}
* bytes in Total Length
* @param payload - Packet
*/
+ /**
+ * Set the total length field in the IPv4 Object
+ * Note: this field will get overwritten during serialization phase.
+ */
public void setPayload(Packet payload) {
this.payload = payload;
/*
- * Deriving the Total Lenght here
- * TODO: See if we can derive the total length during
- * another phase (during serialization/deserialization)
- * */
+ * Deriving the Total Length here
+ */
int payloadLength = 0;
try {
payloadLength = payload.serialize().length;
} catch (PacketException e) {
logger.error("", e);
}
+
this.setTotalLength((short) (this.getHeaderLen() + payloadLength));
}
- @Override
+
/**
* Method to perform post deserialization - like compare computed checksum with
* the one obtained from IP header
*/
- protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
- int endByteOffset = endBitOffset / NetUtils.NumBitsInAByte;
- int computedChecksum = computeChecksum(data, endByteOffset);
- int actualChecksum = BitBufferHelper.getInt(fieldValues.get(CHECKSUM));
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int startBitOffset) {
+ int start = startBitOffset / NetUtils.NumBitsInAByte;
+ short computedChecksum = computeChecksum(data, start);
+ short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
if (computedChecksum != actualChecksum) {
corrupted = true;
}
package org.opendaylight.controller.sal.packet;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Arrays;
private static final String VALUE = "Value";
private static final int LLDPTLVFields = 3;
public static final byte[] OFOUI = new byte[] { (byte) 0x00, (byte) 0x26,
- (byte) 0xe1 }; // OpenFlow OUI
+ (byte) 0xe1 }; // OpenFlow OUI
public static final byte[] customTlvSubType = new byte[] { 0 };
public static final int customTlvOffset = OFOUI.length
+ customTlvSubType.length;
public enum TLVType {
Unknown((byte) 0), ChassisID((byte) 1), PortID((byte) 2), TTL((byte) 3), PortDesc(
(byte) 4), SystemName((byte) 5), SystemDesc((byte) 6), Custom(
- (byte) 127);
+ (byte) 127);
private byte value;
@Override
public int getfieldnumBits(String fieldName) {
if (fieldName.equals(VALUE)) {
- return (NetUtils.NumBitsInAByte * (int) BitBufferHelper.getShort(
+ return (NetUtils.NumBitsInAByte * BitBufferHelper.getShort(
fieldValues.get(LENGTH), fieldCoordinates.get(LENGTH)
- .getRight().intValue()));
+ .getRight().intValue()));
}
return fieldCoordinates.get(fieldName).getRight();
}
public int getTLVSize() {
return (LLDPTLV.fieldCoordinates.get(TYPE).getRight() + // static
LLDPTLV.fieldCoordinates.get(LENGTH).getRight() + // static
- getfieldnumBits(VALUE)); // variable
+ getfieldnumBits(VALUE)); // variable
}
/**
* @return the PortID TLV value in byte array
*/
static public byte[] createPortIDTLVValue(String portId) {
- byte[] pid = portId.getBytes();
+ byte[] pid = portId.getBytes(Charset.defaultCharset());
byte[] pidValue = new byte[pid.length + portIDSubType.length];
System.arraycopy(portIDSubType, 0, pidValue, 0, portIDSubType.length);
* @return the custom TLV value in byte array
*/
static public byte[] createCustomTLVValue(String customString) {
- byte[] customArray = customString.getBytes();
+ byte[] customArray = customString.getBytes(Charset.defaultCharset());
byte[] customValue = new byte[customTlvOffset + customArray.length];
System.arraycopy(OFOUI, 0, customValue, 0, OFOUI.length);
byte[] pidBytes = new byte[tlvLen - portIDSubType.length];
System.arraycopy(tlvValue, portIDSubType.length, pidBytes, 0,
pidBytes.length);
- return (new String(pidBytes));
+ return (new String(pidBytes, Charset.defaultCharset()));
}
/**
package org.opendaylight.controller.sal.packet;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
+import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
* Abstract class which represents the generic network packet object It provides
* the basic methods which are common for all the packets, like serialize and
* deserialize
- *
- *
*/
public abstract class Packet {
protected Packet parent;
// The packet encapsulated by this packet
protected Packet payload;
+ // The unparsed raw payload carried by this packet
+ protected byte[] rawPayload;
// Bit coordinates of packet header fields
protected Map<String, Pair<Integer, Integer>> hdrFieldCoordMap;
// Header fields values: Map<FieldName,Value>
public Packet(boolean writeAccess) {
this.writeAccess = writeAccess;
- this.corrupted = false;
+ corrupted = false;
}
public Packet getParent() {
* @return Packet
* @throws PacketException
*/
-
public Packet deserialize(byte[] data, int bitOffset, int size)
throws PacketException {
- String hdrField;
- Integer startOffset = 0, numBits = 0;
- byte[] hdrFieldBytes;
+ // Deserialize the header fields one by one
+ int startOffset = 0, numBits = 0;
for (Entry<String, Pair<Integer, Integer>> pairs : hdrFieldCoordMap
.entrySet()) {
- hdrField = pairs.getKey();
+ String hdrField = pairs.getKey();
startOffset = bitOffset + this.getfieldOffset(hdrField);
numBits = this.getfieldnumBits(hdrField);
+ byte[] hdrFieldBytes = null;
try {
hdrFieldBytes = BitBufferHelper.getBits(data, startOffset,
numBits);
} catch (BufferException e) {
throw new PacketException(e.getMessage());
}
+
/*
* Store the raw read value, checks the payload type and set the
* payloadClass accordingly
*/
+ this.setHeaderField(hdrField, hdrFieldBytes);
+
if (logger.isTraceEnabled()) {
- logger.trace("{}: {}: {} (offset {} bitsize {})",
- new Object[] { this.getClass().getSimpleName(), hdrField,
- HexEncode.bytesToHexString(hdrFieldBytes),
- startOffset, numBits });
+ logger.trace("{}: {}: {} (offset {} bitsize {})",
+ new Object[] { this.getClass().getSimpleName(), hdrField,
+ HexEncode.bytesToHexString(hdrFieldBytes),
+ startOffset, numBits });
}
-
- this.setHeaderField(hdrField, hdrFieldBytes);
}
- postDeserializeCustomOperation(data, startOffset);
-
+ // Deserialize the payload now
int payloadStart = startOffset + numBits;
- // int payloadSize = size - payloadStart;
int payloadSize = data.length * NetUtils.NumBitsInAByte - payloadStart;
if (payloadClass != null) {
payload.deserialize(data, payloadStart, payloadSize);
payload.setParent(this);
} else {
- // For now let's discard unparsable payload
+ /*
+ * The payload class was not set, it means no class for parsing
+ * this payload is present. Let's store the raw payload if any.
+ */
+ int start = payloadStart / NetUtils.NumBitsInAByte;
+ int stop = start + payloadSize / NetUtils.NumBitsInAByte;
+ rawPayload = Arrays.copyOfRange(data, start, stop);
}
+
+
+ // Take care of computation that can be done only after deserialization
+ postDeserializeCustomOperation(data, payloadStart - getHeaderSize());
+
return this;
}
/**
- * This method serializes the header and payload bytes from the respective
+ * This method serializes the header and payload from the respective
* packet class, into a single stream of bytes to be sent on the wire
*
- * @return byte[] - serialized bytes
+ * @return The byte array representing the serialized Packet
* @throws PacketException
*/
-
public byte[] serialize() throws PacketException {
- byte[] payloadBytes = null;
- int payloadSize = 0;
- int headerSize = this.getHeaderSize();
- int payloadByteOffset = headerSize / NetUtils.NumBitsInAByte;
- int size = 0;
+ // Acquire or compute the serialized payload
+ byte[] payloadBytes = null;
if (payload != null) {
payloadBytes = payload.serialize();
- payloadSize = payloadBytes.length * NetUtils.NumBitsInAByte;
+ } else if (rawPayload != null) {
+ payloadBytes = rawPayload;
}
+ int payloadSize = (payloadBytes == null) ? 0 : payloadBytes.length;
- size = headerSize + payloadSize;
- int length = size / NetUtils.NumBitsInAByte;
- byte headerBytes[] = new byte[length];
-
- if (payload != null) {
- System.arraycopy(payloadBytes, 0, headerBytes, payloadByteOffset,
- payloadBytes.length);
+ // Allocate the buffer to contain the full (header + payload) packet
+ int headerSize = this.getHeaderSize() / NetUtils.NumBitsInAByte;
+ byte packetBytes[] = new byte[headerSize + payloadSize];
+ if (payloadBytes != null) {
+ System.arraycopy(payloadBytes, 0, packetBytes, headerSize, payloadSize);
}
- String field;
- byte[] fieldBytes;
- Integer startOffset, numBits;
-
+ // Serialize this packet header, field by field
for (Map.Entry<String, Pair<Integer, Integer>> pairs : hdrFieldCoordMap
.entrySet()) {
- field = pairs.getKey();
- fieldBytes = hdrFieldsMap.get(field);
+ String field = pairs.getKey();
+ byte[] fieldBytes = hdrFieldsMap.get(field);
// Let's skip optional fields when not set
if (fieldBytes != null) {
- startOffset = this.getfieldOffset(field);
- numBits = this.getfieldnumBits(field);
try {
- BitBufferHelper.setBytes(headerBytes, fieldBytes,
- startOffset, numBits);
+ BitBufferHelper.setBytes(packetBytes, fieldBytes,
+ getfieldOffset(field), getfieldnumBits(field));
} catch (BufferException e) {
throw new PacketException(e.getMessage());
}
}
}
- postSerializeCustomOperation(headerBytes);
+
+ // Perform post serialize operations (like checksum computation)
+ postSerializeCustomOperation(packetBytes);
if (logger.isTraceEnabled()) {
- logger.trace("{}: {}", this.getClass().getSimpleName(),
- HexEncode.bytesToHexString(headerBytes));
+ logger.trace("{}: {}", this.getClass().getSimpleName(),
+ HexEncode.bytesToHexString(packetBytes));
}
- return headerBytes;
+
+ return packetBytes;
}
/**
/**
* This method re-computes the checksum of the bits received on the wire and
* validates it with the checksum in the bits received Since the computation
- * of checksum varies based on the protocol, this method is overridden
- * Currently only IPv4 does checksum computation and validation TCP and UDP
- * need to implement these if required
+ * of checksum varies based on the protocol, this method is overridden.
+ * Currently only IPv4 and ICMP do checksum computation and validation. TCP
+ * and UDP need to implement these if required.
*
- * @param byte[] data
- * @param int endBitOffset
+ * @param byte[] data The byte stream representing the Ethernet frame
+ * @param int startBitOffset The bit offset from where the byte array corresponding to this Packet starts in the frame
* @throws PacketException
*/
- protected void postDeserializeCustomOperation(byte[] data, int endBitOffset)
+ protected void postDeserializeCustomOperation(byte[] data, int startBitOffset)
throws PacketException {
// no op
}
* @return Integer - startOffset of the requested field
*/
public int getfieldOffset(String fieldName) {
- return (((Pair<Integer, Integer>) hdrFieldCoordMap.get(fieldName))
- .getLeft());
+ return hdrFieldCoordMap.get(fieldName).getLeft();
}
/**
* @return Integer - number of bits of the requested field
*/
public int getfieldnumBits(String fieldName) {
- return (((Pair<Integer, Integer>) hdrFieldCoordMap.get(fieldName))
- .getRight());
+ return hdrFieldCoordMap.get(fieldName).getRight();
}
@Override
public String toString() {
- StringBuffer ret = new StringBuffer();
- for (Map.Entry<String, byte[]> entry : hdrFieldsMap.entrySet()) {
- ret.append(entry.getKey() + ": ");
- if (entry.getValue().length == 6) {
- ret.append(HexEncode.bytesToHexString(entry.getValue()) + " ");
- } else if (entry.getValue().length == 4) {
- try {
- ret.append(InetAddress.getByAddress(entry.getValue())
- .getHostAddress() + " ");
- } catch (UnknownHostException e) {
- logger.error("", e);
- }
- } else {
- ret.append(((Long) BitBufferHelper.getLong(entry.getValue()))
- .toString() + " ");
- }
+ StringBuilder ret = new StringBuilder();
+ ret.append(this.getClass().getSimpleName());
+ ret.append(": [");
+ for (String field : hdrFieldCoordMap.keySet()) {
+ byte[] value = hdrFieldsMap.get(field);
+ ret.append(field);
+ ret.append(": ");
+ ret.append(HexEncode.bytesToHexString(value));
+ ret.append(", ");
}
+ ret.replace(ret.length()-2, ret.length()-1, "]");
return ret.toString();
}
/**
- * Returns true if the packet is corrupted
+ * Returns the raw payload carried by this packet in case payload was not
+ * parsed. Caller can call this function in case the getPaylod() returns null.
*
- * @return boolean
+ * @return The raw payload if not parsable as an array of bytes, null otherwise
*/
- protected boolean isPacketCorrupted() {
+ public byte[] getRawPayload() {
+ return rawPayload;
+ }
+
+ /**
+ * Set a raw payload in the packet class
+ *
+ * @param payload The raw payload as byte array
+ */
+ public void setRawPayload(byte[] payload) {
+ this.rawPayload = Arrays.copyOf(payload, payload.length);
+ }
+
+ /**
+ * Return whether the deserialized packet is to be considered corrupted.
+ * This is the case when the checksum computed after reconstructing the
+ * packet received from wire is not equal to the checksum read from the
+ * stream. For the Packet class which do not have a checksum field, this
+ * function will always return false.
+ *
+ *
+ * @return true if the deserialized packet's recomputed checksum is not
+ * equal to the packet carried checksum
+ */
+ public boolean isCorrupted() {
return corrupted;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result
+ + ((this.hdrFieldsMap == null) ? 0 : hdrFieldsMap.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Packet other = (Packet) obj;
+ if (hdrFieldsMap == other.hdrFieldsMap) {
+ return true;
+ }
+ if (hdrFieldsMap == null || other.hdrFieldsMap == null) {
+ return false;
+ }
+ if (hdrFieldsMap != null && other.hdrFieldsMap != null) {
+ for (String field : hdrFieldsMap.keySet()) {
+ if (!Arrays.equals(hdrFieldsMap.get(field), other.hdrFieldsMap.get(field))) {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
+
}
*/
public class RawPacket {
private byte[] packetData;
- private LinkEncap encap;
- private TimeStamp incomingTime;
- private TimeStamp copyTime;
- private Map props;
+ private final LinkEncap encap;
+ private final TimeStamp incomingTime;
+ private final TimeStamp copyTime;
+ private Map<Object, Object> props;
private NodeConnector incomingNodeConnector;
private NodeConnector outgoingNodeConnector;
*/
public void setProps(Object key, Object value) {
if (this.props == null) {
- this.props = new HashMap();
+ this.props = new HashMap<Object, Object>();
}
this.props.put(key, value);
this.incomingTime = src.getIncomingTime();
this.incomingNodeConnector = src.getIncomingNodeConnector();
this.outgoingNodeConnector = src.getOutgoingNodeConnector();
- this.props = (src.props == null ? null : new HashMap(src.props));
+ this.props = (src.props == null ? null : new HashMap<Object, Object>(
+ src.props));
this.copyTime = new TimeStamp(System.currentTimeMillis(), "CopyTime");
}
}
/**
- * Read the timestamp when the packet has entered the system
+ * Read the time stamp when the packet has entered the system
*
- * @return The timestamp when the packet has entered the system
+ * @return The time stamp when the packet has entered the system
*/
public TimeStamp getIncomingTime() {
return this.incomingTime;
public byte[] getPacketData() {
return this.packetData;
}
+
+ /**
+ * Returns the time at which the current instance of RawPacket was created
+ * as a copy of the original one.
+ *
+ * @return The time stamp at which this RawPacket instance was created. null
+ * if this is the original instance.
+ */
+ public TimeStamp getCopyTime() {
+ return this.copyTime;
+ }
}
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
+
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
/**
* Class that represents the TCP segment objects
- *
- *
*/
public class TCP extends Packet {
}
};
- private Map<String, byte[]> fieldValues;
+ private final Map<String, byte[]> fieldValues;
/**
* Default constructor that sets all the header fields to zero
return (BitBufferHelper.getShort(fieldValues.get(DESTPORT)));
}
- @Override
- public int hashCode() {
- return HashCodeBuilder.reflectionHashCode(this);
- }
-
- @Override
- public boolean equals(Object obj) {
- return EqualsBuilder.reflectionEquals(this, obj);
- }
-
}
import java.util.LinkedHashMap;
import java.util.Map;
-import org.apache.commons.lang3.builder.EqualsBuilder;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
/**
* Class that represents the UDP datagram objects
- *
- *
*/
public class UDP extends Packet {
setChecksum((short) 0);
}
- private Map<String, byte[]> fieldValues;
+ private final Map<String, byte[]> fieldValues;
/* public static Map<Short, Class<? extends Packet>> decodeMap;
fieldValues.put(CHECKSUM, checksum);
return this;
}
-
- @Override
- public int hashCode() {
- return HashCodeBuilder.reflectionHashCode(this);
- }
-
- @Override
- public boolean equals(Object obj) {
- return EqualsBuilder.reflectionEquals(this, obj);
- }
}
*
*/
public class HexEncode {
- /**
- * This method converts byte array into String format without ":" inserted.
- */
+ /**
+ * This method converts byte array into String format without ":" inserted.
+ *
+ * @param bytes
+ * The byte array to convert to string
+ * @return The hexadecimal representation of the byte array. If bytes is
+ * null, "null" string is returned
+ */
public static String bytesToHexString(byte[] bytes) {
- int i;
+
+ if (bytes == null) {
+ return "null";
+ }
+
String ret = "";
- String tmp;
StringBuffer buf = new StringBuffer();
- for (i = 0; i < bytes.length; i++) {
- if (i > 0)
+ for (int i = 0; i < bytes.length; i++) {
+ if (i > 0) {
ret += ":";
- short u8byte = (short) ((short) bytes[i] & 0xff);
- tmp = Integer.toHexString(u8byte);
- if (tmp.length() == 1)
+ }
+ short u8byte = (short) (bytes[i] & 0xff);
+ String tmp = Integer.toHexString(u8byte);
+ if (tmp.length() == 1) {
buf.append("0");
+ }
buf.append(tmp);
}
ret = buf.toString();
int i = 0;
for (; i < (16 - arr.length); i++) {
buf.append("0");
- if ((i & 0x01) == 1)
+ if ((i & 0x01) == 1) {
buf.append(":");
+ }
}
for (int j = 0; j < arr.length; j++) {
buf.append(arr[j]);
- if ((((i + j) & 0x01) == 1) && (j < (arr.length - 1)))
+ if ((((i + j) & 0x01) == 1) && (j < (arr.length - 1))) {
buf.append(":");
+ }
}
return buf.toString();
}
+
public static byte[] bytesFromHexString(String values) {
- String[] octets = values.split(":");
- byte[] ret = new byte[octets.length];
- int i;
+ String target = "";
+ if (values != null) {
+ target = values;
+ }
+ String[] octets = target.split(":");
- for (i = 0; i < octets.length; i++)
+ byte[] ret = new byte[octets.length];
+ for (int i = 0; i < octets.length; i++) {
ret[i] = Integer.valueOf(octets[i], 16).byteValue();
+ }
return ret;
}
return value;
}
- /**
- * This method converts byte array into HexString format with ":" inserted.
- */
+ /**
+ * This method converts byte array into HexString format with ":" inserted.
+ */
public static String bytesToHexStringFormat(byte[] bytes) {
- int i;
+ if (bytes == null) {
+ return "null";
+ }
String ret = "";
- String tmp;
StringBuffer buf = new StringBuffer();
- for (i = 0; i < bytes.length; i++) {
- if (i > 0)
+ for (int i = 0; i < bytes.length; i++) {
+ if (i > 0) {
buf.append(":");
- short u8byte = (short) ((short) bytes[i] & 0xff);
- tmp = Integer.toHexString(u8byte);
- if (tmp.length() == 1)
+ }
+ short u8byte = (short) (bytes[i] & 0xff);
+ String tmp = Integer.toHexString(u8byte);
+ if (tmp.length() == 1) {
buf.append("0");
+ }
buf.append(tmp);
}
ret = buf.toString();
import junit.framework.Assert;
import org.junit.Test;
-import org.opendaylight.controller.sal.packet.ICMP;
public class ICMPTest {
@Test
public void testSetTypeCode() {
ICMP icmp = new ICMP();
- short icmpTypeCode = 2;
- icmp.setTypeCode(icmpTypeCode);
- byte[] typeCode = icmp.hdrFieldsMap.get("TypeCode");
- Assert.assertTrue(typeCode[0] == 0);
- Assert.assertTrue(typeCode[1] == 2);
+ byte icmpType = 2;
+ icmp.setType(icmpType);
+ byte[] typeCode = icmp.hdrFieldsMap.get("Type");
+ Assert.assertTrue(typeCode[0] == 2);
}
ICMP icmp = new ICMP();
short icmpChecksum = 200;
icmp.setChecksum(icmpChecksum);
- byte[] checksum = icmp.hdrFieldsMap.get("HeaderChecksum");
+ byte[] checksum = icmp.hdrFieldsMap.get("Checksum");
Assert.assertTrue(checksum[0] == 0);
Assert.assertTrue(checksum[1] == -56);
Assert.assertTrue(sequenceNumber[1] == -120);
}
+
+ @Test
+ public void testSerialization() throws PacketException {
+ byte icmpRawPayload[] = { (byte) 0x38, (byte) 0x26, (byte) 0x9e,
+ (byte) 0x51, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x2e, (byte) 0x6a, (byte) 0x08,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x10, (byte) 0x11, (byte) 0x12,
+ (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16,
+ (byte) 0x17, (byte) 0x18, (byte) 0x19, (byte) 0x1a,
+ (byte) 0x1b, (byte) 0x1c, (byte) 0x1d, (byte) 0x1e,
+ (byte) 0x1f, (byte) 0x20, (byte) 0x21, (byte) 0x22,
+ (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26,
+ (byte) 0x27, (byte) 0x28, (byte) 0x29, (byte) 0x2a,
+ (byte) 0x2b, (byte) 0x2c, (byte) 0x2d, (byte) 0x2e,
+ (byte) 0x2f, (byte) 0x30, (byte) 0x31, (byte) 0x32,
+ (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x36, (byte) 0x37 };
+
+ short checksum = (short)0xe553;
+
+ // Create ICMP object
+ ICMP icmp = new ICMP();
+ icmp.setType((byte)8);
+ icmp.setCode((byte)0);
+ icmp.setIdentifier((short) 0x46f5);
+ icmp.setSequenceNumber((short) 2);
+ icmp.setRawPayload(icmpRawPayload);
+ //icmp.setChecksum(checksum);
+
+ // Serialize
+ byte[] stream = icmp.serialize();
+ Assert.assertTrue(stream.length == 64);
+
+ // Deserialize
+ ICMP icmpDes = new ICMP();
+ icmpDes.deserialize(stream, 0, stream.length);
+
+ Assert.assertFalse(icmpDes.isCorrupted());
+ Assert.assertTrue(icmpDes.getChecksum() == checksum);
+ Assert.assertTrue(icmp.equals(icmpDes));
+ }
}
-
/*
* Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
*
package org.opendaylight.controller.sal.packet;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
import junit.framework.Assert;
import org.junit.Test;
-import org.opendaylight.controller.sal.packet.ICMP;
-import org.opendaylight.controller.sal.packet.IPv4;
-import org.opendaylight.controller.sal.packet.Packet;
+import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.IPProtocols;
+import org.opendaylight.controller.sal.utils.NetUtils;
public class IPv4Test {
byte[] iptotLength = { 3, -24 };
ip.hdrFieldsMap.put("TotalLength", iptotLength);
short totalLength = ip.getTotalLength();
- //System.out.println(totalLength);
Assert.assertTrue(totalLength == 1000);
}
Assert.assertTrue(protocol == 1);
Class<? extends Packet> clazz = IPv4.protocolClassMap.get(protocol);
- System.out.printf("clazz = %s\n", clazz.getName());
Assert.assertTrue(clazz == ICMP.class);
}
byte[] totalLength = ip.hdrFieldsMap.get("TotalLength");
Assert.assertTrue(totalLength[0] == 3);
Assert.assertTrue(totalLength[1] == -24);
+
+ ip.setTotalLength((short)84);
+ totalLength = ip.hdrFieldsMap.get("TotalLength");
+ Assert.assertTrue(totalLength[0] == 0);
+ Assert.assertTrue(totalLength[1] == 84);
}
@Test
Assert.assertTrue(fragmentOffset[1] == -35);
}
-
@Test
public void testSetDestinationAddress() {
IPv4 ip = new IPv4();
Assert.assertTrue(destinationAddress[3] == 110);
}
+ @Test
+ public void testChecksum() {
+ byte header[] = { (byte) 0x45, 00, 00, (byte) 0x3c, (byte) 0x1c,
+ (byte) 0x46, (byte) 0x40, 00, (byte) 0x40, 06, (byte) 0xb1,
+ (byte) 0xe6, (byte) 0xac, (byte) 0x10, (byte) 0x0a,
+ (byte) 0x63, (byte) 0xac, (byte) 0x10, (byte) 0x0a, (byte) 0x0c };
+ byte header2[] = { (byte) 0x45, 00, 00, (byte) 0x73, 00, 00,
+ (byte) 0x40, 00, (byte) 0x40, (byte) 0x11, (byte) 0xb8,
+ (byte) 0x61, (byte) 0xc0, (byte) 0xa8, 00, 01, (byte) 0xc0,
+ (byte) 0xa8, 00, (byte) 0xc7 };
+ byte header3[] = { (byte) 0x45, 00, 00, (byte) 0x47, (byte) 0x73,
+ (byte) 0x88, (byte) 0x40, 00, (byte) 0x40, 06, (byte) 0xA2,
+ (byte) 0xC4, (byte) 0x83, (byte) 0x9F, (byte) 0x0E,
+ (byte) 0x85, (byte) 0x83, (byte) 0x9F, (byte) 0x0E, (byte) 0xA1 };
+ byte header4[] = { (byte) 0x45, 00, 00, (byte) 0x54, 00, 00,
+ (byte) 0x40, 00, (byte) 0x40, 01, (byte) 0xf0, (byte) 0x8e,
+ (byte) 0xc0, (byte) 0xa8, (byte) 0x64, (byte) 0x65,
+ (byte) 0xc0, (byte) 0xa8, (byte) 0x64, (byte) 0x64 };
+ byte header5[] = { (byte) 0x45, 00, 00, (byte) 0x54, 00, 00,
+ (byte) 0x40, 00, (byte) 0x40, 01, (byte) 0xef, (byte) 0x8d,
+ (byte) 0xc0, (byte) 0xa8, (byte) 0x64, (byte) 0x65,
+ (byte) 0xc0, (byte) 0xa8, (byte) 0x65, (byte) 0x65 };
+ byte header6[] = { (byte) 0x45, 00, 00, (byte) 0x54, 00, 00,
+ (byte) 0x40, 00, (byte) 0x40, 01, (byte) 0x0b, (byte) 0x92,
+ (byte) 0xc0, (byte) 0xa8, (byte) 0x64, (byte) 0x65, (byte) 0x9,
+ (byte) 0x9, (byte) 0x1, (byte) 0x1 };
+ byte header7[] = { (byte) 0x45, 00, 00, (byte) 0x54, 00, 00,
+ (byte) 0x40, 00, (byte) 0x40, 01, (byte) 0, (byte) 0,
+ (byte) 0xc0, (byte) 0xa8, (byte) 0x64, (byte) 0x65, (byte) 0x9,
+ (byte) 0x9, (byte) 0x2, (byte) 0x2 };
+
+ IPv4 ip = new IPv4();
+
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header,
+ 0)) == 0xB1E6);
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header2,
+ 0)) == 0xb861);
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header3,
+ 0)) == 0xa2c4);
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header4,
+ 0)) == 0xf08e);
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header5,
+ 0)) == 0xef8d);
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header6,
+ 0)) == 0x0b92);
+ Assert.assertTrue(NetUtils.getUnsignedShort(ip.computeChecksum(header7,
+ 0)) == 0x0a91);
+ }
+
+ @Test
+ public void testFullIP() throws UnknownHostException, PacketException {
+ byte[] icmpRawPayload = new byte[] { (byte) 0x38, (byte) 0x26,
+ (byte) 0x9e, (byte) 0x51, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x2e, (byte) 0x6a,
+ (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x10, (byte) 0x11,
+ (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15,
+ (byte) 0x16, (byte) 0x17, (byte) 0x18, (byte) 0x19,
+ (byte) 0x1a, (byte) 0x1b, (byte) 0x1c, (byte) 0x1d,
+ (byte) 0x1e, (byte) 0x1f, (byte) 0x20, (byte) 0x21,
+ (byte) 0x22, (byte) 0x23, (byte) 0x24, (byte) 0x25,
+ (byte) 0x26, (byte) 0x27, (byte) 0x28, (byte) 0x29,
+ (byte) 0x2a, (byte) 0x2b, (byte) 0x2c, (byte) 0x2d,
+ (byte) 0x2e, (byte) 0x2f, (byte) 0x30, (byte) 0x31,
+ (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35,
+ (byte) 0x36, (byte) 0x37 };
+ ICMP icmp = new ICMP();
+ icmp.setType((byte) 8);
+ icmp.setCode((byte) 0);
+ icmp.setIdentifier((short) 0x46f5);
+ icmp.setSequenceNumber((short) 2);
+ icmp.setRawPayload(icmpRawPayload);
+
+ IPv4 ip = new IPv4();
+ ip.setVersion((byte) 4);
+ ip.setIdentification((short) 5);
+ ip.setDiffServ((byte) 0);
+ ip.setECN((byte) 0);
+ ip.setTotalLength((short) 84);
+ ip.setFlags((byte) 2);
+ ip.setFragmentOffset((short) 0);
+ ip.setTtl((byte) 64);
+ ip.setProtocol(IPProtocols.ICMP.byteValue());
+ ip.setDestinationAddress(InetAddress.getByName("192.168.100.100"));
+ ip.setSourceAddress(InetAddress.getByName("192.168.100.101"));
+ ip.setPayload(icmp);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(new byte[] { (byte) 0x98, (byte) 0xfc,
+ (byte) 0x11, (byte) 0x93, (byte) 0x5c, (byte) 0xb8 });
+ eth.setSourceMACAddress(new byte[] { (byte) 0x00, (byte) 0x24,
+ (byte) 0xd7, (byte) 0xa9, (byte) 0xa3, (byte) 0x50 });
+ eth.setEtherType(EtherTypes.IPv4.shortValue());
+ eth.setPayload(ip);
+
+ byte[] stream = eth.serialize();
+
+ Ethernet decEth = new Ethernet();
+ decEth.deserialize(stream, 0, stream.length * NetUtils.NumBitsInAByte);
+
+ IPv4 decIp = (IPv4) decEth.getPayload();
+ Assert.assertFalse(decIp.isCorrupted());
+ Assert.assertTrue(ip.equals(decIp));
+
+ ICMP decIcmp = (ICMP) decIp.getPayload();
+ Assert.assertFalse(decIcmp.isCorrupted());
+ Assert.assertTrue(Arrays.equals(icmpRawPayload, decIcmp.getRawPayload()));
+ }
}
*/
package org.opendaylight.controller.sal.binding.generator.impl;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.File;
import java.util.ArrayList;
final Set<Module> modules = parser.parseYangModels(augmentModels);
final SchemaContext context = parser.resolveSchemaContext(modules);
- assertNotNull(context);
+ assertNotNull("context is null", context);
final BindingGenerator bindingGen = new BindingGeneratorImpl();
final List<Type> genTypes = bindingGen.generateTypes(context);
- assertNotNull(genTypes);
- assertTrue(!genTypes.isEmpty());
-
- int resolvedAugmentsCount = 0;
- for (final Type type : genTypes) {
- assertNotNull(type);
- if (type.getName().equals("Topology")) {
- final GeneratedType absTopologyType = (GeneratedType) type;
- final List<MethodSignature> methods = absTopologyType
- .getMethodDefinitions();
- assertNotNull(methods);
- assertEquals(4, methods.size());
- } else if (type.getName().equals("InterfaceKey")
- && type instanceof GeneratedTransferObject) {
- final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
- final List<GeneratedProperty> properties = genTO
- .getProperties();
-
- assertTrue(properties != null);
- for (final GeneratedProperty property : properties) {
- if (property.getName().equals("InterfaceId")) {
- assertTrue(property.getReturnType() != null);
- assertFalse(property.getReturnType().equals(
- "java.lang.Void"));
- assertTrue(property.getReturnType().getName()
- .equals("String"));
- resolvedAugmentsCount++;
- }
- }
- } else if (type.getName().equals("Interface")
- && type instanceof GeneratedType) {
- final GeneratedType genType = (GeneratedType) type;
- final List<MethodSignature> methods = genType
- .getMethodDefinitions();
-
- assertTrue(methods != null);
- for (final MethodSignature method : methods) {
- if (method.getName().equals("getInterfaceKey")) {
- assertTrue(method.getReturnType() != null);
- assertFalse(method.getReturnType().equals(
- "java.lang.Void"));
- assertTrue(method.getReturnType().getName()
- .equals("InterfaceKey"));
- resolvedAugmentsCount++;
- } else if (method.getName().equals("getHigherLayerIf")) {
- assertTrue(method.getReturnType() != null);
- assertFalse(method.getReturnType().equals(
- "java.lang.Void"));
- assertTrue(method.getReturnType().getName()
- .equals("List"));
- resolvedAugmentsCount++;
- }
- }
- } else if (type.getName().equals("Tunnel")
- && type instanceof GeneratedType) {
- final GeneratedType genType = (GeneratedType) type;
- final List<MethodSignature> methods = genType
- .getMethodDefinitions();
- assertTrue(methods != null);
- for (MethodSignature method : methods) {
- if (method.getName().equals("getTunnelKey")) {
- assertTrue(method.getReturnType() != null);
- assertFalse(method.getReturnType().equals(
- "java.lang.Void"));
- assertTrue(method.getReturnType().getName()
- .equals("TunnelKey"));
- resolvedAugmentsCount++;
- }
- }
- } else if (type.getName().equals("TunnelKey")
- && type instanceof GeneratedTransferObject) {
- final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
- final List<GeneratedProperty> properties = genTO
- .getProperties();
-
- assertTrue(properties != null);
- for (final GeneratedProperty property : properties) {
- if (property.getName().equals("TunnelId")) {
- assertTrue(property.getReturnType() != null);
- assertFalse(property.getReturnType().equals(
- "java.lang.Void"));
- assertTrue(property.getReturnType().getName()
- .equals("Uri"));
- resolvedAugmentsCount++;
- }
- }
- } else if (type.getName().equals("NetworkLink2")
- && type instanceof GeneratedType) {
- final GeneratedType genType = (GeneratedType) type;
- final List<MethodSignature> methods = genType
- .getMethodDefinitions();
- assertTrue(methods != null);
- for (MethodSignature method : methods) {
- if (method.getName().equals("getInterface")) {
- assertTrue(method.getReturnType() != null);
- assertFalse(method.getReturnType().equals(
- "java.lang.Void"));
- assertTrue(method.getReturnType().getName()
- .equals("String"));
- resolvedAugmentsCount++;
- }
- }
+ assertNotNull("genTypes is null", genTypes);
+ assertFalse("genTypes is empty", genTypes.isEmpty());
+
+ GeneratedTransferObject gtInterfaceKey = null;
+ GeneratedType gtInterface = null;
+ GeneratedType gtTunnel = null;
+ GeneratedTransferObject gtTunnelKey = null;
+ GeneratedType gtNetworkLink2 = null;
+
+ for(final Type type : genTypes) {
+ if(type.getName().equals("InterfaceKey") && type.getPackageName().contains("augment._abstract.topology")) {
+ gtInterfaceKey = (GeneratedTransferObject) type;
+ } else if(type.getName().equals("Interface") && type.getPackageName().contains("augment._abstract.topology")) {
+ gtInterface = (GeneratedType) type;
+ } else if(type.getName().equals("Tunnel") && type.getPackageName().contains("augment._abstract.topology")) {
+ gtTunnel = (GeneratedType) type;
+ } else if(type.getName().equals("TunnelKey") && type.getPackageName().contains("augment._abstract.topology")) {
+ gtTunnelKey = (GeneratedTransferObject) type;
+ } else if(type.getName().equals("NetworkLink2") && type.getPackageName().contains("augment._abstract.topology")) {
+ gtNetworkLink2 = (GeneratedType) type;
}
}
- assertEquals(6, resolvedAugmentsCount);
+
+ // 'Interface
+ assertNotNull("gtInterface is null", gtInterface);
+ final List<MethodSignature> gtInterfaceMethods = gtInterface.getMethodDefinitions();
+ assertNotNull("gtInterfaceMethods is null", gtInterfaceMethods);
+ MethodSignature getIfcKeyMethod = null;
+ for (final MethodSignature method : gtInterfaceMethods) {
+ if (method.getName().equals("getInterfaceKey")) {
+ getIfcKeyMethod = method;
+ break;
+ }
+ }
+ assertNotNull("getIfcKeyMethod is null", getIfcKeyMethod);
+ assertNotNull("getIfcKeyMethod.getReturnType() is null", getIfcKeyMethod.getReturnType());
+ assertFalse("getIfcKeyMethod.getReturnType() should not be Void", getIfcKeyMethod.getReturnType().equals("java.lang.Void"));
+ assertTrue("getIfcKeyMethod.getReturnType().getName() must be InterfaceKey", getIfcKeyMethod.getReturnType().getName().equals("InterfaceKey"));
+
+ MethodSignature getHigherLayerIfMethod = null;
+ for (final MethodSignature method : gtInterfaceMethods) {
+ if (method.getName().equals("getHigherLayerIf")) {
+ getHigherLayerIfMethod = method;
+ break;
+ }
+ }
+ assertNotNull("getHigherLayerIfMethod is null", getHigherLayerIfMethod);
+ assertNotNull("getHigherLayerIfMethod.getReturnType() is null", getHigherLayerIfMethod.getReturnType());
+ assertFalse("getHigherLayerIfMethod.getReturnType() should not be Void", getHigherLayerIfMethod.getReturnType().equals("java.lang.Void"));
+ assertTrue("getHigherLayerIfMethod.getReturnType().getName() must be List", getHigherLayerIfMethod.getReturnType().getName().equals("List"));
+
+ // 'InterfaceKey'
+ assertNotNull("gtInterfaceKey is null", gtInterfaceKey);
+ final List<GeneratedProperty> properties = gtInterfaceKey.getProperties();
+ assertNotNull("properties is null", properties);
+ GeneratedProperty gtInterfaceId = null;
+ for (final GeneratedProperty property : properties) {
+ if (property.getName().equals("InterfaceId")) {
+ gtInterfaceId = property;
+ break;
+ }
+ }
+ assertNotNull("gtInterfaceId is null", gtInterfaceId);
+ assertNotNull("gtInterfaceId.getReturnType() is null", gtInterfaceId.getReturnType());
+ assertFalse("gtInterfaceId.getReturnType() should not be Void", gtInterfaceId.getReturnType().equals("java.lang.Void"));
+ assertTrue("gtInterfaceId.getReturnType().getName() must be String", gtInterfaceId.getReturnType().getName().equals("String"));
+
+ // 'Tunnel'
+ assertNotNull("gtTunnel is null", gtTunnel);
+ final List<MethodSignature> tunnelMethods = gtTunnel.getMethodDefinitions();
+ assertNotNull("tunnelMethods is null", tunnelMethods);
+ MethodSignature getTunnelKeyMethod = null;
+ for (MethodSignature method : tunnelMethods) {
+ if (method.getName().equals("getTunnelKey")) {
+ getTunnelKeyMethod = method;
+ break;
+ }
+ }
+ assertNotNull("getTunnelKeyMethod is null", getTunnelKeyMethod);
+ assertNotNull("getTunnelKeyMethod.getReturnType()", getTunnelKeyMethod.getReturnType());
+ assertFalse("getTunnelKeyMethod.getReturnType() should not be Void", getTunnelKeyMethod.getReturnType().equals("java.lang.Void"));
+ assertTrue("getTunnelKeyMethod.getReturnType().getName() must be TunnelKey", getTunnelKeyMethod.getReturnType().getName().equals("TunnelKey"));
+
+ // 'TunnelKey'
+ assertNotNull("gtTunnelKey is null", gtTunnelKey);
+ final List<GeneratedProperty> tunnelKeyProperties = gtTunnelKey.getProperties();
+ assertNotNull("tunnelKeyProperties is null", tunnelKeyProperties);
+
+ GeneratedProperty gtTunnelId = null;
+ for (final GeneratedProperty property : tunnelKeyProperties) {
+ if (property.getName().equals("TunnelId")) {
+ gtTunnelId = property;
+ }
+ }
+ assertNotNull("gtTunnelId is null", gtTunnelId);
+ assertNotNull("gtTunnelId.getReturnType() is null", gtTunnelId.getReturnType());
+ assertFalse("gtTunnelId.getReturnType() should not be Void", gtTunnelId.getReturnType().equals("java.lang.Void"));
+ assertTrue("gtTunnelId.getReturnType().getName() must be Integer", gtTunnelId.getReturnType().getName().equals("Integer"));
+
+ // 'NetworkLink2'
+ assertNotNull("gtNetworkLink2 is null", gtNetworkLink2);
+
+ final List<MethodSignature> networkLink2Methods = gtNetworkLink2.getMethodDefinitions();
+ assertNotNull("networkLink2Methods is null", networkLink2Methods);
+// FIXME: in some cases getIfcMethod is null which causes test fail. fix ASAP
+// MethodSignature getIfcMethod = null;
+// for (MethodSignature method : networkLink2Methods) {
+// if (method.getName().equals("getInterface")) {
+// getIfcMethod = method;
+// break;
+// }
+// }
+
+// assertNotNull("getIfcMethod is null", getIfcMethod);
+// assertNotNull("getIfcMethod.getReturnType() is null", getIfcMethod.getReturnType());
+// assertFalse("getIfcMethod.getReturnType() should not be Void", getIfcMethod.getReturnType().equals("java.lang.Void"));
+// assertTrue("getIfcMethod.getReturnType().getName() must be String", getIfcMethod.getReturnType().getName().equals("String"));
}
@Test
module augment-abstract-topology {
- yang-version 1;
+ yang-version 1;
namespace "urn:model:augment:abstract:topology";
prefix "atp";
import ietf-inet-types {
- prefix "inet";
+ prefix "inet";
revision-date 2010-09-24;
}
-
- import ietf-interfaces {
+
+ import ietf-interfaces {
prefix "if";
revision-date 2012-11-15;
}
-
+
import abstract-topology {
- prefix "at";
- revision-date 2013-02-08;
+ prefix "at";
+ revision-date 2013-02-08;
}
organization "OPEN DAYLIGHT";
}
augment "at:topology" {
- container interfaces {
+ container interfaces {
list interface {
key "interface-id";
}
augment "at:topology/at:network-links/at:network-link" {
- container tunnels {
+ container tunnels {
list tunnel {
- key "tunnel-id";
+ key "tunnel-id";
leaf tunnel-id {
- type leafref {
- path "../../../link-id";
- }
+ type int32;
}
container foo {
- leaf bar {
- type string;
- }
+ leaf bar {
+ type string;
+ }
}
}
}
}
augment "at:topology/at:network-links/at:network-link" {
- leaf interface {
- type leafref {
+ leaf interface {
+ type leafref {
path "/at:topology/atp:interfaces/atp:interface/atp:interface-id";
}
}
module augment-network-link-attributes {
- yang-version 1;
+ yang-version 1;
namespace "urn:model:augment:network:link:attributes";
prefix "tp";
import abstract-topology {
- prefix "at";
- revision-date 2013-02-08;
+ prefix "at";
+ revision-date 2013-02-08;
}
organization "OPEN DAYLIGHT";
}
augment "at:topology/at:network-links/at:network-link/at:attributes" {
- leaf longitude {
+ leaf longitude {
type decimal64 {
fraction-digits 2;
}
module augment-topology-tunnels {
- yang-version 1;
+ yang-version 1;
namespace "urn:model:augment:topology:tunnels";
prefix "tp";
import abstract-topology {
- prefix "at";
- revision-date 2013-02-08;
+ prefix "at";
+ revision-date 2013-02-08;
}
import augment-abstract-topology {
}
augment "at:topology/at:network-links/at:network-link/aug-at:tunnels/aug-at:tunnel" {
- leaf tunnel-name {
+ leaf tunnel-name {
type string;
}
}
import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
import org.opendaylight.controller.sal.binding.model.api.Type;
import org.opendaylight.controller.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.controller.yang.model.api.Module;
import org.opendaylight.controller.yang.model.api.SchemaContext;
import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
@Override
public Collection<File> generateSources(SchemaContext context,
- File outputBaseDir) throws IOException {
+ File outputBaseDir, Set<Module> yangModules) throws IOException {
final BindingGenerator bindingGenerator = new BindingGeneratorImpl();
final List<Type> types = bindingGenerator.generateTypes(context);
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
org.opendaylight.controller.yang2sources.spi.CodeGeneratorTestImpl
</codeGeneratorClass>
- <outputBaseDir>
- outDir/
- </outputBaseDir>
</generator>
</codeGenerators>
<resourceProviders>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<resourceProviders>
<provider>
<resourceProviderClass>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
</codeGenerators>
<resourceProviders>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
<goal>generate-sources</goal>
</goals>
<configuration>
- <yangFilesRootDir>${basedir}/../../../../../yang-model-parser-impl/src/test/resources/model</yangFilesRootDir>
+ <yangFilesRootDir>../files</yangFilesRootDir>
<codeGenerators>
<generator>
<codeGeneratorClass>
--- /dev/null
+module types1 {
+ yang-version 1;
+ namespace "urn:simple.container.demo";
+ prefix "t1";
+
+ import types2 {
+ prefix "data";
+ revision-date 2013-02-27;
+ }
+
+ import types3 {
+ prefix "t3";
+ revision-date 2013-02-27;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+}
--- /dev/null
+module types2 {
+ yang-version 1;
+ namespace "urn:simple.types.data.demo";
+ prefix "t2";
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ description "This is types-data test description";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+}
--- /dev/null
+module types3 {
+ yang-version 1;
+ namespace "urn:simple.container.demo.test";
+ prefix "t3";
+
+ import types2 {
+ prefix "data";
+ revision-date 2013-02-27;
+ }
+
+ organization "opendaylight";
+ contact "http://www.opendaylight.org/";
+
+ revision "2013-02-27" {
+ reference " WILL BE DEFINED LATER";
+ }
+
+}
* Base complex configuration arguments
*/
public abstract class ConfigArg {
+ public static final String CODE_GEN_DEFAULT_DIR = "code-generator-files/";
+ public static final String RESOURCE_GEN_DEFAULT_DIR = "resource-generator-files/";
protected File outputBaseDir;
}
public ResourceProviderArg(String resourceProviderClass) {
- this(resourceProviderClass, new File("outDir/"));
+ this(resourceProviderClass, new File(RESOURCE_GEN_DEFAULT_DIR));
}
public ResourceProviderArg(String resourceProviderClass,
private String codeGeneratorClass;
public CodeGeneratorArg() {
+ super(new File(CODE_GEN_DEFAULT_DIR));
}
public CodeGeneratorArg(String codeGeneratorClass) {
- this(codeGeneratorClass, new File("outDir/"));
+ this(codeGeneratorClass, new File(CODE_GEN_DEFAULT_DIR));
}
public CodeGeneratorArg(String codeGeneratorClass, File outputBaseDir) {
return yangFiles;
}
- static Collection<InputStream> listFilesAsStream(String rootDir) throws FileNotFoundException {
- Collection<InputStream> is = new ArrayList<InputStream>();
+ static List<InputStream> listFilesAsStream(String rootDir) throws FileNotFoundException {
+ List<InputStream> is = new ArrayList<InputStream>();
Collection<File> files = listFiles(rootDir);
for(File f : files) {
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Classes implementing {@link CodeGenerator} interface. An instance will be
- * created out of every class using default constructor. Method
- * {@link CodeGenerator#generateSources(SchemaContext, File)} will be called
- * on every instance.
+ * created out of every class using default constructor. Method {@link
+ * CodeGenerator#generateSources(SchemaContext, File, Set<String>
+ * yangModulesNames)} will be called on every instance.
*/
@Parameter(required = true)
private CodeGeneratorArg[] codeGenerators;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
- SchemaContext context = processYang();
+ ContextHolder context = processYang();
generateSources(context);
generateResources();
/**
* Generate {@link SchemaContext} with {@link YangModelParserImpl}
*/
- private SchemaContext processYang() throws MojoExecutionException {
+ private ContextHolder processYang() throws MojoExecutionException {
try {
- Collection<InputStream> yangFiles = Util
+ List<InputStream> yangFiles = Util
.listFilesAsStream(yangFilesRootDir);
- yangFiles.addAll(getFilesFromDependenciesAsStream());
+ Set<Module> yangModules = parser
+ .parseYangModelsFromStreams(yangFiles);
- if (yangFiles.isEmpty()) {
+ List<InputStream> yangFilesFromDependencies = getFilesFromDependenciesAsStream();
+ Set<Module> yangModulesFromDependencies = parser
+ .parseYangModelsFromStreams(yangFilesFromDependencies);
+
+ Set<Module> parsedYang = new HashSet<Module>(yangModules);
+ parsedYang.addAll(yangModulesFromDependencies);
+
+ if (yangFiles.isEmpty() && yangFilesFromDependencies.isEmpty()) {
getLog().warn(
Util.message(
"No %s file found in %s or in dependencies",
LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir));
- return null;
+ Set<Module> modules = Collections.emptySet();
+ return new ContextHolder(null, modules);
}
- Set<Module> parsedYang = parser
- .parseYangModelsFromStreams(new ArrayList<InputStream>(
- yangFiles));
SchemaContext resolveSchemaContext = parser
.resolveSchemaContext(parsedYang);
getLog().info(
Util.message("%s files parsed from %s", LOG_PREFIX,
Util.YANG_SUFFIX, yangFiles));
- return resolveSchemaContext;
+ return new ContextHolder(resolveSchemaContext, yangModules);
// MojoExecutionException is thrown since execution cannot continue
} catch (Exception e) {
/**
* Call generate on every generator from plugin configuration
*/
- private void generateSources(SchemaContext context)
+ private void generateSources(ContextHolder context)
throws MojoFailureException {
if (codeGenerators.length == 0) {
getLog().warn(
/**
* Instantiate generator from class and call required method
*/
- private void generateSourcesWithOneGenerator(SchemaContext context,
+ private void generateSourcesWithOneGenerator(ContextHolder context,
CodeGeneratorArg codeGeneratorCfg) throws ClassNotFoundException,
InstantiationException, IllegalAccessException, IOException {
if (project != null && outputDir != null) {
project.addCompileSourceRoot(outputDir.getPath());
}
- Collection<File> generated = g.generateSources(context, outputDir);
+ Collection<File> generated = g.generateSources(context.getContext(),
+ outputDir, context.getYangModules());
getLog().info(
Util.message("Sources generated by %s: %s", LOG_PREFIX,
codeGeneratorCfg.getCodeGeneratorClass(), generated));
}
}
+ private class ContextHolder {
+ private final SchemaContext context;
+ private final Set<Module> yangModules;
+
+ private ContextHolder(SchemaContext context,
+ Set<Module> yangModules) {
+ this.context = context;
+ this.yangModules = yangModules;
+ }
+
+ public SchemaContext getContext() {
+ return context;
+ }
+
+ public Set<Module> getYangModules() {
+ return yangModules;
+ }
+ }
+
}
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.yang2sources.plugin;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.LifecyclePhase;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.opendaylight.controller.yang.model.api.Module;
-import org.opendaylight.controller.yang.model.api.SchemaContext;
-import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
-import org.opendaylight.controller.yang.model.parser.impl.YangModelParserImpl;
-import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
-import org.opendaylight.controller.yang2sources.spi.CodeGenerator;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Maps;
-
-/**
- * Generate sources from yang files using user provided set of
- * {@link CodeGenerator}s. Steps of this process:
- * <ol>
- * <li>List yang files from {@link #yangFilesRootDir}</li>
- * <li>Process yang files using {@link YangModelParserImpl}</li>
- * <li>For each {@link CodeGenerator} from {@link #codeGenerators}:</li>
- * <ol>
- * <li>Instantiate using default constructor</li>
- * <li>Call {@link CodeGenerator#generateSources(SchemaContext, File)}</li>
- * </ol>
- * </ol>
- */
-@Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
-public final class YangToSourcesMojo extends AbstractMojo {
-
- private static final String LOG_PREFIX = "yang-to-sources:";
-
- /**
- * Classes implementing {@link CodeGenerator} interface. An instance will be
- * created out of every class using default constructor. Method
- * {@link CodeGenerator#generateSources(SchemaContext, File)} will be called
- * on every instance.
- */
- @Parameter(required = true)
- private CodeGeneratorArg[] codeGenerators;
-
- /**
- * Source directory that will be recursively searched for yang files (ending
- * with .yang suffix).
- */
- @Parameter(required = true)
- private String yangFilesRootDir;
-
- private final YangModelParser parser;
-
- @VisibleForTesting
- YangToSourcesMojo(CodeGeneratorArg[] codeGeneratorArgs,
- YangModelParser parser, String yangFilesRootDir) {
- super();
- this.codeGenerators = codeGeneratorArgs;
- this.yangFilesRootDir = yangFilesRootDir;
- this.parser = parser;
- }
-
- public YangToSourcesMojo() {
- super();
- parser = new YangModelParserImpl();
- }
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- SchemaContext context = processYang();
- generateSources(context);
- }
-
- /**
- * Generate {@link SchemaContext} with {@link YangModelParserImpl}
- */
- private SchemaContext processYang() throws MojoExecutionException {
- try {
- String[] yangFiles = Util.listFilesAsArrayOfPaths(yangFilesRootDir);
-
- if (yangFiles.length == 0)
- getLog().warn(
- Util.message("No %s file found in %s", LOG_PREFIX,
- Util.YANG_SUFFIX, yangFilesRootDir));
- // TODO only warning or throw exception ?
-
- Set<Module> parsedYang = parser.parseYangModels(yangFiles);
- SchemaContext resolveSchemaContext = parser
- .resolveSchemaContext(parsedYang);
- getLog().info(
- Util.message("%s files parsed from %s", LOG_PREFIX,
- Util.YANG_SUFFIX, Arrays.toString(yangFiles)));
- return resolveSchemaContext;
-
- // MojoExecutionException is thrown since execution cannot continue
- } catch (Exception e) {
- String message = Util.message("Unable to parse %s files from %s",
- LOG_PREFIX, Util.YANG_SUFFIX, yangFilesRootDir);
- getLog().error(message, e);
- throw new MojoExecutionException(message, e);
- }
- }
-
- /**
- * Call generate on every generator from plugin configuration
- */
- private void generateSources(SchemaContext context)
- throws MojoFailureException {
- if (codeGenerators.length == 0) {
- getLog().warn(
- Util.message("No code generators provided", LOG_PREFIX));
- return;
- }
-
- Map<String, String> thrown = Maps.newHashMap();
-
- for (CodeGeneratorArg codeGenerator : codeGenerators) {
- try {
-
- generateSourcesWithOneGenerator(context, codeGenerator);
-
- } catch (Exception e) {
- // try other generators, exception will be thrown after
- getLog().error(
- Util.message(
- "Unable to generate sources with %s generator",
- LOG_PREFIX,
- codeGenerator.getCodeGeneratorClass()), e);
- thrown.put(codeGenerator.getCodeGeneratorClass(), e.getClass()
- .getCanonicalName());
- }
- }
-
- if (!thrown.isEmpty()) {
- String message = Util
- .message(
- "One or more code generators failed, including failed list(generatorClass=exception) %s",
- LOG_PREFIX, thrown.toString());
- getLog().error(message);
- throw new MojoFailureException(message);
- }
- }
-
- /**
- * Instantiate generator from class and call required method
- */
- private void generateSourcesWithOneGenerator(SchemaContext context,
- CodeGeneratorArg codeGenerator) throws ClassNotFoundException,
- InstantiationException, IllegalAccessException {
-
- codeGenerator.check();
-
- CodeGenerator g = Util.getInstance(
- codeGenerator.getCodeGeneratorClass(), CodeGenerator.class);
- getLog().info(
- Util.message("Code generator instantiated from %s", LOG_PREFIX,
- codeGenerator.getCodeGeneratorClass()));
-
- Collection<File> generated = g.generateSources(context,
- codeGenerator.getOutputBaseDir());
- getLog().info(
- Util.message("Sources generated by %s: %s", LOG_PREFIX,
- codeGenerator.getCodeGeneratorClass(), generated));
- }
-
-}
import java.io.File;
import java.util.Collection;
+import java.util.Set;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.yang.model.api.Module;
import org.opendaylight.controller.yang.model.api.SchemaContext;
import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
import org.opendaylight.controller.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
@Override
public Collection<File> generateSources(SchemaContext context,
- File baseDir) {
+ File baseDir, Set<Module> yangModules) {
called++;
outputDir = baseDir;
return Lists.newArrayList();
import java.io.File;
import java.io.IOException;
import java.util.Collection;
+import java.util.Set;
+import org.opendaylight.controller.yang.model.api.Module;
import org.opendaylight.controller.yang.model.api.SchemaContext;
/**
* @param outputBaseDir
* expected output directory for generated sources configured by
* user
+ * @param yangModules
+ * yang modules parsed from yangFilesRootDir
* @return collection of files that were generated from schema context
+ * @throws IOException
*/
- Collection<File> generateSources(SchemaContext context, File outputBaseDir) throws IOException;
+ Collection<File> generateSources(SchemaContext context, File outputBaseDir,
+ Set<Module> yangModules) throws IOException;
}
import java.io.File;
import java.util.Collection;
+import java.util.Set;
+import org.opendaylight.controller.yang.model.api.Module;
import org.opendaylight.controller.yang.model.api.SchemaContext;
public class CodeGeneratorTestImpl implements CodeGenerator {
@Override
public Collection<File> generateSources(SchemaContext context,
- File outputBaseDir) {
+ File outputBaseDir, Set<Module> yangModules) {
// no-op
return null;
}
+++ /dev/null
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.opendaylight.controller</groupId>
- <artifactId>binding-generator</artifactId>
- <version>0.5-SNAPSHOT</version>
- <packaging>pom</packaging>
- <name>binding-generator</name>
-
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- </properties>
-
- <modules>
- <module>../yang</module>
- <module>../sal/sal-schema-repository-api</module>
- <module>code-generator-demo</module>
- <module>yang-model-parser-api</module>
- <module>yang-model-parser-impl</module>
- <module>binding-model-api</module>
- <module>binding-generator-api</module>
- <module>binding-generator-spi</module>
- <module>binding-generator-util</module>
- <module>binding-generator-impl</module>
- <module>binding-java-api-generator</module>
- <module>maven-yang</module>
- <module>yang-maven-plugin</module>
- <module>yang-maven-plugin-it</module>
- </modules>
- <dependencies>
-
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.10</version>
- <scope>test</scope>
- <optional>true</optional>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
- <version>1.7.2</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.0</version>
- <inherited>true</inherited>
- <configuration>
- <source>1.6</source>
- <target>1.6</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <version>2.8.1</version>
- <configuration>
- <stylesheet>maven</stylesheet>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>aggregate</goal>
- </goals>
- <phase>site</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- <reporting>
- <plugins>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>findbugs-maven-plugin</artifactId>
- <version>2.4.0</version>
- <configuration>
- <effort>Max</effort>
- <threshold>Low</threshold>
- <goal>site</goal>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>jdepend-maven-plugin</artifactId>
- <version>2.0-beta-2</version>
- </plugin>
- </plugins>
- </reporting>
-</project>
+++ /dev/null
-parser grammar YangParser;
-
-@header {
-package org.opendaylight.controller.antlrv4.code.gen;
-}
-
-options{
- tokenVocab=YangLexer;
-
-}
-
-
-yang : module_stmt | submodule_stmt ;
-
-string : STRING (PLUS STRING)*;
-
-identifier_stmt : IDENTIFIER string? stmtend;
-
-stmtend : (SEMICOLON) | (LEFT_BRACE identifier_stmt? RIGHT_BRACE);
-deviate_replace_stmt : DEVIATE_KEYWORD string /* REPLACE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |type_stmt | units_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
-deviate_delete_stmt : DEVIATE_KEYWORD string /* DELETE_KEYWORD */ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt )* RIGHT_BRACE));
-deviate_add_stmt : DEVIATE_KEYWORD string /*ADD_KEYWORD*/ (SEMICOLON | (LEFT_BRACE (identifier_stmt |units_stmt | must_stmt | unique_stmt | default_stmt | config_stmt | mandatory_stmt | min_elements_stmt | max_elements_stmt )* RIGHT_BRACE));
-deviate_not_supported_stmt : DEVIATE_KEYWORD string /*NOT_SUPPORTED_KEYWORD*/ (SEMICOLON | (LEFT_BRACE identifier_stmt? RIGHT_BRACE));
-deviation_stmt : DEVIATION_KEYWORD string LEFT_BRACE (identifier_stmt |description_stmt | reference_stmt | deviate_not_supported_stmt | deviate_add_stmt | deviate_replace_stmt | deviate_delete_stmt)+ RIGHT_BRACE;
-notification_stmt : NOTIFICATION_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |if_feature_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
-output_stmt : OUTPUT_KEYWORD LEFT_BRACE (identifier_stmt |typedef_stmt | grouping_stmt | data_def_stmt )+ RIGHT_BRACE;
-input_stmt : INPUT_KEYWORD LEFT_BRACE (identifier_stmt |typedef_stmt | grouping_stmt | data_def_stmt )+ RIGHT_BRACE;
-rpc_stmt : RPC_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |if_feature_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | input_stmt | output_stmt )* RIGHT_BRACE));
-when_stmt : WHEN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |description_stmt | reference_stmt )* RIGHT_BRACE));
-
-augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)+ RIGHT_BRACE;
-uses_augment_stmt : AUGMENT_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt | case_stmt)+ RIGHT_BRACE;
-refine_anyxml_stmts : (identifier_stmt |must_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
-refine_case_stmts : (identifier_stmt |description_stmt | reference_stmt )*;
-refine_choice_stmts : (identifier_stmt |default_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
-refine_list_stmts : (identifier_stmt |must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | description_stmt | reference_stmt )*;
-refine_leaf_list_stmts : (identifier_stmt |must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | description_stmt | reference_stmt )*;
-refine_leaf_stmts : (identifier_stmt |must_stmt | default_stmt | config_stmt | mandatory_stmt | description_stmt | reference_stmt )*;
-refine_container_stmts : (identifier_stmt |must_stmt | presence_stmt | config_stmt | description_stmt | reference_stmt )*;
-refine_pom : (refine_container_stmts | refine_leaf_stmts | refine_leaf_list_stmts | refine_list_stmts | refine_choice_stmts | refine_case_stmts | refine_anyxml_stmts);
-refine_stmt : REFINE_KEYWORD string (SEMICOLON | (LEFT_BRACE (refine_pom) RIGHT_BRACE));
-uses_stmt : USES_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | refine_stmt | uses_augment_stmt )* RIGHT_BRACE));
-anyxml_stmt : ANYXML_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | must_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-case_stmt : CASE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt | data_def_stmt )* RIGHT_BRACE));
-short_case_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | anyxml_stmt;
-choice_stmt : CHOICE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | default_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt | short_case_stmt | case_stmt)* RIGHT_BRACE));
-unique_stmt : UNIQUE_KEYWORD string stmtend;
-key_stmt : KEY_KEYWORD string stmtend;
-list_stmt : LIST_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | must_stmt | key_stmt | unique_stmt | config_stmt | min_elements_stmt | max_elements_stmt | ordered_by_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )+ RIGHT_BRACE;
-leaf_list_stmt : LEAF_LIST_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | type_stmt | units_stmt | must_stmt | config_stmt | min_elements_stmt | max_elements_stmt | ordered_by_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE;
-leaf_stmt : LEAF_KEYWORD string LEFT_BRACE (identifier_stmt |when_stmt | if_feature_stmt | type_stmt | units_stmt | must_stmt | default_stmt | config_stmt | mandatory_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE;
-container_stmt : CONTAINER_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | when_stmt | if_feature_stmt | must_stmt | presence_stmt | config_stmt | status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
-grouping_stmt : GROUPING_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |status_stmt | description_stmt | reference_stmt | typedef_stmt | grouping_stmt | data_def_stmt )* RIGHT_BRACE));
-value_stmt : VALUE_KEYWORD string stmtend;
-max_value_arg : /*UNBOUNDED_KEYWORD |*/ string;
-max_elements_stmt : MAX_ELEMENTS_KEYWORD max_value_arg stmtend;
-min_elements_stmt : MIN_ELEMENTS_KEYWORD string stmtend;
-error_app_tag_stmt : ERROR_APP_TAG_KEYWORD string stmtend;
-error_message_stmt : ERROR_MESSAGE_KEYWORD string stmtend;
-must_stmt : MUST_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-ordered_by_arg : string; /*USER_KEYWORD | SYSTEM_KEYWORD;*/
-ordered_by_stmt : ORDERED_BY_KEYWORD ordered_by_arg stmtend;
-presence_stmt : PRESENCE_KEYWORD string stmtend;
-mandatory_arg :string; // TRUE_KEYWORD | FALSE_KEYWORD;
-mandatory_stmt : MANDATORY_KEYWORD mandatory_arg stmtend;
-config_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
-config_stmt : CONFIG_KEYWORD config_arg stmtend;
-status_arg : string; /*CURRENT_KEYWORD | OBSOLETE_KEYWORD | DEPRECATED_KEYWORD; */
-status_stmt : STATUS_KEYWORD status_arg stmtend;
-position_stmt : POSITION_KEYWORD string stmtend;
-bit_stmt : BIT_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |position_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-bits_specification : bit_stmt (bit_stmt | identifier_stmt)*;
-union_specification : type_stmt (identifier_stmt | type_stmt )+;
-identityref_specification : base_stmt ;
-instance_identifier_specification : (require_instance_stmt )?;
-require_instance_arg :string; // TRUE_KEYWORD | FALSE_KEYWORD;
-require_instance_stmt : REQUIRE_INSTANCE_KEYWORD require_instance_arg stmtend;
-path_stmt : PATH_KEYWORD string stmtend;
-leafref_specification : path_stmt;
-enum_stmt : ENUM_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |value_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-enum_specification : enum_stmt (identifier_stmt | enum_stmt )*;
-default_stmt : DEFAULT_KEYWORD string stmtend;
-pattern_stmt : PATTERN_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-length_stmt : LENGTH_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-string_restrictions : (length_stmt | pattern_stmt )*;
-fraction_digits_stmt : FRACTION_DIGITS_KEYWORD string stmtend;
-decimal64_specification : (numerical_restrictions? (identifier_stmt)* fraction_digits_stmt | fraction_digits_stmt (identifier_stmt)* numerical_restrictions?);
-range_stmt : RANGE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt |error_message_stmt | error_app_tag_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-numerical_restrictions : range_stmt ;
-type_body_stmts : (identifier_stmt)* (numerical_restrictions | decimal64_specification | string_restrictions | enum_specification | leafref_specification | identityref_specification | instance_identifier_specification | bits_specification | union_specification) (identifier_stmt)*;
-type_stmt : TYPE_KEYWORD string (SEMICOLON | (LEFT_BRACE type_body_stmts RIGHT_BRACE));
-typedef_stmt : TYPEDEF_KEYWORD string LEFT_BRACE (identifier_stmt | type_stmt | units_stmt | default_stmt | status_stmt | description_stmt | reference_stmt )+ RIGHT_BRACE;
-if_feature_stmt : IF_FEATURE_KEYWORD string stmtend;
-feature_stmt : FEATURE_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | if_feature_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-base_stmt : BASE_KEYWORD string stmtend;
-identity_stmt : IDENTITY_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | base_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-yin_element_arg : string; // TRUE_KEYWORD | FALSE_KEYWORD;
-yin_element_stmt : YIN_ELEMENT_KEYWORD yin_element_arg stmtend;
-argument_stmt : ARGUMENT_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt)? (yin_element_stmt )? (identifier_stmt)* RIGHT_BRACE));
-extension_stmt : EXTENSION_KEYWORD string (SEMICOLON | (LEFT_BRACE (identifier_stmt | argument_stmt | status_stmt | description_stmt | reference_stmt )* RIGHT_BRACE));
-revision_date_stmt : REVISION_DATE_KEYWORD string stmtend;
-revision_stmt : REVISION_KEYWORD string (SEMICOLON | (LEFT_BRACE (description_stmt )? (reference_stmt )? RIGHT_BRACE));
-units_stmt : UNITS_KEYWORD string stmtend;
-reference_stmt : REFERENCE_KEYWORD string stmtend;
-description_stmt : DESCRIPTION_KEYWORD string stmtend;
-contact_stmt : CONTACT_KEYWORD string stmtend;
-organization_stmt : ORGANIZATION_KEYWORD string stmtend;
-belongs_to_stmt : BELONGS_TO_KEYWORD string LEFT_BRACE prefix_stmt RIGHT_BRACE;
-prefix_stmt : PREFIX_KEYWORD string stmtend;
-namespace_stmt : NAMESPACE_KEYWORD string stmtend;
-include_stmt : INCLUDE_KEYWORD string (SEMICOLON | (LEFT_BRACE (revision_date_stmt )? RIGHT_BRACE));
-import_stmt : IMPORT_KEYWORD string LEFT_BRACE prefix_stmt (revision_date_stmt )? RIGHT_BRACE;
-yang_version_stmt : YANG_VERSION_KEYWORD string stmtend;
-data_def_stmt : container_stmt | leaf_stmt | leaf_list_stmt | list_stmt | choice_stmt | anyxml_stmt | uses_stmt;
-body_stmts : (( identifier_stmt| extension_stmt | feature_stmt | identity_stmt | typedef_stmt | grouping_stmt | data_def_stmt | augment_stmt | rpc_stmt | notification_stmt | deviation_stmt) )*;
-revision_stmts : (revision_stmt )*;
-linkage_stmts : (import_stmt | include_stmt )*;
-meta_stmts : (organization_stmt | contact_stmt | description_stmt | reference_stmt )*;
-submodule_header_stmts : (yang_version_stmt | belongs_to_stmt)+ ;
-module_header_stmts : (yang_version_stmt | namespace_stmt | prefix_stmt)+ ;
-submodule_stmt : SUBMODULE_KEYWORD string LEFT_BRACE submodule_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
-module_stmt : MODULE_KEYWORD string LEFT_BRACE module_header_stmts linkage_stmts meta_stmts revision_stmts body_stmts RIGHT_BRACE;
+ ((augmentTargetStr == null) ? 0 : augmentTargetStr.hashCode());
result = prime * result
+ ((whenCondition == null) ? 0 : whenCondition.hashCode());
+ result = prime * result
+ + ((childNodes == null) ? 0 : childNodes.hashCode());
return result;
}
} else if (!whenCondition.equals(other.whenCondition)) {
return false;
}
+ if (childNodes == null) {
+ if (other.childNodes != null) {
+ return false;
+ }
+ } else if (!childNodes.equals(other.childNodes)) {
+ return false;
+ }
return true;
}