// ex:sw=3
// ^-- shift-width 4 for vi
package lava.net.common;
import java.net.URL;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Hashtable;
/**
* UNA:
* Description of the logical Name of an Object.
* Format is similar to URL.
* Scheme-Name is psyc://
* Objects might be Servers, Groups, Users, Protocols.
* Servers: resource=null
* Groups: resource begins with '@'
* Users: resource begins with '~'
* Protocols: resource begins with '$'
* Every Object only can have only one UNA.
**/
public class UNA extends java.lang.Object
{
/**
*
**/
private static Hashtable cache = new Hashtable();
/**
*
**/
private static Hashtable revcache = new Hashtable();
/**
*
**/
private static boolean instantiated = false;
/**
* Flag to mark that we're an applet.
**/
private static boolean applet = false;
/**
*
**/
private static String defaultScheme = null;
/**
*
**/
private static Hashtable defaultHost = new Hashtable();
/**
*
**/
private static Hashtable defaultPort = new Hashtable();
/**
*
**/
private static Hashtable defaultProtocol = new Hashtable();
/**
*
**/
private static Hashtable defaultResource = new Hashtable();
/**
*
**/
private String scheme = null;
/**
*
**/
private String host = null;
/**
*
**/
private InetAddress hostCache = null;
/**
*
**/
private int port = -1;
/**
*
**/
private String protocol = null;
/**
*
**/
private String resource = null;
/**
*
**/
private int hashCode = -1;
/**
*
**/
private String string = null;
/**
*
**/
public UNA()
{
instantiated = true;
setScheme(null);
setHost((String)null);
setPort(-1);
setProtocol(null);
setResource(null);
}
/**
*
**/
public UNA(String spec)
{
this ((UNA)null,spec);
}
/**
*
**/
public UNA(UNA base, String spec)
{
this ();
// pre-initialize it with our base
if(base != null)
{
setScheme(base.getScheme());
setHost(base.getHostName());
setPort(base.getPort());
setProtocol(base.getProtocol());
setResource(base.getResource());
}
if(spec == null)
return;
int i, c, limit = spec.length();
int start = 0;
//System.err.println("[ "+spec+" ]");
while((limit > 0) && (spec.charAt(limit - 1) <= ' '))
{
// eliminate trailing whitespace
limit--;
}
while((start < limit) && (spec.charAt(start) <= ' '))
{
// eliminate leading whitespace
start++;
}
// rewritten here by LynX
i = spec.indexOf("//");
if(i == start || (i > start && spec.charAt(i-1) == ':'))
{
if(i > start)
setScheme(spec.substring(start,i-1).toLowerCase());
// jump over "//"
start = i + 2;
}
else
{
// if we got here, there is no hostname:port info
// instead, if it is a web url, there may be ../'s
// which should be applied to the base resource path
// since this is a psyc library, we don't to do that
//
if (spec.charAt(start) == '/') start++;
setResource("/" + spec.substring(start,limit));
return;
}
i = spec.indexOf('/',start);
if(i >= 0)
{
if(limit > i)
setResource(spec.substring(i,limit));
limit = i;
}
i = spec.indexOf(':',start);
if(i >= 0 && i < limit)
{
int j;
for(j = i + 1;j < limit;++j)
if(!Character.isDigit(spec.charAt(j)))
break;
if(j > i + 1)
setPort(Integer.parseInt(spec.substring(i + 1,j)));
if(j < limit)
setProtocol(spec.substring(j,limit));
limit = i;
}
if(limit > start)
setHost(spec.substring(start,limit));
/* if(host == null && resource == null)
{
// special case: no real host given
// parse all the stuff as resource, prepend "/"
setPort(-1);
setProtocol(null);
setResource("/" + spec.substring(start,limit));
} */
}
/**
*
**/
public UNA(String scheme, String host, int port, String protocol, //
String resource)
{
instantiated = true;
setScheme(scheme);
setHost(host);
setPort(port);
setProtocol(protocol);
setResource(resource);
}
/**
*
**/
public UNA(String scheme, InetAddress host, int port, String protocol, //
String resource)
{
instantiated = true;
setScheme(scheme);
setHost(host);
setPort(port);
setProtocol(protocol);
setResource(resource);
}
/**
*
**/
public String getScheme()
{
return scheme != null ? scheme : getDefaultScheme();
}
/**
*
**/
public InetAddress getHost()
{
if(hostCache == null)
hostCache = lookup(getHostName());
return hostCache;
}
/**
*
**/
public String getHostName()
{
return host != null ? host : getDefaultHost(getScheme());
}
/**
*
**/
public String getHostAddress()
{
InetAddress h = getHost();
return h == null ? null : h.getHostAddress();
}
/**
*
**/
public int getPort()
{
return port > 0 ? port : getDefaultPort(getScheme());
}
/**
*
**/
public String getProtocol()
{
return protocol != null ? protocol : getDefaultProtocol(getScheme());
}
/**
*
**/
public String getResource()
{
return resource != null ? resource : getDefaultResource(getScheme());
}
/**
*
**/
protected void setScheme(String newScheme)
{
scheme = newScheme;
}
/**
*
**/
protected void setHost(String newHost)
{
host = newHost;
}
/**
*
**/
protected void setHost(InetAddress newHost)
{
setHost(lookup(newHost));
}
/**
*
**/
protected void setPort(int newPort)
{
port = newPort;
}
/**
*
**/
protected void setProtocol(String newProtocol)
{
protocol = newProtocol;
}
/**
*
**/
protected void setResource(String newResource)
{
if(newResource != null && newResource.length() > 1 && //
newResource.charAt(newResource.length() - 1) != '/')
newResource = newResource + "/";
resource = newResource;
}
/**
*
**/
public boolean equalsInScheme(UNA other)
{
if(other == null)
return false;
String s = getScheme(), os = other.getScheme();
return (s == null || os == null ? s == null && //
os == null : s.toLowerCase().equals(os.toLowerCase()));
}
/**
*
**/
public boolean equalsInHost(UNA other)
{
if(other == null)
return false;
InetAddress h = getHost();
String n;
return (h == null ? (n = getHostName()) == null ? //
other.getHostName() == null : n.equals(other.getHostName()) : //
h.equals(other.getHost()));
}
/**
*
**/
public boolean equalsInPort(UNA other)
{
return (other != null) && (getPort() == other.getPort());
}
/**
*
**/
public boolean equalsInProtocol(UNA other)
{
if(other == null)
return false;
String p = getProtocol(), op = other.getProtocol();
return (p == null || op == null ? //
p == null && op == null : p.equals(op));
}
/**
*
**/
public boolean equalsInResource(UNA other)
{
if(other == null)
return false;
String r = getResource(), or = other.getResource();
return (r == null || or == null ? //
r == null && or == null : r.equals(or));
}
/**
*
**/
public boolean masterInResource(UNA other)
{
if(other == null)
return false;
try
{
String r = getResource(), or = other.getResource();
return (r == null || or == null ? r == null : //
or.indexOf(r) == 0 && (or.charAt(r.length() - 1) == '/' || //
or.charAt(r.length()) == '/'));
}
catch(StringIndexOutOfBoundsException e)
{
// resources are equal
return true;
}
}
/**
*
**/
public boolean master(UNA other)
{
return equalsInHost(other) && //
equalsInPort(other) && //
equalsInProtocol(other) && //
masterInResource(other);
}
/**
*
**/
public boolean equals(Object obj)
{
return (obj instanceof UNA) && //
equalsInScheme((UNA)obj) && //
equalsInHost((UNA)obj) && //
equalsInPort((UNA)obj) && //
equalsInProtocol((UNA)obj) && //
equalsInResource((UNA)obj);
}
/**
*
**/
public int hashCode()
{
if(hashCode == -1)
{
String s = getScheme(), p = getProtocol(), r = getResource();
InetAddress h = getHost();
String n;
hashCode = (s == null ? 0 : s.hashCode()) ^ //
(h == null ? (n = getHostName()) == null ? 0 : n.hashCode() : //
h.hashCode()) ^ getPort() ^ //
(p == null ? 0 : p.hashCode()) ^ //
(r == null ? 0 : r.hashCode());
}
return hashCode;
}
/**
*
**/
public String toString()
{
if(string != null)
return string;
StringBuffer me = new StringBuffer();
String s = getScheme(), p = getProtocol(), //
dp = getDefaultProtocol(s), r = getResource(), h = getHostName();
int po = getPort(), dpo = getDefaultPort(s);
if(s != null)
me.append(s + "://");
if((h != null) && h != null)
me.append(h);
if((po >= 0 || p != null) && (po != dpo || p != dp))
me.append(":");
if(po >= 0 && po != dpo)
me.append(po);
if(p != null && p != dp)
me.append(p);
if(r != null)
me.append(r);
string = me.toString();
return string;
}
/**
*
**/
public static void setDefaults(String scheme, InetAddress host, //
int port, String protocol, String resource)
{
String h = null;
if(host != null)
try
{
h = host.getHostAddress();
}
catch(Exception e)
{
h = null;
}
setDefaults(scheme,h,port,protocol,resource);
}
/**
*
**/
public static void setDefaults(String scheme, String host, //
int port, String protocol, String resource)
{
if(instantiated || scheme == null)
return;
if(defaultScheme == null)
defaultScheme = scheme;
scheme = scheme.toLowerCase();
if(host != null && defaultHost.get(scheme) == null)
defaultHost.put(scheme,host);
if(port > 0 && defaultPort.get(scheme) == null)
defaultPort.put(scheme,new Integer(port));
if(protocol != null && defaultProtocol.get(scheme) == null)
defaultProtocol.put(scheme,protocol);
if(resource != null && defaultResource.get(scheme) == null)
defaultResource.put(scheme,resource);
}
/**
*
**/
public static String getDefaultScheme()
{
return defaultScheme;
}
/**
*
**/
public static String getDefaultHost(String scheme)
{
if(scheme == null)
return null;
return (String)defaultHost.get(scheme.toLowerCase());
}
/**
*
**/
public static int getDefaultPort(String scheme)
{
if(scheme == null)
return -1;
Integer port = (Integer)defaultPort.get(scheme.toLowerCase());
if(port == null)
return -1;
return port.intValue();
}
/**
*
**/
public static int getDefaultPort()
{
return getDefaultPort(getDefaultScheme());
}
/**
*
**/
public static String getDefaultProtocol(String scheme)
{
if(scheme == null)
return null;
return (String)defaultProtocol.get(scheme.toLowerCase());
}
/**
*
**/
public static String getDefaultProtocol()
{
return getDefaultProtocol(getDefaultScheme());
}
/**
*
**/
public static String getDefaultResource(String scheme)
{
if(scheme == null)
return null;
return (String)defaultResource.get(scheme.toLowerCase());
}
/**
*
**/
public static String getDefaultResource()
{
return getDefaultResource(getDefaultScheme());
}
/**
*
**/
public static void cache(String name, InetAddress addr)
{
if(name != null && addr != null)
{
cache.put(name,addr);
revcache.put(addr,name);
}
}
/**
*
**/
public static InetAddress lookup(String name)
{
if(name == null)
return null;
InetAddress addr = (InetAddress)cache.get(name);
if(addr == null && !applet)
{
try
{
addr = InetAddress.getByName(name);
cache(name,addr);
}
catch(Exception e)
{
addr = null;
}
}
return addr;
}
/**
*
**/
public static String lookup(InetAddress addr)
{
if(addr == null)
return null;
String name = (String)revcache.get(addr);
if(name == null)
{
if(!applet)
{
try
{
name = addr.getHostName();
if(name != null && name.indexOf('.') < 0)
// refuse the name if it is not fully qualified
name = null;
else
// only cache the name, if it seems to be a fully
// qualified one
cache(name,addr);
}
catch(Exception e)
{
name = null;
}
}
if(name == null)
{
name = addr.getHostAddress();
cache(name,addr);
}
}
return name;
}
/**
*
**/
public static void addAppletHost(String name)
{
applet = false;
lookup(name);
applet = true;
}
/**
*
**/
public static void addAppletHost(InetAddress addr)
{
applet = false;
lookup(addr);
applet = true;
}
/**
*
**/
public static boolean isApplet()
{
return applet;
}
}