vendorspecificattribute.java

来自「TinyRadius is a simple, small and fast J」· Java 代码 · 共 343 行

JAVA
343
字号
/**
 * $Id: VendorSpecificAttribute.java,v 1.7 2005/11/22 10:18:38 wuttke Exp $
 * Created on 10.04.2005
 * @author Matthias Wuttke
 * @version $Revision: 1.7 $
 */
package org.tinyradius.attribute;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.tinyradius.dictionary.AttributeType;
import org.tinyradius.dictionary.Dictionary;
import org.tinyradius.util.RadiusException;

/**
 * This class represents a "Vendor-Specific" attribute.
 */
public class VendorSpecificAttribute extends RadiusAttribute {

	/**
	 * Radius attribute type code for Vendor-Specific
	 */
	public static final int VENDOR_SPECIFIC = 26;

	/**
	 * Constructs an empty Vendor-Specific attribute that can be read from a
	 * Radius packet.
	 */
	public VendorSpecificAttribute() {
		super();
	}

	/**
	 * Constructs a new Vendor-Specific attribute to be sent.
	 * @param vendorId vendor ID of the sub-attributes
	 */
	public VendorSpecificAttribute(int vendorId) {
		setAttributeType(VENDOR_SPECIFIC);
		setChildVendorId(vendorId);
	}

	/**
	 * Sets the vendor ID of the child attributes.
	 * @param childVendorId
	 */
	public void setChildVendorId(int childVendorId) {
		this.childVendorId = childVendorId;
	}

	/**
	 * Returns the vendor ID of the sub-attributes.
	 * @return vendor ID of sub attributes
	 */
	public int getChildVendorId() {
		return childVendorId;
	}

	/**
	 * Also copies the new dictionary to sub-attributes.
	 * @param dictionary dictionary to set
	 * @see org.tinyradius.attribute.RadiusAttribute#setDictionary(org.tinyradius.dictionary.Dictionary)
	 */
	public void setDictionary(Dictionary dictionary) {
		super.setDictionary(dictionary);
		for (Iterator i = subAttributes.iterator(); i.hasNext();) {
			RadiusAttribute attr = (RadiusAttribute) i.next();
			attr.setDictionary(dictionary);
		}
	}

	/**
	 * Adds a sub-attribute to this attribute.
	 * @param attribute sub-attribute to add
	 */
	public void addSubAttribute(RadiusAttribute attribute) {
		if (attribute.getVendorId() != getChildVendorId())
			throw new IllegalArgumentException(
					"sub attribut has incorrect vendor ID");

		subAttributes.add(attribute);
	}

	/**
	 * Adds a sub-attribute with the specified name to this attribute.
	 * @param name name of the sub-attribute
	 * @param value value of the sub-attribute
	 * @exception IllegalArgumentException invalid sub-attribute name or value
	 */
	public void addSubAttribute(String name, String value) {
		if (name == null || name.length() == 0)
			throw new IllegalArgumentException("type name is empty");
		if (value == null || value.length() == 0)
			throw new IllegalArgumentException("value is empty");

		AttributeType type = getDictionary().getAttributeTypeByName(name);
		if (type == null)
			throw new IllegalArgumentException("unknown attribute type '"
					+ name + "'");
		if (type.getVendorId() == -1)
			throw new IllegalArgumentException("attribute type '" + name
					+ "' is not a Vendor-Specific sub-attribute");
		if (type.getVendorId() != getChildVendorId())
			throw new IllegalArgumentException("attribute type '" + name
					+ "' does not belong to vendor ID " + getChildVendorId());

		RadiusAttribute attribute = createRadiusAttribute(getDictionary(),
				getChildVendorId(), type.getTypeCode());
		attribute.setAttributeValue(value);
		addSubAttribute(attribute);
	}

	/**
	 * Removes the specified sub-attribute from this attribute.
	 * @param attribute RadiusAttribute to remove
	 */
	public void removeSubAttribute(RadiusAttribute attribute) {
		if (!subAttributes.remove(attribute))
			throw new IllegalArgumentException("no such attribute");
	}

	/**
	 * Returns the list of sub-attributes.
	 * @return List of RadiusAttribute objects
	 */
	public List getSubAttributes() {
		return subAttributes;
	}

	/**
	 * Returns all sub-attributes of this attribut which have the given type.
	 * @param attributeType type of sub-attributes to get
	 * @return list of RadiusAttribute objects, does not return null
	 */
	public List getSubAttributes(int attributeType) {
		if (attributeType < 1 || attributeType > 255)
			throw new IllegalArgumentException(
					"sub-attribute type out of bounds");

		LinkedList result = new LinkedList();
		for (Iterator i = subAttributes.iterator(); i.hasNext();) {
			RadiusAttribute a = (RadiusAttribute) i.next();
			if (attributeType == a.getAttributeType())
				result.add(a);
		}
		return result;
	}

	/**
	 * Returns a sub-attribute of the given type which may only occur once in
	 * this attribute.
	 * @param type sub-attribute type
	 * @return RadiusAttribute object or null if there is no such sub-attribute
	 * @throws RuntimeException if there are multiple occurences of the
	 * requested sub-attribute type
	 */
	public RadiusAttribute getSubAttribute(int type) {
		List attrs = getSubAttributes(type);
		if (attrs.size() > 1)
			throw new RuntimeException(
					"multiple sub-attributes of requested type " + type);
		else if (attrs.size() == 0)
			return null;
		else
			return (RadiusAttribute) attrs.get(0);
	}

