summaryrefslogtreecommitdiffstats
path: root/src/main/java/org/openslx/thrifthelper
diff options
context:
space:
mode:
authorJonathan Bauer2015-03-04 17:02:45 +0100
committerJonathan Bauer2015-03-04 17:02:45 +0100
commitd871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb (patch)
treec40e57d523e6f5b9eda15281e60f27a088502220 /src/main/java/org/openslx/thrifthelper
parentAdd Dozmod Version file (diff)
downloadmaster-sync-shared-d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb.tar.gz
master-sync-shared-d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb.tar.xz
master-sync-shared-d871f98fa6fbb9cdf479ec149eb513c1fc9bf1bb.zip
moved ThriftManager and ThriftHandler to master-sync-shared
Diffstat (limited to 'src/main/java/org/openslx/thrifthelper')
-rw-r--r--src/main/java/org/openslx/thrifthelper/ThriftHandler.java101
-rw-r--r--src/main/java/org/openslx/thrifthelper/ThriftManager.java147
2 files changed, 248 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/thrifthelper/ThriftHandler.java b/src/main/java/org/openslx/thrifthelper/ThriftHandler.java
new file mode 100644
index 0000000..ed66678
--- /dev/null
+++ b/src/main/java/org/openslx/thrifthelper/ThriftHandler.java
@@ -0,0 +1,101 @@
+package org.openslx.thrifthelper;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+import org.apache.thrift.TException;
+import org.apache.thrift.transport.TTransportException;
+
+public class ThriftHandler<T extends Object> implements InvocationHandler {
+
+ private final static Logger LOGGER = Logger.getLogger(ThriftHandler.class);
+
+ public interface ClientCreationCallback<T> {
+ public T get();
+ }
+
+ private final ThreadLocal<T> clients = new ThreadLocal<T>();
+ private final ClientCreationCallback<T> callback;
+
+ public ThriftHandler(final Class<T> clazz, ClientCreationCallback<T> cb) {
+ callback = cb;
+ thriftMethods = Collections.unmodifiableSet(new HashSet<String>() {
+ private static final long serialVersionUID = 8983506538154055231L;
+ {
+ Method[] methods = clazz.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ boolean thrift = false;
+ Class<?>[] type = methods[i].getExceptionTypes();
+ for (int e = 0; e < type.length; e++) {
+ if (TException.class.isAssignableFrom(type[e]))
+ thrift = true;
+
+ }
+ String name = methods[i].getName();
+ if (thrift && !name.startsWith("send_") && !name.startsWith("recv_")) {
+ add(name);
+ }
+ }
+ }
+ });
+ }
+
+ private final Set<String> thriftMethods;
+
+ public Object invoke(Object tproxy, Method method, Object[] args) throws Throwable {
+
+ // first find the thrift methods
+ if (!thriftMethods.contains(method.getName())) {
+ try {
+ return method.invoke(method, args);
+ } catch (InvocationTargetException e) {
+ // TODO Auto-generated catch block
+ Throwable cause = e.getCause();
+ if (cause == null) {
+ throw new RuntimeException();
+ }
+ throw cause;
+ }
+ }
+ LOGGER.debug("Proxying '" + method.getName() + "'");
+
+ T client = getClient(false);
+ Throwable cause = null;
+ for (int i = 0; i < 3; i++) {
+ try {
+ return method.invoke(client, args);
+ } catch (InvocationTargetException e) {
+ cause = e.getCause();
+ if (cause instanceof TTransportException) {
+ LOGGER.debug("Transport error - re-initialising ...");
+ // new client
+ client = getClient(true);
+ }
+ }
+ }
+
+ if (cause != null)
+ throw cause;
+ return null;
+
+ }
+
+ private T getClient(boolean forceNew) {
+ T client = clients.get();
+ if (client != null && !forceNew) {
+ return client;
+ }
+ client = callback.get();
+ if (client == null) {
+ // TODO own exception
+ throw new RuntimeException();
+ }
+ clients.set(client);
+ return client;
+ }
+}
diff --git a/src/main/java/org/openslx/thrifthelper/ThriftManager.java b/src/main/java/org/openslx/thrifthelper/ThriftManager.java
new file mode 100644
index 0000000..c6d8986
--- /dev/null
+++ b/src/main/java/org/openslx/thrifthelper/ThriftManager.java
@@ -0,0 +1,147 @@
+package org.openslx.thrifthelper;
+
+import java.lang.reflect.Proxy;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.transport.TFramedTransport;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TTransportException;
+import org.openslx.imagemaster.thrift.iface.ImageServer;
+import org.openslx.sat.thrift.iface.Server;
+import org.openslx.thrifthelper.ThriftHandler.ClientCreationCallback;
+
+public class ThriftManager {
+
+ private final static Logger LOGGER = Logger.getLogger(ThriftManager.class);
+
+ /**
+ * Public variables to represent client types
+ * TODO: Public needed?
+ */
+ public static enum ClientType {
+ MASTER, SATELLITE
+ }
+ /**
+ * Private singleton instances of itself and the satellite/master clients
+ */
+ private static Server.Iface _satClient = (Server.Iface) Proxy.newProxyInstance(
+ Server.Iface.class.getClassLoader(),
+ new Class[] { Server.Iface.class }, new ThriftHandler<Server.Client>(Server.Client.class, new ClientCreationCallback<Server.Client>() {
+
+ @Override
+ public Server.Client get() {
+ // first check if we have a sat ip
+ if (SATELLITE_IP == null) {
+ LOGGER.error("Satellite ip adress was not set prior to getting the sat client. Use setSatellite(<ip>).");
+ return null;
+ }
+ // ok lets do it
+ TTransport transport =
+ new TSocket(SATELLITE_IP, SATELLITE_PORT, SATELLITE_TIMEOUT);
+ try {
+ transport.open();
+ } catch (TTransportException e) {
+ LOGGER.error("Could not open transport to thrift's server with IP: " + SATELLITE_IP);
+ return null;
+ }
+ final TProtocol protocol = new TBinaryProtocol(transport);
+ // now we are ready to create the client, according to ClientType!
+ LOGGER.info("Satellite '" + SATELLITE_IP + "' reachable. Client initialised.");
+ return new Server.Client(protocol);
+ }
+ }));
+
+ private static ImageServer.Iface _masterClient = (ImageServer.Iface) Proxy.newProxyInstance(
+ ImageServer.Iface.class.getClassLoader(),
+ new Class[] { ImageServer.Iface.class }, new ThriftHandler<ImageServer.Client>(ImageServer.Client.class, new ClientCreationCallback<ImageServer.Client>() {
+
+ @Override
+ public ImageServer.Client get() {
+ // ok lets do it
+ TTransport transport =
+ new TFramedTransport(new TSocket(MASTERSERVER_IP, MASTERSERVER_PORT, MASTERSERVER_TIMEOUT));
+ try {
+ transport.open();
+ } catch (TTransportException e) {
+ LOGGER.error("Could not open transport to thrift's server with IP: " + MASTERSERVER_IP);
+ return null;
+ }
+ final TProtocol protocol = new TBinaryProtocol(transport);
+ // now we are ready to create the client, according to ClientType!
+ return new ImageServer.Client(protocol);
+
+ }
+ }));
+ /**
+ * Private members for master connection information
+ */
+ private static final String MASTERSERVER_IP = "132.230.4.16";
+ private static final int MASTERSERVER_PORT = 9090;
+ private static final int MASTERSERVER_TIMEOUT = 30000;
+
+
+ /**
+ * Private members for satellite connection information
+ */
+ private static String SATELLITE_IP = null;
+ private static final int SATELLITE_PORT = 9090;
+ private static final int SATELLITE_TIMEOUT = 10000;
+
+ /**
+ * IP Validation Regex
+ */
+ private static final String IP_VALID_PATTERN =
+ "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
+ "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
+
+ /**
+ * Sets the IP of the satellite to connect to
+ * @param ip the ip of the satellite as String
+ * @return true if setting the ip worked, false otherwise
+ */
+ public static boolean setSatellite(String ip) {
+ if (ip.isEmpty()) {
+ LOGGER.error("Given IP for satellite is empty.");
+ return false;
+ }
+ // validate
+ Matcher matcher = Pattern.compile(IP_VALID_PATTERN).matcher(ip);
+ if (!matcher.matches()) {
+ LOGGER.error("Given form of IP is invalid: " + ip);
+ return false;
+ }
+ // finally set it
+ SATELLITE_IP = ip;
+
+ // last check: try to connect
+ if (getSatClient() == null) {
+ // init failed
+ LOGGER.error("Could not initialise new client to satellite: " + SATELLITE_IP);
+ return false;
+ }
+ // TODO final last: get version from server
+ return true;
+ }
+ /**
+ * Returns the singleton client of the thrift connection to the satellite
+ * @return the thrift client to the satellite server
+ */
+ public static Server.Iface getSatClient() {
+ return _satClient;
+ }
+
+ /**
+ * Returns the singleton client of the master thrift connection
+ * @return the thrift client to the master server
+ */
+ public static ImageServer.Iface getMasterClient() {
+ return _masterClient;
+ }
+}