package org.basex.core;
import static org.basex.core.Text.*;
import static org.basex.util.Token.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import org.basex.io.IO;
import org.basex.io.IOFile;
import org.basex.io.in.DataInput;
import org.basex.io.out.DataOutput;
import org.basex.server.ClientListener;
import org.basex.server.Sessions;
import org.basex.util.TokenBuilder;
import org.basex.util.Util;
/**
* This class organizes all known events.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
* @author Roman Raedle
* @author Andreas Weiler
*/
public final class Events extends HashMap<String, Sessions> {
/** Event file. */
private final IOFile file = new IOFile(Prop.HOME, IO.BASEXSUFFIX + "events");
/**
* Constructor.
*/
public Events() {
if(!file.exists()) return;
DataInput in = null;
try {
in = new DataInput(file);
final int s = in.readNum();
for(int u = 0; u < s; ++u) put(string(in.readToken()), new Sessions());
} catch(final IOException ex) {
Util.errln(ex);
} finally {
if(in != null) try { in.close(); } catch(final IOException ex) { }
}
}
/**
* Creates an event.
* @param name event name
* @return success flag
*/
public synchronized boolean create(final String name) {
final boolean b = put(name, new Sessions()) == null;
if(b) write();
return b;
}
/**
* Drops an event.
* @param name event name
* @return success flag
*/
public synchronized boolean drop(final String name) {
final boolean b = remove(name) != null;
if(b) write();
return b;
}
/**
* Writes global permissions to disk.
*/
private synchronized void write() {
try {
final DataOutput out = new DataOutput(file);
out.writeNum(size());
for(final String name : keySet()) out.writeToken(token(name));
out.close();
} catch(final IOException ex) {
Util.debug(ex);
}
}
/**
* Returns information on all events.
* @return information on all events.
*/
public synchronized String info() {
final TokenBuilder tb = new TokenBuilder();
tb.addExt(EVENTS_X, size()).add(size() != 0 ? COL : DOT);
final String[] names = keySet().toArray(new String[size()]);
Arrays.sort(names);
for(final String n : names) tb.add(NL).add(LI).add(n);
return tb.toString();
}
/**
* Notifies the watching sessions about an event.
* @param ctx database context
* @param name name
* @param msg message
* @return success flag
*/
public synchronized boolean notify(final Context ctx, final byte[] name,
final byte[] msg) {
final Sessions sess = get(string(name));
// event was not found
if(sess == null) return false;
// refresh timestamp for last interaction
for(final ClientListener srv : sess) {
// ignore active client
if(srv == ctx.listener) continue;
try {
srv.notify(name, msg);
} catch(final IOException ex) {
// remove client if event could not be delivered
sess.remove(srv);
}
}
return true;
}
}