/**
*
*/
package org.squidy.database;
import java.io.IOException;
import java.io.StringReader;
import java.net.ConnectException;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.basex.BaseXServer;
import org.basex.core.BaseXException;
import org.basex.server.ClientSession;
import org.basex.server.EventNotifier;
import org.squidy.Namespaces;
/**
* <code>BaseXSessionProvider</code>.
*
* <pre>
* Date: Dec 7, 2010
* Time: 1:57:27 PM
* </pre>
*
*
* @author Roman R�dle <a
* href="mailto:Roman.Raedle@uni-konstanz.de">Roman.Raedle
* @uni-konstanz.de</a> Human-Computer Interaction Group University of Konstanz
*
* @version $Id: BaseXSessionProvider.java 772 2011-09-16 15:39:44Z raedle $
* @since 1.5.0
*
*/
public class BaseXSessionProvider implements RemoteUpdatableSessionProvider<BaseXSession>, EventNotifier {
// A logger to log info, error, debug,... messages.
private static final Log LOG = LogFactory.getLog(BaseXSessionProvider.class);
private static BaseXSessionProvider provider;
public static BaseXSessionProvider get() {
if (provider == null)
provider = new BaseXSessionProvider();
return provider;
}
private String host;
public final String getHost() {
return host;
}
private int port;
public final int getPort() {
return port;
}
private String user;
public final String getUser() {
return user;
}
private String pw;
private String db;
public final String getDatabase() {
return db;
}
private BaseXSession session;
/**
*
*/
public BaseXSessionProvider() {
host = System.getProperty("host", "127.0.0.1");
port = Integer.parseInt(System.getProperty("port", "1984"));
user = System.getProperty("user", "admin");
pw = System.getProperty("pw", "admin");
db = System.getProperty("db", "squidy");
}
/* (non-Javadoc)
* @see org.squidy.database.SessionProvider#getSession()
*/
public BaseXSession getSession() {
if (session != null)
return session;
session = createSession();
return session;
}
/* (non-Javadoc)
* @see org.squidy.database.SessionProvider#createSession()
*/
public BaseXSession createSession() {
BaseXSession session = null;
try {
session = new BaseXSession(host, port, user, pw);
} catch (ConnectException e) {
if ("Connection refused".equals(e.getMessage())) {
if (LOG.isWarnEnabled())
LOG.warn("Could not connect to database " + db + " [host=" + host + ",port=" + port + ",user=" + user + "][cause=" + e.getMessage() + "]");
try {
startServer();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
return createSession();
}
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error(e);
}
if (session != null)
try {
String res = session.execute("open " + db);
if (LOG.isInfoEnabled())
LOG.info(res);
if (!res.isEmpty()) {
session.execute("create db " + db + " <common:Data xmlns:common='" + Namespaces.NAMESPACE_PREFIX_COMMON + "' />");
session.execute("open " + db);
}
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error(e);
}
if (session != null) {
try {
if (!containsTrigger(session))
session.execute("create event " + REMOTE_UPDATE_TRIGGER_NAME);
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error("Failed to create trigger " + REMOTE_UPDATE_TRIGGER_NAME, e);
}
try {
session.watch(REMOTE_UPDATE_TRIGGER_NAME, this);
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error("Failed to attach trigger " + REMOTE_UPDATE_TRIGGER_NAME, e);
}
}
return session;
}
private boolean containsTrigger(ClientSession session) throws IOException {
String triggers = session.execute("show events");
if (!triggers.isEmpty())
for (String trigger : triggers.split("\n")) {
if (trigger.equals(REMOTE_UPDATE_TRIGGER_NAME))
return true;
}
return false;
}
private void startServer() throws IOException {
final BaseXServer server = new BaseXServer("-p " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
super.run();
try {
server.stop();
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error("Could not stop server", e);
}
}
});
}
/* (non-Javadoc)
* @see org.squidy.database.SessionProvider#closeSession()
*/
public void closeSession() {
closeSession(session);
session = null;
}
/* (non-Javadoc)
* @see org.squidy.database.SessionProvider#closeSession(java.lang.Object)
*/
public void closeSession(BaseXSession session) {
if (session != null) {
try {
session.close();
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error("Could not close session.", e);
}
session = null;
}
}
// ################################################################################
// BEGIN REMOTE UPDATE
// ################################################################################
private boolean ignoreUpdateRemote = false;
public void setIgnoreUpdateRemote(boolean ignore) {
this.ignoreUpdateRemote = ignore;
}
public void updateRemote(RemoteUpdatable update) {
String type = update.getClass().getName();
String id = update.getId();
String serial = update.serialize();
try {
if (!ignoreUpdateRemote)
getSession().execute("db:event(" + REMOTE_UPDATE_TRIGGER_NAME + ", type" + RemoteUpdatable.KEY_VALUE_DELIMITER + type + RemoteUpdatable.KEY_VALUE_PAIR_DELIMITER + "id" + RemoteUpdatable.KEY_VALUE_DELIMITER + id + RemoteUpdatable.KEY_VALUE_PAIR_DELIMITER + "serial" + RemoteUpdatable.KEY_VALUE_DELIMITER + serial + ")");
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error(e);
}
}
public void notify(final String value) {
Properties props = new Properties();
try {
props.load(new StringReader(value));
String type = props.getProperty("type");
String id = props.getProperty("id");
if (id != null) {
RemoteUpdatable up = RemoteUpdatablePool.getRemoteUpdatable(id);
if (up != null) {
ignoreUpdateRemote = true;
up.deserialize(props.getProperty("serial"));
ignoreUpdateRemote = false;
}
else if ("org.squidy.designer.model.NodeShape".equals(type)) {
System.out.println(props.getProperty("serial"));
// else if (Processable.class.isAssignableFrom(type)) {
// // type=<processor_type>,processor=<id>,shape=<id>,layoutConstraintId=<id>,parent=<id>,x=<id>,y=<id>
// String processorId = addStr[1].split("=")[1];
// String id = addStr[2].split("=")[1];
// String layoutConstraintId = addStr[3].split("=")[1];
// String parentId = addStr[4].split("=")[1];
// double x = Double.parseDouble(addStr[5].split("=")[1]);
// double y = Double.parseDouble(addStr[6].split("=")[1]);
//
// Processable processable = ReflectionUtil.createInstance((Class<Processable>) type);
// processable.setId(processorId);
//
// ContainerShape parentShape = (ContainerShape<?, ?>) ShapeUtils.getShapeWithId(Designer.getInstance().data.getWorkspaceShape(), parentId);
// ActionShape<?, ?> shape = ShapeUtils.getActionShape(processable);
// shape.setId(id);
// shape.getLayoutConstraint().setId(layoutConstraintId);
//
// ((ContainerShape<?, Piping>) shape).setProcessable((Piping) processable);
// ((ContainerShape<?, Piping>) parentShape).getProcessable().addSubProcessable(processable);
// parentShape.addVisualShape(shape);
//
//// shape.setOffset(x, y);
//
// shape.setDraggable(true);
// }
}
}
} catch (IOException e) {
if (LOG.isErrorEnabled())
LOG.error(e);
}
}
// ################################################################################
// END REMOTE UPDATE
// ################################################################################
}