- modified api-call interface to record api calls with references to api-call database (carries pk)

- added recording date, last execution date and next execution date for a scheduler (scheduler to be implemented next)
- extended database access methods for more data formats, especially for date insert/retrieval
- extended 'Steering' interface to show new database fields
- migrated Steering to new http client
- extended cora http client to transmit authentication and also added some convenience methods (http response code)
- simplified database back-end (not so much specialized methods for multiple properties)
- extended date formatter to produce a special format to show dates in html (  in spaces of date format)


git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7049 6c8d7289-2bf4-0310-a012-ef5d649a1542
This commit is contained in:
orbiter 2010-08-18 15:56:38 +00:00
parent 1bc08e1416
commit 189a986ebd
12 changed files with 277 additions and 280 deletions

View File

@ -173,8 +173,7 @@
</javadoc>
</target>
<target name="compile-core" depends="init" description="compile YaCy core">
<!-- defining the classpath that should be used for compiling -->
<!-- define the classpath that should be used for compiling -->
<path id="project.class.path">
<pathelement location="${build}" />
<pathelement location="${htroot}" />
@ -207,6 +206,8 @@
<pathelement location="${lib}/webcat-0.1-swf.jar" />
<pathelement location="${lib}/xerces.jar" />
</path>
<target name="compile-core" depends="init" description="compile YaCy core">
<!-- compile yacyBuildProperties.java -->
<javac srcdir="${build}" destdir="${build}" sourcepath="${src}"
@ -246,9 +247,9 @@
<!-- compile htroot, htroot/yacy and htroot/htdocsdefault -->
<javac srcdir="${htroot}/"
excludes="processing/**"
classpathref="project.class.path"
source="${javacSource}" target="${javacTarget}"
debug="true" debuglevel="lines,vars,source">
<classpath refid="project.class.path" />
<compilerarg value="-Xlint"/>
</javac>
</target>

View File

@ -41,17 +41,23 @@
<table class="sortable" border="0" cellpadding="2" cellspacing="1">
<tr class="TableHeader" valign="bottom">
<td><input type="checkbox" name="allswitch" onclick="setall(this.form.name, this.value)" /></td>
<td>Date</td>
<td>Type</td>
<td>Comment</td>
<td>Call<br/>Count</td>
<td>Recording<br/>Date</td>
<td>Last&nbsp;Exec<br/>Date</td>
<td>Next&nbsp;Exec<br/>Date</td>
<td>URL</td>
</tr>
#{list}#
<tr class="TableCell#(dark)#Light::Dark::Summary#(/dark)#">
<td align="left"><input type="checkbox" name="item_#[count]#" value="mark_#[pk]#" /></td>
<td>#[date]#</td>
<td>#[type]#</td>
<td>#[comment]#</td>
<td>#[callcount]#</td>
<td>#[dateRecording]#</td>
<td>#[dateLastExec]#</td>
<td>#[dateNextExec]#</td>
<td>#[url]#</td>
</tr>
#{/list}#

View File