	/**
	 * Returns a single sub-attribute of the given type name.
	 * @param type attribute type name
	 * @return RadiusAttribute object or null if there is no such attribute
	 * @throws RuntimeException if the attribute occurs multiple times
	 */
	public RadiusAttribute getSubAttribute(String type) throws RadiusException {
		if (type == null || type.length() == 0)
			throw new IllegalArgumentException("type name is empty");

		AttributeType t = getDictionary().getAttributeTypeByName(type);
		if (t == null)
			throw new IllegalArgumentException("unknown attribute type name '"
					+ type + "'");
		if (t.getVendorId() != getChildVendorId())
			throw new IllegalArgumentException("vendor ID mismatch");

		return getSubAttribute(t.getTypeCode());
	}

	/**
	 * Returns the value of the Radius attribute of the given type or null if
	 * there is no such attribute.
	 * @param type attribute type name
	 * @return value of the attribute as a string or null if there is no such
	 * attribute
	 * @throws IllegalArgumentException if the type name is unknown
	 * @throws RuntimeException attribute occurs multiple times
	 */
	public String getSubAttributeValue(String type) throws RadiusException {
		RadiusAttribute attr = getSubAttribute(type);
		if (attr == null)
			return null;
		else
			return attr.getAttributeValue();
	}

	/**
	 * Renders this attribute as a byte array.
	 * @see org.tinyradius.attribute.RadiusAttribute#writeAttribute()
	 */
	public byte[] writeAttribute() {
		// write vendor ID
		ByteArrayOutputStream bos = new ByteArrayOutputStream(255);
		bos.write(getChildVendorId() >> 24 & 0x0ff);
		bos.write(getChildVendorId() >> 16 & 0x0ff);
		bos.write(getChildVendorId() >> 8 & 0x0ff);
		bos.write(getChildVendorId() & 0x0ff);

		// write sub-attributes
		try {
			for (Iterator i = subAttributes.iterator(); i.hasNext();) {
				RadiusAttribute a = (RadiusAttribute) i.next();
				bos.write(a.writeAttribute());
			}
		} catch (IOException ioe) {
			// occurs never
			throw new RuntimeException("error writing data", ioe);
		}

		// check data length
		byte[] attrData = bos.toByteArray();
		int len = attrData.length;
		if (len > 253)
			throw new RuntimeException("Vendor-Specific attribute too long: "
					+ bos.size());

		// compose attribute
		byte[] attr = new byte[len + 2];
		attr[0] = VENDOR_SPECIFIC; // code
		attr[1] = (byte) (len + 2); // length
		System.arraycopy(attrData, 0, attr, 2, len);
		return attr;
	}

	/**
	 * Reads a Vendor-Specific attribute and decodes the internal sub-attribute
	 * structure.
	 * @see org.tinyradius.attribute.RadiusAttribute#readAttribute(byte[], int,
	 * int)
	 */
	public void readAttribute(byte[] data, int offset, int length)
			throws RadiusException {
		// check length
		if (length < 6)
			throw new RadiusException("Vendor-Specific attribute too short: "
					+ length);

		int vsaCode = data[offset];
		int vsaLen = ((int) data[offset + 1] & 0x000000ff) - 6;

		if (vsaCode != VENDOR_SPECIFIC)
			throw new RadiusException("not a Vendor-Specific attribute");

		// read vendor ID and vendor data
		/*
		 * int vendorId = (data[offset + 2] << 24 | data[offset + 3] << 16 |
		 * data[offset + 4] << 8 | ((int)data[offset + 5] & 0x000000ff));
		 */
		int vendorId = (unsignedByteToInt(data[offset + 2]) << 24
				| unsignedByteToInt(data[offset + 3]) << 16
				| unsignedByteToInt(data[offset + 4]) << 8 | unsignedByteToInt(data[offset + 5]));
		setChildVendorId(vendorId);

		// validate sub-attribute structure
		int pos = 0;
		int count = 0;
		while (pos < vsaLen) {
			if (pos + 1 >= vsaLen)
				throw new RadiusException("Vendor-Specific attribute malformed");
			// int vsaSubType = data[(offset + 6) + pos] & 0x0ff;
			int vsaSubLen = data[(offset + 6) + pos + 1] & 0x0ff;
			pos += vsaSubLen;
			count++;
		}
		if (pos != vsaLen)
			throw new RadiusException("Vendor-Specific attribute malformed");

		subAttributes = new ArrayList(count);
		pos = 0;
		while (pos < vsaLen) {
			int subtype = data[(offset + 6) + pos] & 0x0ff;
			int sublength = data[(offset + 6) + pos + 1] & 0x0ff;
			RadiusAttribute a = createRadiusAttribute(getDictionary(),
					vendorId, subtype);
			a.readAttribute(data, (offset + 6) + pos, sublength);
			subAttributes.add(a);
			pos += sublength;
		}
	}

	private static int unsignedByteToInt(byte b) {
		return (int) b & 0xFF;
	}

	/**
	 * Returns a string representation for debugging.
	 * @see org.tinyradius.attribute.RadiusAttribute#toString()
	 */
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("Vendor-Specific: ");
		int vendorId = getChildVendorId();
		String vendorName = getDictionary().getVendorName(vendorId);
		if (vendorName != null) {
			sb.append(vendorName);
			sb.append(" (");
			sb.append(vendorId);
			sb.append(")");
		} else {
			sb.append("vendor ID ");
			sb.append(vendorId);
		}
		for (Iterator i = getSubAttributes().iterator(); i.hasNext();) {
			RadiusAttribute attr = (RadiusAttribute) i.next();
			sb.append("\n");
			sb.append(attr.toString());
		}
		return sb.toString();
	}

	/**
	 * Sub attributes. Only set if isRawData == false.
	 */
	private List subAttributes = new ArrayList();

	/**
	 * Vendor ID of sub-attributes.
	 */
	private int childVendorId;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?