forked from I2P_Developers/i2p.i2p
NamingService: Add export methods,
fill in subclass methods for efficient exporting, fill in getBase64Entires() and getNames() where unimplemented SusiDNS: Add export support, no UI yet
This commit is contained in:
@ -42,6 +42,11 @@
|
|||||||
<url-pattern>/index</url-pattern>
|
<url-pattern>/index</url-pattern>
|
||||||
</servlet-mapping>
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>i2p.susi.dns.jsp.export_jsp</servlet-name>
|
||||||
|
<url-pattern>/export</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
<session-config>
|
<session-config>
|
||||||
<session-timeout>
|
<session-timeout>
|
||||||
30
|
30
|
||||||
|
@ -21,12 +21,15 @@
|
|||||||
|
|
||||||
package i2p.susi.dns;
|
package i2p.susi.dns;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
|
||||||
import net.i2p.client.naming.NamingService;
|
import net.i2p.client.naming.NamingService;
|
||||||
import net.i2p.data.DataFormatException;
|
import net.i2p.data.DataFormatException;
|
||||||
@ -196,7 +199,8 @@ public class NamingServiceBean extends AddressbookBean
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressBean array[] = list.toArray(new AddressBean[list.size()]);
|
AddressBean array[] = list.toArray(new AddressBean[list.size()]);
|
||||||
Arrays.sort( array, sorter );
|
if (!(results instanceof SortedMap))
|
||||||
|
Arrays.sort( array, sorter );
|
||||||
entries = array;
|
entries = array;
|
||||||
|
|
||||||
message = generateLoadMessage();
|
message = generateLoadMessage();
|
||||||
@ -351,4 +355,21 @@ public class NamingServiceBean extends AddressbookBean
|
|||||||
rv.setProperties(outProps);
|
rv.setProperties(outProps);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public void export(Writer out) throws IOException {
|
||||||
|
Properties searchProps = new Properties();
|
||||||
|
// only blockfile needs this
|
||||||
|
searchProps.setProperty("list", getFileName());
|
||||||
|
if (filter != null) {
|
||||||
|
String startsAt = filter.equals("0-9") ? "[0-9]" : filter;
|
||||||
|
searchProps.setProperty("startsWith", startsAt);
|
||||||
|
}
|
||||||
|
if (search != null && search.length() > 0)
|
||||||
|
searchProps.setProperty("search", search.toLowerCase(Locale.US));
|
||||||
|
getNamingService().export(out, searchProps);
|
||||||
|
// No post-filtering for hosts.txt naming services. It is what it is.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
35
apps/susidns/src/jsp/export.jsp
Normal file
35
apps/susidns/src/jsp/export.jsp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<%
|
||||||
|
/*
|
||||||
|
* This file is part of susidns project, see http://susi.i2p/
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 <susi23@mail.i2p>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// http://www.crazysquirrel.com/computing/general/form-encoding.jspx
|
||||||
|
if (request.getCharacterEncoding() == null)
|
||||||
|
request.setCharacterEncoding("UTF-8");
|
||||||
|
%>
|
||||||
|
<%@page pageEncoding="UTF-8"%>
|
||||||
|
<%@page trimDirectiveWhitespaces="true"%>
|
||||||
|
<%@ page contentType="text/plain"%>
|
||||||
|
<jsp:useBean id="book" class="i2p.susi.dns.NamingServiceBean" scope="session" />
|
||||||
|
<jsp:setProperty name="book" property="*" />
|
||||||
|
<jsp:setProperty name="book" property="resetDeletionMarks" value="1"/>
|
||||||
|
<%
|
||||||
|
book.export(out);
|
||||||
|
%>
|
@ -18,11 +18,14 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.DataFormatException;
|
import net.i2p.data.DataFormatException;
|
||||||
@ -860,7 +863,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
iter = sl.find(beginWith);
|
iter = sl.find(beginWith);
|
||||||
else
|
else
|
||||||
iter = sl.iterator();
|
iter = sl.iterator();
|
||||||
Map<String, Destination> rv = new HashMap<String, Destination>();
|
Map<String, Destination> rv = new TreeMap<String, Destination>();
|
||||||
for (int i = 0; i < skip && iter.hasNext(); i++) {
|
for (int i = 0; i < skip && iter.hasNext(); i++) {
|
||||||
// don't bother validating here
|
// don't bother validating here
|
||||||
iter.next();
|
iter.next();
|
||||||
@ -896,6 +899,188 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param options If non-null and contains the key "list", get
|
||||||
|
* from that list (default "hosts.txt", NOT all lists)
|
||||||
|
* Key "skip": skip that many entries
|
||||||
|
* Key "limit": max number to return
|
||||||
|
* Key "search": return only those matching substring
|
||||||
|
* Key "startsWith": return only those starting with
|
||||||
|
* ("[0-9]" allowed)
|
||||||
|
* Key "beginWith": start here in the iteration
|
||||||
|
* Don't use both startsWith and beginWith.
|
||||||
|
* Search, startsWith, and beginWith values must be lower case.
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getBase64Entries(Properties options) {
|
||||||
|
String listname = FALLBACK_LIST;
|
||||||
|
String search = null;
|
||||||
|
String startsWith = null;
|
||||||
|
String beginWith = null;
|
||||||
|
int limit = Integer.MAX_VALUE;
|
||||||
|
int skip = 0;
|
||||||
|
if (options != null) {
|
||||||
|
String ln = options.getProperty("list");
|
||||||
|
if (ln != null)
|
||||||
|
listname = ln;
|
||||||
|
search = options.getProperty("search");
|
||||||
|
startsWith = options.getProperty("startsWith");
|
||||||
|
beginWith = options.getProperty("beginWith");
|
||||||
|
if (beginWith == null && startsWith != null) {
|
||||||
|
if (startsWith.equals("[0-9]"))
|
||||||
|
beginWith = "0";
|
||||||
|
else
|
||||||
|
beginWith = startsWith;
|
||||||
|
}
|
||||||
|
String lim = options.getProperty("limit");
|
||||||
|
try {
|
||||||
|
limit = Integer.parseInt(lim);
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
String sk = options.getProperty("skip");
|
||||||
|
try {
|
||||||
|
skip = Integer.parseInt(sk);
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
synchronized(_bf) {
|
||||||
|
if (_isClosed)
|
||||||
|
return Collections.emptyMap();
|
||||||
|
try {
|
||||||
|
SkipList sl = _bf.getIndex(listname, _stringSerializer, _destSerializer);
|
||||||
|
if (sl == null) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("No skiplist found for lookup in " + listname);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
SkipIterator iter;
|
||||||
|
if (beginWith != null)
|
||||||
|
iter = sl.find(beginWith);
|
||||||
|
else
|
||||||
|
iter = sl.iterator();
|
||||||
|
Map<String, String> rv = new TreeMap<String, String>();
|
||||||
|
for (int i = 0; i < skip && iter.hasNext(); i++) {
|
||||||
|
// don't bother validating here
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < limit && iter.hasNext(); ) {
|
||||||
|
String key = (String) iter.nextKey();
|
||||||
|
if (startsWith != null) {
|
||||||
|
if (startsWith.equals("[0-9]")) {
|
||||||
|
if (key.charAt(0) > '9')
|
||||||
|
break;
|
||||||
|
} else if (!key.startsWith(startsWith)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DestEntry de = (DestEntry) iter.next();
|
||||||
|
if (!validate(key, de, listname))
|
||||||
|
continue;
|
||||||
|
if (search != null && key.indexOf(search) < 0)
|
||||||
|
continue;
|
||||||
|
rv.put(key, de.dest.toBase64());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
_log.error("DB lookup error", ioe);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
_log.error("DB lookup error", re);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
} finally {
|
||||||
|
deleteInvalid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param options If non-null and contains the key "list", get
|
||||||
|
* from that list (default "hosts.txt", NOT all lists)
|
||||||
|
* Key "skip": skip that many entries
|
||||||
|
* Key "limit": max number to return
|
||||||
|
* Key "search": return only those matching substring
|
||||||
|
* Key "startsWith": return only those starting with
|
||||||
|
* ("[0-9]" allowed)
|
||||||
|
* Key "beginWith": start here in the iteration
|
||||||
|
* Don't use both startsWith and beginWith.
|
||||||
|
* Search, startsWith, and beginWith values must be lower case.
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Set<String> getNames(Properties options) {
|
||||||
|
String listname = FALLBACK_LIST;
|
||||||
|
String search = null;
|
||||||
|
String startsWith = null;
|
||||||
|
String beginWith = null;
|
||||||
|
int limit = Integer.MAX_VALUE;
|
||||||
|
int skip = 0;
|
||||||
|
if (options != null) {
|
||||||
|
String ln = options.getProperty("list");
|
||||||
|
if (ln != null)
|
||||||
|
listname = ln;
|
||||||
|
search = options.getProperty("search");
|
||||||
|
startsWith = options.getProperty("startsWith");
|
||||||
|
beginWith = options.getProperty("beginWith");
|
||||||
|
if (beginWith == null && startsWith != null) {
|
||||||
|
if (startsWith.equals("[0-9]"))
|
||||||
|
beginWith = "0";
|
||||||
|
else
|
||||||
|
beginWith = startsWith;
|
||||||
|
}
|
||||||
|
String lim = options.getProperty("limit");
|
||||||
|
try {
|
||||||
|
limit = Integer.parseInt(lim);
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
String sk = options.getProperty("skip");
|
||||||
|
try {
|
||||||
|
skip = Integer.parseInt(sk);
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
synchronized(_bf) {
|
||||||
|
if (_isClosed)
|
||||||
|
return Collections.emptySet();
|
||||||
|
try {
|
||||||
|
SkipList sl = _bf.getIndex(listname, _stringSerializer, _destSerializer);
|
||||||
|
if (sl == null) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("No skiplist found for lookup in " + listname);
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
SkipIterator iter;
|
||||||
|
if (beginWith != null)
|
||||||
|
iter = sl.find(beginWith);
|
||||||
|
else
|
||||||
|
iter = sl.iterator();
|
||||||
|
Set<String> rv = new HashSet<String>();
|
||||||
|
for (int i = 0; i < skip && iter.hasNext(); i++) {
|
||||||
|
iter.next();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < limit && iter.hasNext(); ) {
|
||||||
|
String key = (String) iter.nextKey();
|
||||||
|
if (startsWith != null) {
|
||||||
|
if (startsWith.equals("[0-9]")) {
|
||||||
|
if (key.charAt(0) > '9')
|
||||||
|
break;
|
||||||
|
} else if (!key.startsWith(startsWith)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (search != null && key.indexOf(search) < 0)
|
||||||
|
continue;
|
||||||
|
rv.add(key);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
_log.error("DB lookup error", ioe);
|
||||||
|
return Collections.emptySet();
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
_log.error("DB lookup error", re);
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param options ignored
|
* @param options ignored
|
||||||
* @since 0.8.9
|
* @since 0.8.9
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.i2p.client.naming;
|
package net.i2p.client.naming;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -179,6 +181,19 @@ public class MetaNamingService extends DummyNamingService {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All services aggregated
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getBase64Entries(Properties options) {
|
||||||
|
Map<String, String> rv = new HashMap<String, String>();
|
||||||
|
for (NamingService ns : _services) {
|
||||||
|
rv.putAll(ns.getBase64Entries(options));
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All services aggregated
|
* All services aggregated
|
||||||
*/
|
*/
|
||||||
@ -191,6 +206,17 @@ public class MetaNamingService extends DummyNamingService {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All services aggregated.
|
||||||
|
* Duplicates not removed (for efficiency)
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public void export(Writer out, Properties options) throws IOException {
|
||||||
|
for (NamingService ns : _services) {
|
||||||
|
export(out, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All services aggregated
|
* All services aggregated
|
||||||
*/
|
*/
|
||||||
|
@ -7,12 +7,16 @@
|
|||||||
*/
|
*/
|
||||||
package net.i2p.client.naming;
|
package net.i2p.client.naming;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
@ -235,14 +239,75 @@ public abstract class NamingService {
|
|||||||
* Warning - This will bring the whole database into memory
|
* Warning - This will bring the whole database into memory
|
||||||
* if options is null, empty, or unsupported, use with caution.
|
* if options is null, empty, or unsupported, use with caution.
|
||||||
*
|
*
|
||||||
|
* This implementation calls getEntries(options) and returns a SortedMap.
|
||||||
|
* Subclasses should override if they store base64 natively.
|
||||||
|
*
|
||||||
* @param options NamingService-specific, can be null
|
* @param options NamingService-specific, can be null
|
||||||
* @return all mappings (matching the options if non-null)
|
* @return all mappings (matching the options if non-null)
|
||||||
* or empty Map if none;
|
* or empty Map if none;
|
||||||
* Returned Map is not necessarily sorted, implementation dependent
|
* Returned Map is not necessarily sorted, implementation dependent
|
||||||
* @since 0.8.7
|
* @since 0.8.7, implemented in 0.9.20
|
||||||
*/
|
*/
|
||||||
public Map<String, String> getBase64Entries(Properties options) {
|
public Map<String, String> getBase64Entries(Properties options) {
|
||||||
return Collections.emptyMap();
|
Map<String, Destination> entries = getEntries(options);
|
||||||
|
if (entries.size() <= 0)
|
||||||
|
return Collections.emptyMap();
|
||||||
|
Map<String, String> rv = new TreeMap<String, String>();
|
||||||
|
for (Map.Entry<String, Destination> e : entries.entrySet()) {
|
||||||
|
rv.put(e.getKey(), e.getValue().toBase64());
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export in a hosts.txt format.
|
||||||
|
* Output is not necessarily sorted, implementation dependent.
|
||||||
|
* Output may or may not contain comment lines, implementation dependent.
|
||||||
|
* Caller must close writer.
|
||||||
|
*
|
||||||
|
* This implementation calls getBase64Entries().
|
||||||
|
* Subclasses should override if they store in a hosts.txt format natively.
|
||||||
|
*
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public void export(Writer out) throws IOException {
|
||||||
|
export(out, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export in a hosts.txt format.
|
||||||
|
* Output is not necessarily sorted, implementation dependent.
|
||||||
|
* Output may or may not contain comment lines, implementation dependent.
|
||||||
|
* Caller must close writer.
|
||||||
|
*
|
||||||
|
* This implementation calls getBase64Entries(options).
|
||||||
|
* Subclasses should override if they store in a hosts.txt format natively.
|
||||||
|
*
|
||||||
|
* @param options NamingService-specific, can be null
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public void export(Writer out, Properties options) throws IOException {
|
||||||
|
Map<String, String> entries = getBase64Entries(options);
|
||||||
|
out.write("# Address book: ");
|
||||||
|
out.write(getName());
|
||||||
|
out.write('\n');
|
||||||
|
int sz = entries.size();
|
||||||
|
if (sz <= 0) {
|
||||||
|
out.write("# No entries\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.write("# Exported: ");
|
||||||
|
out.write((new Date()).toString());
|
||||||
|
out.write('\n');
|
||||||
|
if (sz > 1) {
|
||||||
|
out.write("# " + sz + " entries\n");
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, String> e : entries.entrySet()) {
|
||||||
|
out.write(e.getKey());
|
||||||
|
out.write('=');
|
||||||
|
out.write(e.getValue());
|
||||||
|
out.write('\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +15,9 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -364,6 +366,102 @@ public class SingleFileNamingService extends NamingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden since we store base64 natively.
|
||||||
|
*
|
||||||
|
* @param options As follows:
|
||||||
|
* Key "search": return only those matching substring
|
||||||
|
* Key "startsWith": return only those starting with
|
||||||
|
* ("[0-9]" allowed)
|
||||||
|
* @return all mappings (matching the options if non-null)
|
||||||
|
* or empty Map if none.
|
||||||
|
* Returned Map is not sorted.
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public Map<String, String> getBase64Entries(Properties options) {
|
||||||
|
if (!_file.exists())
|
||||||
|
return Collections.emptyMap();
|
||||||
|
String searchOpt = null;
|
||||||
|
String startsWith = null;
|
||||||
|
if (options != null) {
|
||||||
|
searchOpt = options.getProperty("search");
|
||||||
|
startsWith = options.getProperty("startsWith");
|
||||||
|
}
|
||||||
|
BufferedReader in = null;
|
||||||
|
getReadLock();
|
||||||
|
try {
|
||||||
|
in = new BufferedReader(new InputStreamReader(new FileInputStream(_file), "UTF-8"), 16*1024);
|
||||||
|
String line = null;
|
||||||
|
Map<String, String> rv = new HashMap<String, String>();
|
||||||
|
while ( (line = in.readLine()) != null) {
|
||||||
|
if (line.length() <= 0)
|
||||||
|
continue;
|
||||||
|
if (startsWith != null) {
|
||||||
|
if (startsWith.equals("[0-9]")) {
|
||||||
|
if (line.charAt(0) < '0' || line.charAt(0) > '9')
|
||||||
|
continue;
|
||||||
|
} else if (!line.startsWith(startsWith)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (line.startsWith("#"))
|
||||||
|
continue;
|
||||||
|
if (line.indexOf('#') > 0) // trim off any end of line comment
|
||||||
|
line = line.substring(0, line.indexOf('#')).trim();
|
||||||
|
int split = line.indexOf('=');
|
||||||
|
if (split <= 0)
|
||||||
|
continue;
|
||||||
|
String key = line.substring(0, split);
|
||||||
|
if (searchOpt != null && key.indexOf(searchOpt) < 0)
|
||||||
|
continue;
|
||||||
|
String b64 = line.substring(split+1); //.trim() ??????????????
|
||||||
|
if (b64.length() < 387)
|
||||||
|
continue;
|
||||||
|
rv.put(key, b64);
|
||||||
|
}
|
||||||
|
if (searchOpt == null && startsWith == null) {
|
||||||
|
_lastWrite = _file.lastModified();
|
||||||
|
_size = rv.size();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
_log.error("getEntries error", ioe);
|
||||||
|
return Collections.emptyMap();
|
||||||
|
} finally {
|
||||||
|
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||||
|
releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overridden for efficiency.
|
||||||
|
* Output is not sorted.
|
||||||
|
*
|
||||||
|
* @param options ignored
|
||||||
|
* @since 0.9.20
|
||||||
|
*/
|
||||||
|
public void export(Writer out, Properties options) throws IOException {
|
||||||
|
out.write("# Address book: ");
|
||||||
|
out.write(getName());
|
||||||
|
out.write('\n');
|
||||||
|
out.write("# Exported: ");
|
||||||
|
out.write((new Date()).toString());
|
||||||
|
out.write('\n');
|
||||||
|
BufferedReader in = null;
|
||||||
|
getReadLock();
|
||||||
|
try {
|
||||||
|
in = new BufferedReader(new InputStreamReader(new FileInputStream(_file), "UTF-8"), 16*1024);
|
||||||
|
String line = null;
|
||||||
|
while ( (line = in.readLine()) != null) {
|
||||||
|
out.write(line);
|
||||||
|
out.write('\n');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||||
|
releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param options ignored
|
* @param options ignored
|
||||||
* @return all known host names, unsorted
|
* @return all known host names, unsorted
|
||||||
|
Reference in New Issue
Block a user