package com.limegroup.gnutella;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* This class defines the types of URNs supported in the application and
* provides utility functions for handling urn types.
*
* @see URN
* @see UrnCache
*/
public class UrnType implements Serializable {
private static final long serialVersionUID = -8211681448456483713L;
/**
* Identifier string for the SHA1 type.
*/
public static final String SHA1_STRING = "sha1:";
/**
* Identifier string for the BITPRINT type.
*/
public static final String BITPRINT_STRING = "bitprint:";
/**
* The <tt>UrnType</tt> for an invalid UrnType.
*/
public static final UrnType INVALID = new UrnType("invalid");
/**
* The <tt>UrnType</tt> for SHA1 hashes.
*/
public static final UrnType SHA1 = new UrnType(SHA1_STRING);
/**
* The <tt>UrnType</tt> for bitprint hashes.
*/
public static final UrnType BITPRINT = new UrnType(BITPRINT_STRING);
/**
* The <tt>UrnType</tt> for specifying any URN type.
*/
public static final UrnType ANY_TYPE = new UrnType("");
/**
* Constant for specifying SHA1 URNs in replies.
*/
public static transient final Set SHA1_SET = new HashSet();
/**
* Constant for specifying any type of URN for replies.
*/
public static transient final Set ANY_TYPE_SET = new HashSet();
/**
* Statically add the SHA1 type to the set.
*/
static {
SHA1_SET.add(UrnType.SHA1);
ANY_TYPE_SET.add(UrnType.ANY_TYPE);
}
/**
* Constant for the leading URN string identifier, as specified in
* RFC 2141. This is equal to "urn:", although note that this
* should be used in a case-insensitive manner in compliance with
* the URN specification (RFC 2141).
*/
public static final String URN_NAMESPACE_ID = "urn:";
/**
* Constant string for the URN type. INVARIANT: this cannot be null
*/
private transient String _urnType;
/**
* Private constructor ensures that this class can never be constructed
* from outside the class. This assigns the _urnType string.
*
* @param typeString the string representation of the URN type
* @throws <tt>NullPointerException</tt> if the <tt>typeString</tt>
* argument is <tt>null</tt>
*/
private UrnType(String typeString) {
if(typeString == null) {
throw new NullPointerException("UrnTypes cannot except null strings");
}
_urnType = typeString;
}
/**
* Returns whether or not this URN type is SHA1.
*
* @return <tt>true</tt> if this is a SHA1 URN type, <tt>false</tt>
* otherwise
*/
public boolean isSHA1() {
return _urnType.equals(SHA1_STRING);
}
/**
* Returns the string representation of this URN type.
*
* @return the string representation of this URN type
*/
public String toString() {
return URN_NAMESPACE_ID+_urnType;
}
/**
* It is necessary for this class to override equals because the
* readResolve method was not added to the serialization API until
* Java 1.2, which means that we cannot use it to ensure that the
* <tt>UrnType</tt> enum constants are actually the same instances upon
* deserialization. Therefore, we must rely on Object.equals instead
* of upon "==".
*
* @param o the <tt>Object</tt> to compare for equality
* @return <tt>true</tt> if these represent the same UrnType, <tt>false</tt>
* otherwise
* @see java.lang.Object#equals(Object)
*/
public boolean equals(Object o) {
if(o == this) return true;
if(!(o instanceof UrnType)) return false;
UrnType type = (UrnType)o;
return _urnType.equals(type._urnType);
}
/**
* Overridden to meet the contract of Object.hashCode.
*
* @return the unique hashcode for this <tt>UrnType</tt>, in accordance with
* Object.equals
* @see java.lang.Object#hashCode
*/
public int hashCode() {
int result = 17;
result = 37*result + _urnType.hashCode();
return result;
}
/**
* Serializes this instance.
*
* @serialData the string representation of the URN type
*/
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
s.writeObject(_urnType);
}
/**
* Deserializes this <tt>UrnType</tt> instance, validating the input string.
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
_urnType = (String)s.readObject();
if(!_urnType.equals("") &&
!_urnType.equals(SHA1_STRING) &&
!_urnType.equals(BITPRINT_STRING)) {
throw new InvalidObjectException("invalid urn type: "+_urnType);
}
}
/**
* Factory method for obtaining <tt>UrnType</tt> instances from strings.
* If the isSupportedUrnType method returns <tt>true</tt> this is
* guaranteed to return a non-null UrnType.
*
* @param type the string representation of the urn type
* @return the <tt>UrnType</tt> instance corresponding with the specified
* string, or <tt>null</tt> if the type is not supported
*/
public static UrnType createUrnType(String type) {
String lowerCaseType = type.toLowerCase().trim();
if(lowerCaseType.equals(SHA1.toString())) {
return SHA1;
} else if(lowerCaseType.equals(ANY_TYPE.toString())) {
return ANY_TYPE;
} else if(lowerCaseType.equals(BITPRINT.toString())) {
return BITPRINT;
} else {
return null;
}
}
/**
* Returns whether or not the string argument is a urn type that
* we know about.
*
* @param urnString to string to check
* @return <tt>true</tt> if it is a valid URN type, <tt>false</tt>
* otherwise
*/
public static boolean isSupportedUrnType(final String urnString) {
UrnType type = UrnType.createUrnType(urnString);
if(type == null) return false;
return true;
}
}