@ -18,19 +18,20 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeSet;
import net.yacy.cora.protocol.Client;
import net.yacy.kelondro.blob.Tables;
import net.yacy.kelondro.index.RowSpaceExceededException;
import net.yacy.kelondro.logging.Log;
import net.yacy.kelondro.util.DateFormatter;
import de.anomic.data.WorkTables;
import de.anomic.http.client.Client;
import de.anomic.http.server.RequestHeader;
import de.anomic.http.server.ResponseContainer;
import de.anomic.search.Switchboard;
import de.anomic.server.serverObjects;
import de.anomic.server.serverSwitch;
@ -66,17 +67,21 @@ public class Table_API_p {
}
// now call the api URLs and store the result status
final RequestHeader reqHeader = new RequestHeader();
final Client client = new Client(120000, reqHeader);
ResponseContainer result;
final Client client = new Client();
client.setRealm(sb.getConfig("adminAccountBase64MD5", ""));
client.setTimout(120000);
LinkedHashMap<String, Integer> l = new LinkedHashMap<String, Integer>();
for (String pk: pks) {
try {
Tables.Row row = sb.tables.select(WorkTables.TABLE_API_NAME, pk.getBytes());
if (row != null) {
String url = "http://localhost:" + sb.getConfig("port", "8080") + new String(row.from(WorkTables.TABLE_API_COL_URL));
result = client.GET(url, Long.MAX_VALUE, sb.getConfig("adminAccountBase64MD5", ""));
l.put(url, result.getStatusCode());
String url = "http://localhost:" + sb.getConfig("port", "8080") + new String(row.get(WorkTables.TABLE_API_COL_URL));
url += "&" + WorkTables.TABLE_API_COL_APICALL_PK + "=" + pk;
url += "&" + WorkTables.TABLE_API_COL_APICALL_COUNT + "=" + (row.get(WorkTables.TABLE_API_COL_APICALL_COUNT, 1) + 1);
url += "&" + WorkTables.TABLE_API_COL_APICALL_SCHEDULE_TIME + "=" + row.get(WorkTables.TABLE_API_COL_APICALL_SCHEDULE_TIME, "");
url += "&" + WorkTables.TABLE_API_COL_APICALL_SCHEDULE_UNIT + "=" + row.get(WorkTables.TABLE_API_COL_APICALL_SCHEDULE_UNIT, "");
client.GETbytes(url);
l.put(url, client.getStatusCode());
}
} catch (IOException e) {
Log.logException(e);
@ -110,19 +115,28 @@ public class Table_API_p {
int count = 0;
try {
final Iterator<Tables.Row> plainIterator = sb.tables.iterator(WorkTables.TABLE_API_NAME);
final Iterator<Tables.Row> mapIterator = sb.tables.orderBy(plainIterator, -1, WorkTables.TABLE_API_COL_DATE).iterator();
final Iterator<Tables.Row> mapIterator = sb.tables.orderBy(plainIterator, -1, WorkTables.TABLE_API_COL_DATE_RECORDING).iterator();
Tables.Row row;
boolean dark = true;
while (mapIterator.hasNext()) {
row = mapIterator.next();
if (row == null) continue;
Date dfltdate = new Date();
Date date = row.containsKey(WorkTables.TABLE_API_COL_DATE) ? row.get(WorkTables.TABLE_API_COL_DATE, dfltdate) : null;
Date date_recording = row.get(WorkTables.TABLE_API_COL_DATE_RECORDING, date);
Date date_last_exec = row.get(WorkTables.TABLE_API_COL_DATE_LAST_EXEC, date);
Date date_next_exec = row.containsKey(WorkTables.TABLE_API_COL_DATE_NEXT_EXEC) ? row.get(WorkTables.TABLE_API_COL_DATE_NEXT_EXEC, dfltdate) : null;
int callcount = row.get(WorkTables.TABLE_API_COL_APICALL_COUNT, 1);
prop.put("showtable_list_" + count + "_dark", ((dark) ? 1 : 0) ); dark=!dark;
prop.put("showtable_list_" + count + "_pk", new String(row.getPK()));
prop.put("showtable_list_" + count + "_count", count);
prop.put("showtable_list_" + count + "_date", row.from(WorkTables.TABLE_API_COL_DATE));
prop.put("showtable_list_" + count + "_type", row.from(WorkTables.TABLE_API_COL_TYPE));
prop.put("showtable_list_" + count + "_comment", row.from(WorkTables.TABLE_API_COL_COMMENT));
prop.put("showtable_list_" + count + "_url", "http://" + sb.myPublicIP() + ":" + sb.getConfig("port", "8080") + new String(row.from(WorkTables.TABLE_API_COL_URL)));
prop.put("showtable_list_" + count + "_callcount", callcount);
prop.put("showtable_list_" + count + "_dateRecording", date_recording == null ? "-" : DateFormatter.formatHTML(date_recording));
prop.put("showtable_list_" + count + "_dateLastExec", date_last_exec == null ? "-" : DateFormatter.formatHTML(date_last_exec));
prop.put("showtable_list_" + count + "_dateNextExec", date_next_exec == null ? "-" : DateFormatter.formatHTML(date_next_exec));
prop.put("showtable_list_" + count + "_type", row.get(WorkTables.TABLE_API_COL_TYPE));
prop.put("showtable_list_" + count + "_comment", row.get(WorkTables.TABLE_API_COL_COMMENT));
prop.put("showtable_list_" + count + "_url", "http://" + sb.myPublicIP() + ":" + sb.getConfig("port", "8080") + new String(row.get(WorkTables.TABLE_API_COL_URL)));
count++;
}
} catch (IOException e) {

View File

@ -120,7 +120,7 @@ public class Tables_p {
}
}
try {
sb.tables.insert(table, pk.getBytes(), map);
sb.tables.update(table, pk.getBytes(), map);
} catch (IOException e) {
Log.logException(e);
}
@ -192,7 +192,7 @@ public class Tables_p {
prop.put("showtable_list_" + count + "_pk", new String(row.getPK()));
prop.put("showtable_list_" + count + "_count", count);
for (int i = 0; i < columns.size(); i++) {
cell = row.from(columns.get(i));
cell = row.get(columns.get(i));
prop.putHTML("showtable_list_" + count + "_columns_" + i + "_cell", cell == null ? "" : new String(cell));
}
prop.put("showtable_list_" + count + "_columns", columns.size());
@ -223,7 +223,7 @@ public class Tables_p {
int count = 0;
byte[] cell;
for (String col: columns) {
cell = row.from(col);
cell = row.get(col);
prop.put("showedit_list_" + count + "_key", col);
prop.put("showedit_list_" + count + "_value", cell == null ? "" : new String(cell));
count++;

View File

@ -95,7 +95,7 @@ public class table_p {
prop.put("showtable_list_" + count + "_showpk_pk", new String(trow.getPK()));
prop.put("showtable_list_" + count + "_count", count);
for (int i = 0; i < columns.size(); i++) {
cell = trow.from(columns.get(i));
cell = trow.get(columns.get(i));
prop.putHTML("showtable_list_" + count + "_columns_" + i + "_column", columns.get(i));
prop.putHTML("showtable_list_" + count + "_columns_" + i + "_cell", cell == null ? "" : new String(cell));
}

View File

@ -45,8 +45,15 @@ public class WorkTables extends Tables {
public final static String TABLE_API_COL_TYPE = "type";
public final static String TABLE_API_COL_COMMENT = "comment";
public final static String TABLE_API_COL_DATE = "date";
public final static String TABLE_API_COL_DATE_RECORDING = "date_recording"; // if not present default to old date field
public final static String TABLE_API_COL_DATE_LAST_EXEC = "date_last_exec"; // if not present default to old date field
public final static String TABLE_API_COL_DATE_NEXT_EXEC = "date_next_exec"; // if not present default to zero
public final static String TABLE_API_COL_DATE = "date"; // old date; do not set in new records
public final static String TABLE_API_COL_URL = "url";
public final static String TABLE_API_COL_APICALL_PK = "apicall_pk"; // the primary key for the table entry of that api call (not really a database field, only a name in the apicall)
public final static String TABLE_API_COL_APICALL_COUNT = "apicall_count"; // counts how often the API was called (starts with 1)
public final static String TABLE_API_COL_APICALL_SCHEDULE_TIME = "apicall_schedule_time"; // factor for SCHEULE_UNIT time units
public final static String TABLE_API_COL_APICALL_SCHEDULE_UNIT= "apicall_schedule_unit"; // may be 'minutes', 'hours', 'days'
public final static String TABLE_ROBOTS_NAME = "robots";
@ -56,15 +63,60 @@ public class WorkTables extends Tables {
}
public void recordAPICall(final serverObjects post, final String servletName, final String type, final String comment) {
// remove the apicall attributes from the post object
String pk = post.remove(TABLE_API_COL_APICALL_PK);
String count = post.remove(TABLE_API_COL_APICALL_COUNT);
if (count == null) count = "1";
String time = post.remove(TABLE_API_COL_APICALL_SCHEDULE_TIME);
String unit = post.remove(TABLE_API_COL_APICALL_SCHEDULE_UNIT);
if (time == null || unit == null || unit.length() == 0 || "minues,hours,days".indexOf(unit) < 0) {
time = ""; unit = "";
}
// generate the apicall url - without the apicall attributes
final String apiurl = /*"http://localhost:" + getConfig("port", "8080") +*/ "/" + servletName + "?" + post.toString();
// read old entry from the apicall table (if exists)
Row row = null;
try {
super.insert(
TABLE_API_NAME,
TABLE_API_COL_TYPE, type.getBytes(),
TABLE_API_COL_COMMENT, comment.getBytes(),
TABLE_API_COL_DATE, DateFormatter.formatShortMilliSecond(new Date()).getBytes(),
TABLE_API_COL_URL, apiurl.getBytes()
);
row = (pk == null) ? null : super.select(TABLE_API_NAME, pk.getBytes());
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {
Log.logException(e);
}
// insert or update entry
try {
if (row != null) {
// modify and update existing entry
// modify date attributes and patch old values
row.put(TABLE_API_COL_DATE_LAST_EXEC, DateFormatter.formatShortMilliSecond(new Date()).getBytes());
if (!row.containsKey(TABLE_API_COL_DATE_RECORDING)) row.put(TABLE_API_COL_DATE_RECORDING, row.get(TABLE_API_COL_DATE));
row.remove(TABLE_API_COL_DATE);
// insert APICALL attributes
row.put(TABLE_API_COL_APICALL_COUNT, count.getBytes());
row.put(TABLE_API_COL_APICALL_SCHEDULE_TIME, time.getBytes());
row.put(TABLE_API_COL_APICALL_SCHEDULE_UNIT, unit.getBytes());
super.update(TABLE_API_NAME, row);
} else {
// create and insert new entry
Data data = new Data();
data.put(TABLE_API_COL_TYPE, type.getBytes());
data.put(TABLE_API_COL_COMMENT, comment.getBytes());
byte[] date = DateFormatter.formatShortMilliSecond(new Date()).getBytes();
data.put(TABLE_API_COL_DATE_RECORDING, date);
data.put(TABLE_API_COL_DATE_LAST_EXEC, date);
data.put(TABLE_API_COL_URL, apiurl.getBytes());
// insert APICALL attributes
data.put(TABLE_API_COL_APICALL_COUNT, count.getBytes());
data.put(TABLE_API_COL_APICALL_SCHEDULE_TIME, time.getBytes());
data.put(TABLE_API_COL_APICALL_SCHEDULE_UNIT, unit.getBytes());
super.insert(TABLE_API_NAME, data);
}
} catch (IOException e) {
Log.logException(e);
} catch (RowSpaceExceededException e) {

View File

@ -92,6 +92,7 @@ public class Client {
private String userAgent = null;
private String host = null;
private boolean redirecting = true;
private String realm = null;
public Client() {
super();
@ -221,6 +222,14 @@ public class Client {
this.redirecting = redirecting;
}
/**
* set the authorization realm
* @param realm
*/
public void setRealm(final String realm) {
this.realm = realm;
}
/**
* This method GETs a page from the server.
*
@ -254,12 +263,12 @@ public class Client {
* @throws IOException
*/
public void GET(final String uri) throws IOException {
if (currentRequest != null) throw new IOException("Client is in use!");
final HttpGet httpGet = new HttpGet(uri);
currentRequest = httpGet;
execute(httpGet);
if (currentRequest != null) throw new IOException("Client is in use!");
final HttpGet httpGet = new HttpGet(uri);
currentRequest = httpGet;
execute(httpGet);
}
/**
* This method gets HEAD response
*
@ -326,6 +335,15 @@ public class Client {
return httpResponse;
}
/**
*
* @return status code from http request
*/
public int getStatusCode() {
return httpResponse.getStatusLine().getStatusCode();
}
public void writeTo(final OutputStream outputStream) throws IOException {
if (httpResponse != null && currentRequest != null) {
final HttpEntity httpEntity = httpResponse.getEntity();
@ -409,6 +427,8 @@ public class Client {
httpUriRequest.addHeader(header);
}
}
if (realm != null)
httpUriRequest.setHeader("Authorization", "realm=" + realm);
}
private void setParams(final HttpParams httpParams) {

View File

@ -115,62 +115,11 @@ public class BEncodedHeap implements Iterable<Map.Entry<byte[], Map<String, byte
this.columnames.addAll(map.keySet());
}
public void put(
byte[] pk,
String key, byte[] value
) throws IOException {
public void put(byte[] pk, String key, byte[] value) throws IOException {
byte[] b = BEncoder.encodeMap(key, value);
this.table.put(pk, b);
this.columnames.add(key);
}
public void put(
byte[] pk,
String key0, byte[] value0,
String key1, byte[] value1
) throws IOException {
byte[] b = BEncoder.encodeMap(
key0, value0,
key1, value1
);
this.table.put(pk, b);
this.columnames.add(key0);
this.columnames.add(key1);
}
public void put(
byte[] pk,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2
) throws IOException {
byte[] b = BEncoder.encodeMap(
key0, value0,
key1, value1,
key2, value2
);
this.table.put(pk, b);
this.columnames.add(key0);
this.columnames.add(key1);
this.columnames.add(key2);
}
public void put(
byte[] pk,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2,
String key3, byte[] value3
) throws IOException {
byte[] b = BEncoder.encodeMap(
key0, value0,
key1, value1,
key2, value2,
key3, value3
);
this.table.put(pk, b);
this.columnames.add(key0);
this.columnames.add(key1);
this.columnames.add(key2);
this.columnames.add(key3);
}
/**
* select a map from the table

View File

@ -29,10 +29,13 @@ package net.yacy.kelondro.blob;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
@ -41,6 +44,7 @@ import java.util.regex.Pattern;
import net.yacy.kelondro.index.RowSpaceExceededException;
import net.yacy.kelondro.logging.Log;
import net.yacy.kelondro.util.ByteBuffer;
import net.yacy.kelondro.util.DateFormatter;
import net.yacy.kelondro.util.FileUtils;
import net.yacy.kelondro.util.LookAheadIterator;
@ -135,9 +139,9 @@ public class Tables {
if (row == null) {
// table counter entry in pkcounter table does not exist: make a new table entry
row = new Row(tablename.getBytes(), system_table_pkcounter_counterName, int2key(0).getBytes());
insert(system_table_pkcounter, row);
update(system_table_pkcounter, row);
}
byte[] pk = row.from(system_table_pkcounter_counterName);
byte[] pk = row.get(system_table_pkcounter_counterName);
int pki;
if (pk == null) {
pki = size(tablename);
@ -170,110 +174,13 @@ public class Tables {
*/
public byte[] insert(final String tablename, Map<String, byte[]> map) throws IOException, RowSpaceExceededException {
byte[] uk = ukey(tablename);
insert(tablename, uk, map);
insert(system_table_pkcounter, tablename.getBytes(), system_table_pkcounter_counterName, uk);
update(tablename, uk, map);
BEncodedHeap heap = getHeap(system_table_pkcounter);
heap.put(tablename.getBytes(), system_table_pkcounter_counterName, uk);
return uk;
}
public byte[] insert(final String tablename, String key, byte[] value) throws IOException, RowSpaceExceededException {
byte[] uk = ukey(tablename);
insert(tablename, uk, key, value);
insert(system_table_pkcounter, tablename.getBytes(), system_table_pkcounter_counterName, uk);
return uk;
}
public byte[] insert(final String tablename,
String key0, byte[] value0,
String key1, byte[] value1
) throws IOException, RowSpaceExceededException {
byte[] uk = ukey(tablename);
insert(tablename, uk,
key0, value0,
key1, value1
);
insert(system_table_pkcounter, tablename.getBytes(), system_table_pkcounter_counterName, uk);
return uk;
}
public byte[] insert(final String tablename,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2
) throws IOException, RowSpaceExceededException {
byte[] uk = ukey(tablename);
insert(tablename, uk,
key0, value0,
key1, value1,
key2, value2
);
insert(system_table_pkcounter, tablename.getBytes(), system_table_pkcounter_counterName, uk);
return uk;
}
public byte[] insert(final String tablename,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2,
String key3, byte[] value3
) throws IOException, RowSpaceExceededException {
byte[] uk = ukey(tablename);
insert(tablename, uk,
key0, value0,
key1, value1,
key2, value2,
key3, value3
);
insert(system_table_pkcounter, tablename.getBytes(), system_table_pkcounter_counterName, uk);
return uk;
}
public void insert(final String table, byte[] pk,
String key, byte[] value
) throws IOException {
BEncodedHeap heap = getHeap(table);
heap.put(pk, key, value);
}
public void insert(final String table, byte[] pk,
String key0, byte[] value0,
String key1, byte[] value1
) throws IOException {
BEncodedHeap heap = getHeap(table);
heap.put(pk,
key0, value0,
key1, value1
);
}
public void insert(final String table, byte[] pk,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2
) throws IOException {
BEncodedHeap heap = getHeap(table);
heap.put(pk,
key0, value0,
key1, value1,
key2, value2
);
}
public void insert(final String table, byte[] pk,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2,
String key3, byte[] value3
) throws IOException {
BEncodedHeap heap = getHeap(table);
heap.put(pk,
key0, value0,
key1, value1,
key2, value2,
key3, value3
);
}
public void insert(final String table, byte[] pk, Map<String, byte[]> map) throws IOException {
public void update(final String table, byte[] pk, Map<String, byte[]> map) throws IOException {
BEncodedHeap heap = getHeap(table);
try {
heap.put(pk, map);
@ -282,10 +189,10 @@ public class Tables {
}
}
public void insert(final String table, Row row) throws IOException {
public void update(final String table, Row row) throws IOException {
BEncodedHeap heap = getHeap(table);
try {
heap.put(row.pk, row.map);
heap.put(row.pk, row);
} catch (RowSpaceExceededException e) {
throw new IOException(e.getMessage());
}
@ -348,9 +255,12 @@ public class Tables {
byte[] r;
while ((maxcount < 0 || maxcount-- > 0) && rowIterator.hasNext()) {
row = rowIterator.next();
r = row.from(sortColumn);
if (r == null) continue;
sortTree.put(new String(r) + new String(row.pk), row);
r = row.get(sortColumn);
if (r == null) {
sortTree.put("0000" + new String(row.pk), row);
} else {
sortTree.put(new String(r) + new String(row.pk), row);
}
}
return sortTree.values();
}
@ -432,7 +342,7 @@ public class Tables {
while (i.hasNext()) {
Row r = new Row(i.next());
if (this.whereValue != null) {
if (ByteBuffer.equals(r.from(this.whereColumn), this.whereValue)) return r;
if (ByteBuffer.equals(r.get(this.whereColumn), this.whereValue)) return r;
} else if (this.wherePattern != null) {
if (this.whereColumn == null) {
// shall match any column
@ -441,7 +351,7 @@ public class Tables {
}
} else {
// must match the given column
if (this.wherePattern.matcher(new String(r.from(this.whereColumn))).matches()) return r;
if (this.wherePattern.matcher(new String(r.get(this.whereColumn))).matches()) return r;
}
} else {
return r;
@ -452,60 +362,119 @@ public class Tables {
}
public class Row {
public class Data extends LinkedHashMap<String, byte[]> {
final byte[] pk;
final Map<String, byte[]> map;
private static final long serialVersionUID = 978426054043749337L;
public Row(final Map.Entry<byte[], Map<String, byte[]>> entry) {
public Data() {
super();
}
private Data(final Map<String, byte[]> map) {
super();
assert map != null;
this.putAll(map);
}
public void put(String colname, String value) {
super.put(colname, value.getBytes());
}
public void put(String colname, int value) {
super.put(colname, Integer.toString(value).getBytes());
}
public void put(String colname, long value) {
super.put(colname, Long.toString(value).getBytes());
}
public void put(String colname, Date value) {
super.put(colname, DateFormatter.formatShortMilliSecond(value).getBytes());
}
public byte[] get(String colname, byte[] dflt) {
byte[] r = this.get(colname);
if (r == null) return dflt;
return r;
}
public String get(String colname, String dflt) {
byte[] r = this.get(colname);
if (r == null) return dflt;
return new String(r);
}
public int get(String colname, int dflt) {
byte[] r = this.get(colname);
if (r == null) return dflt;
try {
return Integer.parseInt(new String(r));
} catch (NumberFormatException e) {
return dflt;
}
}
public long get(String colname, long dflt) {
byte[] r = this.get(colname);
if (r == null) return dflt;
try {
return Long.parseLong(new String(r));
} catch (NumberFormatException e) {
return dflt;
}
}
public Date get(String colname, Date dflt) {
byte[] r = this.get(colname);
if (r == null) return dflt;
try {
return DateFormatter.parseShortMilliSecond(new String(r));
} catch (ParseException e) {
return dflt;
}
}
}
public class Row extends Data {
private static final long serialVersionUID = 978426054043749338L;
private final byte[] pk;
private Row(final Map.Entry<byte[], Map<String, byte[]>> entry) {
super(entry.getValue());
assert entry != null;
assert entry.getKey() != null;
assert entry.getValue() != null;
this.pk = entry.getKey();
this.map = entry.getValue();
}
public Row(final byte[] pk, final Map<String, byte[]> map) {
private Row(final byte[] pk, final Map<String, byte[]> map) {
super(map);
assert pk != null;
assert map != null;
this.pk = pk;
this.map = map;
}
public Row(final byte[] pk, String k0, byte[] v0) {
private Row(final byte[] pk, String k0, byte[] v0) {
super();
assert k0 != null;
assert v0 != null;
Map<String, byte[]> map = new ConcurrentHashMap<String, byte[]>();
map.put(k0, v0);
this.put(k0, v0);
this.pk = pk;
this.map = map;
}
public byte[] getPK() {
return this.pk;
}
public byte[] from(String colname) {
return this.map.get(colname);
}
public byte[] from(String colname, byte[] dflt) {
byte[] r = this.map.get(colname);
if (r == null) return dflt;
return r;
}
protected Collection<byte[]> values() {
return this.map.values();
}
public String toString() {
StringBuilder sb = new StringBuilder(keymaxlen + 20 * map.size());
sb.append(new String(pk)).append(":").append(map.toString());
StringBuilder sb = new StringBuilder(keymaxlen + 20 * this.size());
sb.append(new String(pk)).append(":").append(super.toString());
return sb.toString();
}
}
public static void main(String[] args) {
// test the class
File f = new File(new File("maptest").getAbsolutePath());
@ -516,11 +485,11 @@ public class Tables {
// put some values into the map
Map<String, byte[]> m = new HashMap<String, byte[]>();
m.put("k", "000".getBytes());
map.insert("testdao", "123".getBytes(), m);
map.update("testdao", "123".getBytes(), m);
m.put("k", "111".getBytes());
map.insert("testdao", "456".getBytes(), m);
map.update("testdao", "456".getBytes(), m);
m.put("k", "222".getBytes());
map.insert("testdao", "789".getBytes(), m);
map.update("testdao", "789".getBytes(), m);
// iterate over keys
Iterator<Row> i = map.iterator("testdao");
while (i.hasNext()) {

View File

@ -169,65 +169,17 @@ public class BDecoder {
public void toStream(OutputStream os) throws IOException {
os.write(_d);
for (Map.Entry<String, BObject> e: this.m.entrySet()) {
new BStringObject(e.getKey().getBytes()).toStream(os);
BStringObject.toStream(os, e.getKey());
e.getValue().toStream(os);
}
os.write(_e);
}
public static void toStream(
OutputStream os,
String key, byte[] value
) throws IOException {
public static void toStream(OutputStream os, String key, byte[] value) throws IOException {
os.write(_d);
BStringObject.toStream(os, key);
BStringObject.toStream(os, value);
os.write(_e);
}
public static void toStream(
OutputStream os,
String key0, byte[] value0,
String key1, byte[] value1
) throws IOException {
os.write(_d);
BStringObject.toStream(os, key0);
BStringObject.toStream(os, value0);
BStringObject.toStream(os, key1);
BStringObject.toStream(os, value1);
os.write(_e);
}
public static void toStream(
OutputStream os,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2
) throws IOException {
os.write(_d);
BStringObject.toStream(os, key0);
BStringObject.toStream(os, value0);
BStringObject.toStream(os, key1);
BStringObject.toStream(os, value1);
BStringObject.toStream(os, key2);
BStringObject.toStream(os, value2);
os.write(_e);
}
public static void toStream(
OutputStream os,
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2,
String key3, byte[] value3
) throws IOException {
os.write(_d);
BStringObject.toStream(os, key0);
BStringObject.toStream(os, value0);
BStringObject.toStream(os, key1);
BStringObject.toStream(os, value1);
BStringObject.toStream(os, key2);
BStringObject.toStream(os, value2);
BStringObject.toStream(os, key3);
BStringObject.toStream(os, value3);
os.write(_e);
}
}
public static class BIntegerObject extends BDfltObject implements BObject {

View File

@ -71,7 +71,6 @@ public class BEncoder {
} catch (IOException e) {}
return null;
}
public static byte[] encodeMap(String key, byte[] value) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
@ -81,7 +80,8 @@ public class BEncoder {
} catch (IOException e) {}
return null;
}
/*
public static byte[] encodeMap(
String key0, byte[] value0,
String key1, byte[] value1
@ -139,6 +139,29 @@ public class BEncoder {
return null;
}
public static byte[] encodeMap(
String key0, byte[] value0,
String key1, byte[] value1,
String key2, byte[] value2,
String key3, byte[] value3,
String key4, byte[] value4
) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
BDecoder.BDictionaryObject.toStream(
baos,
key0, value0,
key1, value1,
key2, value2,
key3, value3,
key4, value4
);
baos.close();
return baos.toByteArray();
} catch (IOException e) {}
return null;
}
*/
public static void main(final String[] args) {
Map<String, byte[]> m = new HashMap<String, byte[]>();
m.put("k", "000".getBytes());

View File

@ -43,6 +43,9 @@ public final class DateFormatter {
/** minimal date format including milliseconds (fixed width: 17) */
public static final String PATTERN_SHORT_MILSEC = "yyyyMMddHHmmssSSS";
/** special time format for two-line display in html tables **/
public static final String PATTERN_HTML = "dd'&nbsp;'MMM'&nbsp;'yyyy HH:mm:ss";
/** default HTTP 1.1 header date format pattern */
public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss Z"; // with numeric time zone indicator as defined in RFC5322
public static final String PATTERN_RFC1123_SHORT = "EEE, dd MMM yyyy";
@ -68,6 +71,9 @@ public final class DateFormatter {
/** Date formatter/parser for minimal yyyyMMddHHmmssSSS pattern */
private static final SimpleDateFormat FORMAT_SHORT_MILSEC = new SimpleDateFormat(PATTERN_SHORT_MILSEC, Locale.US);
/** special time format for two-line display in html tables **/
private static final SimpleDateFormat FORMAT_HTML = new SimpleDateFormat(PATTERN_HTML, Locale.US);
/** Date formatter/non-sloppy parser for W3C datetime (ISO8601) in GMT/UTC */
private static final SimpleDateFormat FORMAT_ISO8601 = new SimpleDateFormat(PATTERN_ISO8601, Locale.US);
@ -170,6 +176,11 @@ public final class DateFormatter {
return FORMAT_RFC1123_SHORT.format(date);
}
public static String formatHTML(final Date date) {
if (date == null) return "";
return FORMAT_HTML.format(date);
}
/**
* Parse dates as defined in {@linkplain http://www.w3.org/TR/NOTE-datetime}.