First pass at a new naming system. Probably the last as well. So sad :).
This commit is contained in:
59
core/java/src/net/i2p/client/naming/AddressDB.java
Normal file
59
core/java/src/net/i2p/client/naming/AddressDB.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package net.i2p.client.naming;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.data.Address;
|
||||||
|
|
||||||
|
public abstract class AddressDB {
|
||||||
|
|
||||||
|
private final static Log _log = new Log(NamingService.class);
|
||||||
|
protected I2PAppContext _context;
|
||||||
|
|
||||||
|
/** what classname should be used as the address db impl? */
|
||||||
|
public static final String PROP_IMPL = "i2p.addressdb.impl";
|
||||||
|
private static final String DEFAULT_IMPL = "net.i2p.client.naming.FilesystemAddressDB";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address db should only be constructed and accessed through the
|
||||||
|
* application context. This constructor should only be used by the
|
||||||
|
* appropriate application context itself.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected AddressDB(I2PAppContext context) {
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AddressDB() { // nop
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an address db instance. This method ensures that there
|
||||||
|
* will be only one address db instance (singleton) as well as
|
||||||
|
* choose the implementation from the "i2p.addressdb.impl" system
|
||||||
|
* property.
|
||||||
|
*/
|
||||||
|
public static final synchronized AddressDB createInstance(I2PAppContext context) {
|
||||||
|
AddressDB instance = null;
|
||||||
|
String impl = context.getProperty(PROP_IMPL, DEFAULT_IMPL);
|
||||||
|
try {
|
||||||
|
Class cls = Class.forName(impl);
|
||||||
|
Constructor con = cls.getConstructor(new Class[] { I2PAppContext.class });
|
||||||
|
instance = (AddressDB)con.newInstance(new Object[] { context });
|
||||||
|
} catch (Exception ex) {
|
||||||
|
_log.error("Cannot load address db implementation", ex);
|
||||||
|
instance = new DummyAddressDB(context); // fallback
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Address get(String hostname);
|
||||||
|
public abstract Address put(Address address);
|
||||||
|
public abstract Address remove(String hostname);
|
||||||
|
public abstract Address remove(Address address);
|
||||||
|
public abstract boolean contains(Address address);
|
||||||
|
public abstract boolean contains(String hostname);
|
||||||
|
public abstract Collection hostnames();
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package net.i2p.client.naming;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.Destination;
|
||||||
|
import net.i2p.data.Address;
|
||||||
|
|
||||||
|
public class AddressDBNamingService extends NamingService {
|
||||||
|
|
||||||
|
private AddressDB _addressdb;
|
||||||
|
|
||||||
|
public AddressDBNamingService(I2PAppContext context) {
|
||||||
|
super(context);
|
||||||
|
_addressdb = AddressDB.createInstance(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AddressDBNamingService() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Destination lookup(String hostname) {
|
||||||
|
Address addr = _addressdb.get(hostname);
|
||||||
|
if (addr != null) {
|
||||||
|
return addr.getDestination();
|
||||||
|
} else {
|
||||||
|
// If we can't find hostname in the addressdb, assume it's a key.
|
||||||
|
return lookupBase64(hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String reverseLookup(Destination dest) {
|
||||||
|
Iterator iter = _addressdb.hostnames().iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Address addr = _addressdb.get((String)iter.next());
|
||||||
|
if (addr != null && addr.getDestination().equals(dest)) {
|
||||||
|
return addr.getHostname();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
42
core/java/src/net/i2p/client/naming/DummyAddressDB.java
Normal file
42
core/java/src/net/i2p/client/naming/DummyAddressDB.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package net.i2p.client.naming;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.Address;
|
||||||
|
|
||||||
|
public class DummyAddressDB extends AddressDB {
|
||||||
|
|
||||||
|
public DummyAddressDB(I2PAppContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address get(String hostname) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address put(Address address) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address remove(String hostname) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address remove(Address address) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Address address) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String hostname) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection hostnames() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
118
core/java/src/net/i2p/client/naming/FilesystemAddressDB.java
Normal file
118
core/java/src/net/i2p/client/naming/FilesystemAddressDB.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package net.i2p.client.naming;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.data.Address;
|
||||||
|
import net.i2p.data.DataFormatException;
|
||||||
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
public class FilesystemAddressDB extends AddressDB {
|
||||||
|
|
||||||
|
public final static String PROP_ADDRESS_DIR = "i2p.addressdir";
|
||||||
|
public final static String DEFAULT_ADDRESS_DIR = "addressDb";
|
||||||
|
private final static Log _log = new Log(FilesystemAddressDB.class);
|
||||||
|
|
||||||
|
public FilesystemAddressDB(I2PAppContext context) {
|
||||||
|
super(context);
|
||||||
|
|
||||||
|
//If the address db directory doesn't exist, create it, using the
|
||||||
|
//contents of hosts.txt.
|
||||||
|
String dir = _context.getProperty(PROP_ADDRESS_DIR, DEFAULT_ADDRESS_DIR);
|
||||||
|
File addrDir = new File(dir);
|
||||||
|
if (!addrDir.exists()) {
|
||||||
|
addrDir.mkdir();
|
||||||
|
Properties hosts = new Properties();
|
||||||
|
File hostsFile = new File("hosts.txt");
|
||||||
|
if (hostsFile.exists() && hostsFile.canRead()) {
|
||||||
|
try {
|
||||||
|
DataHelper.loadProps(hosts, hostsFile);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
_log.error("Error loading hosts file " + hostsFile, ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iterator iter = hosts.keySet().iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
String hostname = (String)iter.next();
|
||||||
|
Address addr = new Address();
|
||||||
|
addr.setHostname(hostname);
|
||||||
|
addr.setDestination(hosts.getProperty(hostname));
|
||||||
|
put(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address get(String hostname) {
|
||||||
|
String dir = _context.getProperty(PROP_ADDRESS_DIR, DEFAULT_ADDRESS_DIR);
|
||||||
|
File f = new File(dir, hostname);
|
||||||
|
if (f.exists() && f.canRead()) {
|
||||||
|
Address addr = new Address();
|
||||||
|
try {
|
||||||
|
addr.readBytes(new FileInputStream(f));
|
||||||
|
} catch (FileNotFoundException exp) {
|
||||||
|
return null;
|
||||||
|
} catch (DataFormatException exp) {
|
||||||
|
_log.error(f.getPath() + " is not a valid address file.");
|
||||||
|
return null;
|
||||||
|
} catch (IOException exp) {
|
||||||
|
_log.error("Error reading " + f.getPath());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
} else {
|
||||||
|
_log.warn(f.getPath() + " does not exist.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address put(Address address) {
|
||||||
|
Address previous = get(address.getHostname());
|
||||||
|
|
||||||
|
String dir = _context.getProperty(PROP_ADDRESS_DIR, DEFAULT_ADDRESS_DIR);
|
||||||
|
File f = new File(dir, address.getHostname());
|
||||||
|
try {
|
||||||
|
address.writeBytes(new FileOutputStream(f));
|
||||||
|
} catch (Exception exp) {
|
||||||
|
_log.error("Error writing " + f.getPath(), exp);
|
||||||
|
}
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address remove(String hostname) {
|
||||||
|
Address previous = get(hostname);
|
||||||
|
|
||||||
|
String dir = _context.getProperty(PROP_ADDRESS_DIR, DEFAULT_ADDRESS_DIR);
|
||||||
|
File f = new File(dir, hostname);
|
||||||
|
f.delete();
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address remove(Address address) {
|
||||||
|
if (contains(address)) {
|
||||||
|
return remove(address.getHostname());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Address address) {
|
||||||
|
Address inDb = get(address.getHostname());
|
||||||
|
return inDb.equals(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(String hostname) {
|
||||||
|
return hostnames().contains(hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection hostnames() {
|
||||||
|
String dir = _context.getProperty(PROP_ADDRESS_DIR, DEFAULT_ADDRESS_DIR);
|
||||||
|
File f = new File(dir);
|
||||||
|
return Arrays.asList(f.list());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
81
core/java/src/net/i2p/data/Address.java
Normal file
81
core/java/src/net/i2p/data/Address.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package net.i2p.data;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
|
public class Address extends DataStructureImpl {
|
||||||
|
private final static Log _log = new Log(Address.class);
|
||||||
|
private String _hostname;
|
||||||
|
private Destination _destination;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
_hostname = null;
|
||||||
|
_destination = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHostname() {
|
||||||
|
return _hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHostname(String hostname) {
|
||||||
|
_hostname = hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Destination getDestination() {
|
||||||
|
return _destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination(Destination destination) {
|
||||||
|
_destination = destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDestination(String base64) {
|
||||||
|
try {
|
||||||
|
Destination result = new Destination();
|
||||||
|
result.fromBase64(base64);
|
||||||
|
_destination = result;
|
||||||
|
} catch (DataFormatException dfe) {
|
||||||
|
_destination = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readBytes(InputStream in) throws DataFormatException,
|
||||||
|
IOException {
|
||||||
|
_hostname = DataHelper.readString(in);
|
||||||
|
_destination = new Destination();
|
||||||
|
_destination.readBytes(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeBytes(OutputStream out) throws DataFormatException,
|
||||||
|
IOException {
|
||||||
|
if ((_hostname == null) || (_destination == null))
|
||||||
|
throw new DataFormatException("Not enough data to write address");
|
||||||
|
DataHelper.writeString(out, _hostname);
|
||||||
|
_destination.writeBytes(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if ((obj == null) || !(obj instanceof Address)) return false;
|
||||||
|
Address addr = (Address) obj;
|
||||||
|
return DataHelper.eq(_hostname, addr.getHostname())
|
||||||
|
&& DataHelper.eq(_destination, addr.getDestination());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return DataHelper.hashCode(getHostname())
|
||||||
|
+ DataHelper.hashCode(getDestination());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buf = new StringBuffer(64);
|
||||||
|
buf.append("[Address: ");
|
||||||
|
buf.append("\n\tHostname: ").append(getHostname());
|
||||||
|
buf.append("\n\tDestination: ").append(getDestination());
|
||||||
|
buf.append("]");
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user