Changeset c269546c


Ignore:
Timestamp:
Feb 22, 2011 11:39:51 PM (9 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
a3fb49a
Parents:
258c260
Message:

stub out new API, needs testing

Location:
core/java/src/net/i2p/client/naming
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/client/naming/BlockfileNamingService.java

    r258c260 rc269546c  
    336336    }
    337337   
    338     @Override
    339     public Destination lookup(String hostname) {
     338    public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
    340339        Destination d = super.lookup(hostname);
    341340        if (d != null)
  • core/java/src/net/i2p/client/naming/DummyNamingService.java

    r258c260 rc269546c  
    88package net.i2p.client.naming;
    99
     10import java.util.ArrayList;
     11import java.util.HashMap;
     12import java.util.List;
     13import java.util.Map;
     14import java.util.Properties;
     15
    1016import net.i2p.I2PAppContext;
    1117import net.i2p.data.Destination;
     
    1521 */
    1622class DummyNamingService extends NamingService {
     23    private final Map<String, CacheEntry> _cache;
     24
    1725    private static final int BASE32_HASH_LENGTH = 52;   // 1 + Hash.HASH_LENGTH * 8 / 5
    1826    public final static String PROP_B32 = "i2p.naming.hostsTxt.useB32";
     27    protected static final int CACHE_MAX_SIZE = 16;
     28    public static final int DEST_SIZE = 516;                    // Std. Base64 length (no certificate)
    1929
    2030    /**
     
    2434     *
    2535     */
    26     protected DummyNamingService(I2PAppContext context) { super(context); }
    27     private DummyNamingService() { super(null); }
     36    protected DummyNamingService(I2PAppContext context) {
     37        super(context);
     38        _cache = new HashMap(CACHE_MAX_SIZE);
     39    }
    2840   
    2941    @Override
    30     public Destination lookup(String hostname) {
     42    public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
    3143        Destination d = getCache(hostname);
    3244        if (d != null)
     
    5365        return null;
    5466    }
     67
     68    /**
     69     *  Provide basic caching for the service
     70     *  The service may override the age and/or size limit
     71     */
     72    /** Don't know why a dest would ever change but keep this short anyway */
     73    protected static final long CACHE_MAX_AGE = 7*60*1000;
     74
     75    private class CacheEntry {
     76        public Destination dest;
     77        public long exp;
     78        public CacheEntry(Destination d) {
     79            dest = d;
     80            exp = _context.clock().now() + CACHE_MAX_AGE;
     81        }
     82        public boolean isExpired() {
     83            return exp < _context.clock().now();
     84        }
     85    }
     86
     87    /**
     88     * Clean up when full.
     89     * Don't bother removing old entries unless full.
     90     * Caller must synchronize on _cache.
     91     */
     92    private void cacheClean() {
     93        if (_cache.size() < CACHE_MAX_SIZE)
     94            return;
     95        boolean full = true;
     96        String oldestKey = null;
     97        long oldestExp = Long.MAX_VALUE;
     98        List<String> deleteList = new ArrayList(CACHE_MAX_SIZE);
     99        for (Map.Entry<String, CacheEntry> entry : _cache.entrySet()) {
     100            CacheEntry ce = entry.getValue();
     101            if (ce.isExpired()) {
     102                deleteList.add(entry.getKey());
     103                full = false;
     104                continue;
     105            }
     106            if (oldestKey == null || ce.exp < oldestExp) {
     107                oldestKey = entry.getKey();
     108                oldestExp = ce.exp;
     109            }
     110        }
     111        if (full && oldestKey != null)
     112            deleteList.add(oldestKey);
     113        for (String s : deleteList) {
     114            _cache.remove(s);
     115        }
     116    }
     117
     118    protected void putCache(String s, Destination d) {
     119        if (d == null)
     120            return;
     121        synchronized (_cache) {
     122            _cache.put(s, new CacheEntry(d));
     123            cacheClean();
     124        }
     125    }
     126
     127    protected Destination getCache(String s) {
     128        synchronized (_cache) {
     129            CacheEntry ce = _cache.get(s);
     130            if (ce == null)
     131                return null;
     132            if (ce.isExpired()) {
     133                _cache.remove(s);
     134                return null;
     135            }
     136            return ce.dest;
     137        }
     138    }
     139
     140    /** @since 0.8.5 */
     141    protected void removeCache(String s) {
     142        synchronized (_cache) {
     143            _cache.remove(s);
     144        }
     145    }
     146
     147    /** @since 0.8.1 */
     148    public void clearCache() {
     149        synchronized (_cache) {
     150            _cache.clear();
     151        }
     152    }
    55153}
  • core/java/src/net/i2p/client/naming/EepGetAndAddNamingService.java

    r258c260 rc269546c  
    3131 *
    3232 * @author zzz
     33 * @deprecated use HostsTxtNamingService.put()
    3334 * @since 0.7.9
    3435 */
  • core/java/src/net/i2p/client/naming/EepGetNamingService.java

    r258c260 rc269546c  
    88import java.util.ArrayList;
    99import java.util.List;
     10import java.util.Properties;
    1011import java.util.StringTokenizer;
    1112
     
    2627 * Cannot be used as the only NamingService! Be sure any naming service hosts
    2728 * are in hosts.txt.
     29 * Supports caching, b32, and b64.
    2830 *
    2931 * Sample config to put in configadvanced.jsp (restart required):
     
    3436 *
    3537 */
    36 public class EepGetNamingService extends NamingService {
     38public class EepGetNamingService extends DummyNamingService {
    3739
    3840    private final static String PROP_EEPGET_LIST = "i2p.naming.eepget.list";
     
    6062   
    6163    @Override
    62     public Destination lookup(String hostname) {
    63         // If it's long, assume it's a key.
    64         if (hostname.length() >= DEST_SIZE)
    65             return lookupBase64(hostname);
     64    public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
     65        Destination d = super.lookup(hostname, null, null);
     66        if (d != null)
     67            return d;
    6668
    6769        hostname = hostname.toLowerCase();
    68 
    69         // If you want b32, chain with HostsTxtNamingService
    70         if (hostname.length() == 60 && hostname.endsWith(".b32.i2p"))
    71             return null;
    72 
    73         // check the cache
    74         Destination d = getCache(hostname);
    75         if (d != null)
    76             return d;
    7770
    7871        List URLs = getURLs();
     
    10497
    10598    // FIXME allow larger Dests for non-null Certs
    106     private static final int DEST_SIZE = 516;                    // Std. Base64 length (no certificate)
    10799    private static final int MAX_RESPONSE = DEST_SIZE + 68 + 10; // allow for hostname= and some trailing stuff
    108100    private String fetchAddr(String url, String hostname) {
  • core/java/src/net/i2p/client/naming/ExecNamingService.java

    r258c260 rc269546c  
    66
    77import java.io.InputStream;
     8import java.util.Properties;
    89
    910import net.i2p.I2PAppContext;
     
    2829 * Can be used from MetaNamingService, (e.g. after HostsTxtNamingService),
    2930 * or as the sole naming service.
     31 * Supports caching, b32, and b64.
    3032 *
    3133 * Sample chained config to put in configadvanced.jsp (restart required):
     
    4143 *
    4244 */
    43 public class ExecNamingService extends NamingService {
     45public class ExecNamingService extends DummyNamingService {
    4446
    4547    private final static String PROP_EXEC_CMD = "i2p.naming.exec.command";
     
    6062   
    6163    @Override
    62     public Destination lookup(String hostname) {
    63         // If it's long, assume it's a key.
    64         if (hostname.length() >= DEST_SIZE)
    65             return lookupBase64(hostname);
     64    public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
     65        Destination d = super.lookup(hostname, null, null);
     66        if (d != null)
     67            return d;
    6668
    6769        hostname = hostname.toLowerCase();
    68 
    69         // If you want b32, chain with HostsTxtNamingService
    70         if (hostname.length() == 60 && hostname.endsWith(".b32.i2p"))
    71             return null;
    72 
    73         // check the cache
    74         Destination d = getCache(hostname);
    75         if (d != null)
    76             return d;
    7770
    7871        // lookup
     
    8881
    8982    // FIXME allow larger Dests for non-null Certs
    90     private static final int DEST_SIZE = 516;                    // Std. Base64 length (no certificate)
    9183    private static final int MAX_RESPONSE = DEST_SIZE + 68 + 10; // allow for hostname= and some trailing stuff
    9284    private String fetchAddr(String hostname) {
  • core/java/src/net/i2p/client/naming/HostsTxtNamingService.java

    r258c260 rc269546c  
    88package net.i2p.client.naming;
    99
    10 import java.io.BufferedReader;
    11 import java.io.File;
    12 import java.io.FileInputStream;
    13 import java.io.InputStreamReader;
    14 import java.io.IOException;
    1510import java.util.ArrayList;
    16 import java.util.Iterator;
    1711import java.util.List;
    1812import java.util.Properties;
    19 import java.util.Set;
    2013import java.util.StringTokenizer;
    2114
    2215import net.i2p.I2PAppContext;
    23 import net.i2p.data.DataFormatException;
    24 import net.i2p.data.DataHelper;
    2516import net.i2p.data.Destination;
    26 import net.i2p.data.Hash;
    27 import net.i2p.util.Log;
    2817
    2918/**
    30  * A naming service based on the "hosts.txt" file.
     19 * A naming service based on multiple "hosts.txt" files.
     20 * Supports .b32.i2p and {b64} lookups.
     21 * Supports caching.
     22 * All host names are converted to lower case.
    3123 */
    32 public class HostsTxtNamingService extends DummyNamingService {
     24public class HostsTxtNamingService extends MetaNamingService {
    3325
    3426    /**
     
    3830     *
    3931     */
    40     public HostsTxtNamingService(I2PAppContext context) { super(context); }
    41     private HostsTxtNamingService() { super(null); }
     32    public HostsTxtNamingService(I2PAppContext context) {
     33        super(context, null);
     34        for (String name : getFilenames()) {
     35            addNamingService(new SingleFileNamingService(context, name), false);
     36        }
     37    }
    4238   
    4339    /**
     
    4743    public final static String PROP_HOSTS_FILE = "i2p.hostsfilelist";
    4844
    49     /** default hosts.txt filename */
     45    /** default hosts.txt filenames */
    5046    public final static String DEFAULT_HOSTS_FILE =
    5147        "privatehosts.txt,userhosts.txt,hosts.txt";
    5248
    53     private final static Log _log = new Log(HostsTxtNamingService.class);
    54 
    55     private List getFilenames() {
     49    private List<String> getFilenames() {
    5650        String list = _context.getProperty(PROP_HOSTS_FILE, DEFAULT_HOSTS_FILE);
    5751        StringTokenizer tok = new StringTokenizer(list, ",");
    58         List rv = new ArrayList(tok.countTokens());
     52        List<String> rv = new ArrayList(tok.countTokens());
    5953        while (tok.hasMoreTokens())
    6054            rv.add(tok.nextToken());
     
    6357   
    6458    @Override
    65     public Destination lookup(String hostname) {
    66         Destination d = super.lookup(hostname);
    67         if (d != null)
    68             return d;
    69 
    70         List filenames = getFilenames();
    71         for (int i = 0; i < filenames.size(); i++) {
    72             String hostsfile = (String)filenames.get(i);
    73             try {
    74                 File f = new File(_context.getRouterDir(), hostsfile);
    75                 if ( (f.exists()) && (f.canRead()) ) {
    76                     String key = getKey(f, hostname.toLowerCase());
    77                     if ( (key != null) && (key.trim().length() > 0) ) {
    78                         d = lookupBase64(key);
    79                         putCache(hostname, d);
    80                         return d;
    81                     }
    82                    
    83                 } else {
    84                     _log.warn("Hosts file " + hostsfile + " does not exist.");
    85                 }
    86             } catch (Exception ioe) {
    87                 _log.error("Error loading hosts file " + hostsfile, ioe);
    88             }
    89             // not found, continue to the next file
    90         }
    91         return null;
    92     }
    93    
    94     @Override
    95     public String reverseLookup(Destination dest) {
    96         String destkey = dest.toBase64();
    97         List filenames = getFilenames();
    98         for (int i = 0; i < filenames.size(); i++) {
    99             String hostsfile = (String)filenames.get(i);
    100             Properties hosts = new Properties();
    101             try {
    102                 File f = new File(_context.getRouterDir(), hostsfile);
    103                 if ( (f.exists()) && (f.canRead()) ) {
    104                     DataHelper.loadProps(hosts, f, true);
    105                     Set keyset = hosts.keySet();
    106                     Iterator iter = keyset.iterator();
    107                     while (iter.hasNext()) {
    108                         String host = (String)iter.next();
    109                         String key = hosts.getProperty(host);
    110                         if (destkey.equals(key))
    111                             return host;
    112                     }
    113                 }
    114             } catch (Exception ioe) {
    115                 _log.error("Error loading hosts file " + hostsfile, ioe);
    116             }
    117         }
    118         return null;
     59    public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
     60        // If it's long, assume it's a key.
     61        if (hostname.length() >= DEST_SIZE)
     62            return lookupBase64(hostname);
     63        return super.lookup(hostname.toLowerCase(), lookupOptions, storedOptions);
    11964    }
    12065
    121     /** @deprecated unused */
    12266    @Override
    123     public String reverseLookup(Hash h) {
    124         List filenames = getFilenames();
    125         for (int i = 0; i < filenames.size(); i++) {
    126             String hostsfile = (String)filenames.get(i);
    127             Properties hosts = new Properties();
    128             try {
    129                 File f = new File(_context.getRouterDir(), hostsfile);
    130                 if ( (f.exists()) && (f.canRead()) ) {
    131                     DataHelper.loadProps(hosts, f, true);
    132                     Set keyset = hosts.keySet();
    133                     Iterator iter = keyset.iterator();
    134                     while (iter.hasNext()) {
    135                         String host = (String)iter.next();
    136                         String key = hosts.getProperty(host);
    137                         try {
    138                             Destination destkey = new Destination();
    139                             destkey.fromBase64(key);
    140                             if (h.equals(destkey.calculateHash()))
    141                                 return host;
    142                         } catch (DataFormatException dfe) {}
    143                     }
    144                 }
    145             } catch (Exception ioe) {
    146                 _log.error("Error loading hosts file " + hostsfile, ioe);
    147             }
    148         }
    149         return null;
     67    public boolean put(String hostname, Destination d, Properties options) {
     68        return super.put(hostname.toLowerCase(), d, options);
    15069    }
    15170
    152     /**
    153      *  Better than DataHelper.loadProps(), doesn't load the whole file into memory,
    154      *  and stops when it finds a match.
    155      *
    156      *  @param host lower case
    157      *  @since 0.7.13
    158      */
    159     private static String getKey(File file, String host) throws IOException {
    160         BufferedReader in = null;
    161         try {
    162             in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"), 16*1024);
    163             String line = null;
    164             while ( (line = in.readLine()) != null) {
    165                 if (!line.toLowerCase().startsWith(host + '='))
    166                     continue;
    167                 if (line.indexOf('#') > 0)  // trim off any end of line comment
    168                     line = line.substring(0, line.indexOf('#')).trim();
    169                 int split = line.indexOf('=');
    170                 return line.substring(split+1);   //.trim() ??????????????
    171             }
    172         } finally {
    173             if (in != null) try { in.close(); } catch (IOException ioe) {}
    174         }
    175         return null;
     71    @Override
     72    public boolean putIfAbsent(String hostname, Destination d, Properties options) {
     73        return super.putIfAbsent(hostname.toLowerCase(), d, options);
     74    }
     75
     76    @Override
     77    public boolean remove(String hostname, Properties options) {
     78        return super.remove(hostname.toLowerCase(), options);
    17679    }
    17780}
  • core/java/src/net/i2p/client/naming/MetaNamingService.java

    r258c260 rc269546c  
    33import java.lang.reflect.Constructor;
    44import java.util.ArrayList;
     5import java.util.Collections;
    56import java.util.Iterator;
    67import java.util.List;
     8import java.util.Properties;
    79import java.util.StringTokenizer;
     10import java.util.concurrent.CopyOnWriteArrayList;
    811
    912import net.i2p.I2PAppContext;
    1013import net.i2p.data.Destination;
    1114
    12 public class MetaNamingService extends NamingService {
     15/**
     16 * A naming service of multiple naming services.
     17 * Supports .b32.i2p and {b64} lookups.
     18 * Supports caching.
     19 */
     20public class MetaNamingService extends DummyNamingService {
    1321   
    1422    private final static String PROP_NAME_SERVICES = "i2p.nameservicelist";
    1523    private final static String DEFAULT_NAME_SERVICES =
    16         "net.i2p.client.naming.PetNameNamingService,net.i2p.client.naming.HostsTxtNamingService";
    17     private List _services;
     24        "net.i2p.client.naming.HostsTxtNamingService";
     25
     26    protected final List<NamingService> _services;
    1827   
    1928    public MetaNamingService(I2PAppContext context) {
    2029        super(context);
    21        
    2230        String list = _context.getProperty(PROP_NAME_SERVICES, DEFAULT_NAME_SERVICES);
    2331        StringTokenizer tok = new StringTokenizer(list, ",");
    24         _services = new ArrayList(tok.countTokens());
     32        _services = new CopyOnWriteArrayList();
    2533        while (tok.hasMoreTokens()) {
    2634            try {
    2735                Class cls = Class.forName(tok.nextToken());
    2836                Constructor con = cls.getConstructor(new Class[] { I2PAppContext.class });
    29                 _services.add(con.newInstance(new Object[] { context }));
     37                addNamingService((NamingService)con.newInstance(new Object[] { context }), false);
    3038            } catch (Exception ex) {
    31                 _services.add(new DummyNamingService(context)); // fallback
     39            }
     40        }
     41    }
     42   
     43    /**
     44     *  @param if non-null, services to be added. If null, this will only handle b32 and b64.
     45     *  @since 0.8.5
     46     */
     47    public MetaNamingService(I2PAppContext context, List<NamingService> services) {
     48        super(context);
     49        _services = new CopyOnWriteArrayList();
     50        if (services != null) {
     51            for (NamingService ns : services) {
     52                addNamingService(ns, false);
    3253            }
    3354        }
     
    3556   
    3657    @Override
    37     public Destination lookup(String hostname) {
    38         Iterator iter = _services.iterator();
    39         while (iter.hasNext()) {
    40             NamingService ns = (NamingService)iter.next();
    41             Destination dest = ns.lookup(hostname);
    42             if (dest != null) {
    43                 return dest;
     58    public boolean addNamingService(NamingService ns, boolean head) {
     59        if (head)
     60            _services.add(0, ns);
     61        else
     62            _services.add(ns);
     63        return true;
     64    }
     65
     66    @Override
     67    public List<NamingService> getNamingServices() {
     68        return new Collections.unmodifiableList(_services);
     69    }
     70
     71    @Override
     72    public boolean removeNamingService(NamingService ns) {
     73        return  _services.remove(ns);
     74    }
     75
     76    @Override
     77    public void registerListener(NamingServiceListener nsl) {
     78        for (NamingService ns : _services) {
     79            ns.registerListener(nsl);
     80        }
     81    }
     82
     83    @Override
     84    public void unregisterListener(NamingServiceListener nsl) {
     85        for (NamingService ns : _services) {
     86            ns.unregisterListener(nsl);
     87        }
     88    }
     89
     90    @Override
     91    public Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions) {
     92        Destination d = super.lookup(hostname, null, null);
     93        if (d != null)
     94            return d;
     95
     96        for (NamingService ns : _services) {
     97            d = ns.lookup(hostname, lookupOptions, storedOptions);
     98            if (d != null) {
     99                putCache(hostname, d);
     100                return d;
    44101            }
    45102        }
    46         return lookupBase64(hostname);
     103        return null;
    47104    }
    48105   
    49106    @Override
    50     public String reverseLookup(Destination dest) {
    51         Iterator iter = _services.iterator();
    52         while (iter.hasNext()) {
    53             NamingService ns = (NamingService)iter.next();
    54             String hostname = ns.reverseLookup(dest);
    55             if (hostname != null) {
    56                 return hostname;
     107    public String reverseLookup(Destination dest, Properties options) {
     108        for (NamingService ns : _services) {
     109            String host = ns.reverseLookup(dest, options);
     110            if (host != null) {
     111                return host;
    57112            }
    58113        }
     
    60115    }
    61116
     117    /**
     118     *  Stores in the last service
     119     */
     120    @Override
     121    public boolean put(String hostname, Destination d, Properties options) {
     122        if (_services.isEmpty())
     123            return false;
     124        boolean rv = _services.get(_services.size() - 1).put(hostname, d, options);
     125        // overwrite any previous entry in case it changed
     126        if (rv)
     127            putCache(hostname, d);
     128        return rv;
     129    }
     130
     131    /**
     132     *  Stores in the last service
     133     */
     134    @Override
     135    public boolean putIfAbsent(String hostname, Destination d, Properties options) {
     136        if (_services.isEmpty())
     137            return false;
     138        return _services.get(_services.size() - 1).putIfAbsent(hostname, d, options);
     139    }
     140
     141    /**
     142     *  Removes from all services
     143     */
     144    @Override
     145    public boolean remove(String hostname, Properties options) {
     146        boolean rv = false;
     147        for (NamingService ns : _services) {
     148            if (ns.remove(hostname, options))
     149                rv = true;
     150        }
     151        if (rv)
     152            removeCache(hostname);
     153        return rv;
     154    }
    62155}
  • core/java/src/net/i2p/client/naming/NamingService.java

    r258c260 rc269546c  
    1010import java.lang.reflect.Constructor;
    1111import java.util.ArrayList;
    12 import java.util.HashMap;
     12import java.util.Collections;
    1313import java.util.Iterator;
     14import java.util.List;
    1415import java.util.Map;
     16import java.util.Properties;
     17import java.util.Set;
     18import java.util.concurrent.CopyOnWriteArraySet;
    1519
    1620import net.i2p.I2PAppContext;
     
    2630
    2731    private final static Log _log = new Log(NamingService.class);
    28     protected I2PAppContext _context;
    29     private /* FIXME final FIXME */ HashMap _cache;
     32    protected final I2PAppContext _context;
     33    protected final Set<NamingServiceListener> _listeners;
    3034
    3135    /** what classname should be used as the naming service impl? */
    3236    public static final String PROP_IMPL = "i2p.naming.impl";
    3337    private static final String DEFAULT_IMPL = "net.i2p.client.naming.HostsTxtNamingService";
    34 
    35     protected static final int CACHE_MAX_SIZE = 16;
    36 
    3738   
    3839    /**
     
    4445    protected NamingService(I2PAppContext context) {
    4546        _context = context;
    46         _cache = new HashMap(CACHE_MAX_SIZE);
    47     }
    48     private NamingService() { // nop
     47        _listeners = new CopyOnWriteArraySet();
    4948    }
    5049   
     
    5453     * <code>null</code> if name is unknown.
    5554     */
    56     public abstract Destination lookup(String hostname);
     55    public Destination lookup(String hostname) {
     56        return lookup(hostname, null, null);
     57    }
    5758
    5859    /**
     
    6263     * <code>null</code> if no reverse lookup is possible.
    6364     */
    64     public String reverseLookup(Destination dest) { return null; };
     65    public String reverseLookup(Destination dest) {
     66        return reverseLookup(dest, null);
     67    }
    6568
    6669    /** @deprecated unused */
    67     public String reverseLookup(Hash h) { return null; };
     70    public String reverseLookup(Hash h) { return null; }
    6871
    6972    /**
     
    8285        }
    8386    }
     87
     88    ///// New API Starts Here
     89
     90    /**
     91     *  @return Class simple name by default
     92     *  @since 0.8.5
     93     */
     94    public String getName() {
     95        return getClass().getSimpleName();
     96    }
     97
     98    /**
     99     *  @return NamingService-specific options or null
     100     *  @since 0.8.5
     101     */
     102    public Properties getConfiguration() {
     103        return null;
     104    }
     105
     106    /**
     107     *  @return success
     108     *  @since 0.8.5
     109     */
     110    public boolean setConfiguration(Properties p) {
     111        return true;
     112    }
     113
     114    // These are for daisy chaining (MetaNamingService)
     115
     116    /**
     117     *  @return chained naming services or null
     118     *  @since 0.8.5
     119     */
     120    public List<NamingService> getNamingServices() {
     121        return null;
     122    }
     123
     124    /**
     125     *  @return parent naming service or null if this is the root
     126     *  @since 0.8.5
     127     */
     128    public NamingService getParent() {
     129        return null;
     130    }
     131
     132    /**
     133     * Only for chaining-capable NamingServices. Add to end of the list.
     134     * @return success
     135     */
     136    public boolean addNamingService(NamingService ns) {
     137        return addNamingService(ns, false);
     138    }
     139
     140
     141    /**
     142     * Only for chaining-capable NamingServices
     143     * @param head or tail
     144     * @return success
     145     */
     146    public boolean addNamingService(NamingService ns, boolean head) {
     147        return false;
     148    }
     149
     150    /**
     151     *  Only for chaining-capable NamingServices
     152     *  @return success
     153     *  @since 0.8.5
     154     */
     155    public boolean removeNamingService(NamingService ns) {
     156        return false;
     157    }
     158
     159    // options would be used to specify public / private / master ...
     160    // or should we just daisy chain 3 HostsTxtNamingServices ?
     161    // that might be better... then addressbook only talks to the 'router' HostsTxtNamingService
     162
     163    /**
     164     *  @return number of entries or -1 if unknown
     165     *  @since 0.8.5
     166     */
     167    public int size() {
     168        return size(null);
     169    }
     170
     171    /**
     172     *  @param options NamingService-specific, can be null
     173     *  @return number of entries (matching the options if non-null) or -1 if unknown
     174     *  @since 0.8.5
     175     */
     176    public int size(Properties options) {
     177        return -1;
     178    }
     179
     180    /**
     181     *  @return all mappings
     182     *          or empty Map if none;
     183     *          Returned Map is not necessarily sorted, implementation dependent
     184     *  @since 0.8.5
     185     */
     186    public Map<String, Destination> getEntries() {
     187        return getEntries(null);
     188    }
     189
     190    /**
     191     *  @param options NamingService-specific, can be null
     192     *  @return all mappings (matching the options if non-null)
     193     *          or empty Map if none;
     194     *          Returned Map is not necessarily sorted, implementation dependent
     195     *  @since 0.8.5
     196     */
     197    public Map<String, Destination> getEntries(Properties options) {
     198        return Collections.EMPTY_MAP;
     199    }
     200
     201    /**
     202     *  This may be more or less efficient than getEntries()
     203     *  @param options NamingService-specific, can be null
     204     *  @return all mappings (matching the options if non-null)
     205     *          or empty Map if none;
     206     *          Returned Map is not necessarily sorted, implementation dependent
     207     *  @since 0.8.5
     208     */
     209    public Map<String, String> getBase64Entries(Properties options) {
     210        return Collections.EMPTY_MAP;
     211    }
     212
     213    /**
     214     *  @return all known host names
     215     *          or empty Set if none;
     216     *          Returned Set is not necessarily sorted, implementation dependent
     217     *  @since 0.8.5
     218     */
     219    public Set<String> getNames() {
     220        return getNames(null);
     221    }
     222
     223    /**
     224     *  @param options NamingService-specific, can be null
     225     *  @return all known host names (matching the options if non-null)
     226     *          or empty Set if none;
     227     *          Returned Set is not necessarily sorted, implementation dependent
     228     *  @since 0.8.5
     229     */
     230    public Set<String> getNames(Properties options) {
     231        return Collections.EMPTY_SET;
     232    }
     233
     234    /**
     235     *  @return success
     236     *  @since 0.8.5
     237     */
     238    public boolean put(String hostname, Destination d) {
     239        return put(hostname, d, null);
     240    }
     241
     242    /**
     243     *  @param options NamingService-specific, can be null
     244     *  @return success
     245     *  @since 0.8.5
     246     */
     247    public boolean put(String hostname, Destination d, Properties options) {
     248        return false;
     249    }
     250
     251    /**
     252     *  Fails if entry previously exists
     253     *  @return success
     254     *  @since 0.8.5
     255     */
     256    public boolean putIfAbsent(String hostname, Destination d) {
     257        return putIfAbsent(hostname, d, null);
     258    }
     259
     260    /**
     261     *  Fails if entry previously exists
     262     *  @param options NamingService-specific, can be null
     263     *  @return success
     264     *  @since 0.8.5
     265     */
     266    public boolean putIfAbsent(String hostname, Destination d, Properties options) {
     267        return false;
     268    }
     269
     270    /**
     271     *  @param options NamingService-specific, can be null
     272     *  @return success
     273     *  @since 0.8.5
     274     */
     275    public boolean putAll(Map<String, Destination> entries, Properties options) {
     276        boolean rv = true;
     277        for (Map.Entry<String, Destination> entry : entries.entrySet()) {
     278            if (!put(entry.getKey(), entry.getValue(), options))
     279                rv = false;
     280        }
     281        return rv;
     282    }
     283
     284    /**
     285     *  Fails if entry did not previously exist
     286     *  @param d may be null if only options are changing
     287     *  @param options NamingService-specific, can be null
     288     *  @return success
     289     *  @since 0.8.5
     290     */
     291    public boolean update(String hostname, Destination d, Properties options) {
     292        return false;
     293    }
     294
     295    /**
     296     *  @return success
     297     *  @since 0.8.5
     298     */
     299    public boolean remove(String hostname) {
     300        return remove(hostname, null);
     301    }
     302
     303    /**
     304     *  @param options NamingService-specific, can be null
     305     *  @return success
     306     *  @since 0.8.5
     307     */
     308    public boolean remove(String hostname, Properties options) {
     309        return false;
     310    }
     311
     312    /**
     313     *  Ask the NamingService to update its database
     314     *  Should this be a separate interface? This is what addressbook needs
     315     *  @param options NamingService-specific, can be null
     316     *  @since 0.8.5
     317     */
     318    public void requestUpdate(Properties options) {}
     319
     320    /**
     321     *  @since 0.8.5
     322     */
     323    public void registerListener(NamingServiceListener nsl) {
     324        _listeners.add(nsl);
     325    }
     326
     327    /**
     328     *  @since 0.8.5
     329     */
     330    public void unregisterListener(NamingServiceListener nsl) {
     331        _listeners.remove(nsl);
     332    }
     333
     334    /**
     335     *  Same as lookup(hostname) but with in and out options
     336     *  Note that whether this (and lookup(hostname)) resolve B32 addresses is
     337     *  NamingService-specific.
     338     *  @param lookupOptions input parameter, NamingService-specific, can be null
     339     *  @param storedOptions output parameter, NamingService-specific, any stored properties will be added if non-null
     340     *  @return dest or null
     341     *  @since 0.8.5
     342     */
     343    public abstract Destination lookup(String hostname, Properties lookupOptions, Properties storedOptions);
     344
     345    /**
     346     *  Same as reverseLookup(dest) but with options
     347     *  @param options NamingService-specific, can be null
     348     *  @return host name or null
     349     *  @since 0.8.5
     350     */
     351    public String reverseLookup(Destination d, Properties options) {
     352        return null;
     353    }
     354
     355    /**
     356     *  Lookup a Base 32 address. This may require the router to fetch the LeaseSet,
     357     *  which may take quite a while.
     358     *  @param hostname must be {52 chars}.b32.i2p
     359     *  @param timeout in seconds; <= 0 means use router default
     360     *  @return dest or null
     361     *  @since 0.8.5
     362     */
     363    public Destination lookupBase32(String hostname, int timeout) {
     364        return null;
     365    }
     366
     367    /**
     368     *  Same as lookupB32 but with the SHA256 Hash precalculated
     369     *  @param timeout in seconds; <= 0 means use router default
     370     *  @return dest or null
     371     *  @since 0.8.5
     372     */
     373    public Destination lookup(Hash hash, int timeout) {
     374        return null;
     375    }
     376
     377    /**
     378     *  Parent will call when added.
     379     *  If this is the root naming service, the core will start it.
     380     *  Should not be called by others.
     381     *  @since 0.8.5
     382     */
     383    public void start() {}
     384
     385    /**
     386     *  Parent will call when removed.
     387     *  If this is the root naming service, the core will stop it.
     388     *  Should not be called by others.
     389     *  @since 0.8.5
     390     */
     391    public void stop() {}
     392
     393    //// End New API
    84394
    85395    /**
     
    103413    }
    104414
    105     /**
    106      *  Provide basic caching for the service
    107      *  The service may override the age and/or size limit
    108      */
    109     /** Don't know why a dest would ever change but keep this short anyway */
    110     protected static final long CACHE_MAX_AGE = 7*60*1000;
    111 
    112     private class CacheEntry {
    113         public Destination dest;
    114         public long exp;
    115         public CacheEntry(Destination d) {
    116             dest = d;
    117             exp = _context.clock().now() + CACHE_MAX_AGE;
    118         }
    119         public boolean isExpired() {
    120             return exp < _context.clock().now();
    121         }
    122     }
    123 
    124     /**
    125      * Clean up when full.
    126      * Don't bother removing old entries unless full.
    127      * Caller must synchronize on _cache.
    128      */
    129     private void cacheClean() {
    130         if (_cache.size() < CACHE_MAX_SIZE)
    131             return;
    132         boolean full = true;
    133         Object oldestKey = null;
    134         long oldestExp = Long.MAX_VALUE;
    135         ArrayList deleteList = new ArrayList(CACHE_MAX_SIZE);
    136         for (Iterator iter = _cache.entrySet().iterator(); iter.hasNext(); ) {
    137             Map.Entry entry = (Map.Entry) iter.next();
    138             CacheEntry ce = (CacheEntry) entry.getValue();
    139             if (ce.isExpired()) {
    140                 deleteList.add(entry.getKey());
    141                 full = false;
    142                 continue;
    143             }
    144             if (oldestKey == null || ce.exp < oldestExp) {
    145                 oldestKey = entry.getKey();
    146                 oldestExp = ce.exp;
    147             }
    148         }
    149         if (full && oldestKey != null)
    150             deleteList.add(oldestKey);
    151         for (Iterator iter = deleteList.iterator(); iter.hasNext(); ) {
    152             _cache.remove(iter.next());
    153         }
    154     }
    155 
    156     protected void putCache(String s, Destination d) {
    157         if (d == null)
    158             return;
    159         synchronized (_cache) {
    160             _cache.put(s, new CacheEntry(d));
    161             cacheClean();
    162         }
    163     }
    164 
    165     protected Destination getCache(String s) {
    166         synchronized (_cache) {
    167             CacheEntry ce = (CacheEntry) _cache.get(s);
    168             if (ce == null)
    169                 return null;
    170             if (ce.isExpired()) {
    171                 _cache.remove(s);
    172                 return null;
    173             }
    174             return ce.dest;
    175         }
    176     }
    177 
    178     /** @since 0.8.1 */
    179     public void clearCache() {
    180         synchronized (_cache) {
    181             _cache.clear();
    182         }
    183     }
    184415}
Note: See TracChangeset for help on using the changeset viewer.