/* * This file is part of Sensorium. * * Sensorium is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Sensorium 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Sensorium. If not, see * <http://www.gnu.org/licenses/>. * * */ package at.univie.sensorium; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.reflect.Field; import java.util.LinkedList; import java.util.List; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.text.Html; import android.util.Log; import android.widget.TextView; import at.univie.sensorium.extinterfaces.XMLRPCSensorServerThread; import at.univie.sensorium.logging.JSONLogger; import at.univie.sensorium.preferences.Preferences; import at.univie.sensorium.privacy.Privacy; import at.univie.sensorium.sensors.AbstractSensor; import at.univie.sensorium.sensors.SensorValue; public class SensorRegistry { public static final String TAG = "Sensorium"; private static SensorRegistry instance = null; private List<AbstractSensor> sensors; private StringBuffer debugBuffer; private int bufferedLines = 0; private static final int MAXDEBUGLINES = 20; private TextView textoutput; private Context context; private Preferences preferences; private JSONLogger jsonlogger; protected SensorRegistry() { sensors = new LinkedList<AbstractSensor>(); debugBuffer = new StringBuffer(); } public static SensorRegistry getInstance() { if (instance == null) { instance = new SensorRegistry(); } return instance; } public void startup(Context context) { this.context = context; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); for (AbstractSensor sensor : sensors) { try { boolean savedstate = prefs.getBoolean(sensor.getClass().getName(), true); Log.d(SensorRegistry.TAG, sensor.getClass().getName() + ": " + savedstate); if (savedstate) sensor.enable(); } catch (Exception e) { sensor.disable(); Log.d(SensorRegistry.TAG, e.toString()); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } } } public void registerSensor(AbstractSensor sensor) { for (AbstractSensor s : sensors) { if (s.getClass().equals(sensor.getClass())) { Log.d(SensorRegistry.TAG, "Sensor of this class already present, not registering."); return; } } sensors.add(sensor); } private AbstractSensor getSensorWithName(String classname) { for (AbstractSensor sensor : sensors) { String sensorname = sensor.getClass().getName(); sensorname = sensorname.substring(sensorname.lastIndexOf('.') + 1); if (sensorname.equals(classname) && sensor.isEnabled()) { return sensor; } } return null; } public void log(String tag, String out) { out = out.replaceAll("\r\n|\r|\n", " "); if (bufferedLines >= MAXDEBUGLINES) { debugBuffer.deleteCharAt(debugBuffer.length() - 1); debugBuffer.delete(debugBuffer.lastIndexOf("\n"), debugBuffer.length() - 1); bufferedLines--; } debugBuffer.insert(0, "<b>" + tag + ": </b>" + out + "<br>\n"); bufferedLines++; if (textoutput != null) textoutput.setText(Html.fromHtml(debugBuffer.toString()), TextView.BufferType.SPANNABLE); } public AbstractSensor getSensorForClassname(String classname) { for (AbstractSensor sensor : sensors) { String name = sensor.getClass().getName(); if (classname.lastIndexOf('.') > 0) { // we have a qualified name if (name.equals(classname)) return sensor; } else { name = name.substring(name.lastIndexOf('.') + 1); if (name.equals(classname)) { return sensor; } } } return null; } private SensorValue invokeMethod(String classname, String methodname) { AbstractSensor sensor = getSensorForClassname(classname); if (sensor != null) { if (sensor.isEnabled()) { Field[] fields = sensor.getClass().getDeclaredFields(); try { for (Field f : fields) { f.setAccessible(true); Object o = f.get(sensor); if (f.getName().equals(methodname) && o instanceof SensorValue) { return (SensorValue) o; } } } catch (IllegalArgumentException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } catch (IllegalAccessException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } } } return null; } public Object callSensorMethod(String methodname) { if (methodname.lastIndexOf('.') == -1) { Log.d("SeattleSensor", "Invalid XMLRPC method call"); return null; } String classname = methodname.substring(0, methodname.lastIndexOf('.')); methodname = methodname.substring(methodname.lastIndexOf('.') + 1); SensorValue val = invokeMethod(classname, methodname); if (val != null) { AbstractSensor sensor = getSensorWithName(classname); return Privacy.anonymize(val, sensor.getPrivacylevel()).getValue(); } return null; } public Object[] getSensorMethodSignature(String methodname) { List<String> signature = new LinkedList<String>(); if (methodname.lastIndexOf('.') > 0) { String classname = methodname.substring(0, methodname.lastIndexOf('.')); AbstractSensor sensor = getSensorForClassname(classname); if (sensor != null && sensor.isEnabled()) { Field[] fields = sensor.getClass().getDeclaredFields(); try { for (Field f : fields) { f.setAccessible(true); Object o = f.get(sensor); if (o instanceof SensorValue) { String fieldname = f.getName(); if (fieldname.equals(methodname.substring(methodname.lastIndexOf('.') + 1))) { signature.add(methodname); SensorValue sv = (SensorValue) o; String rettype = sv.getValue().getClass().toString(); // TODO: this will frequently be only String and // changing, // due to be set to "n/a" when no value is // present if (rettype.equals("class [Ljava.lang.Object;")) { signature.add("array"); } else if (rettype.equals("class java.lang.String")) { signature.add("string"); } else if (rettype.equals("class java.lang.Integer")) { signature.add("int"); } else if (rettype.equals("class java.lang.Boolean")) { signature.add("boolean"); } else if (rettype.equals("class java.lang.Double")) { signature.add("double"); } else if (rettype.equals("class java.lang.Float")) { signature.add("ex:float"); } else if (rettype.equals("class java.lang.Long")) { signature.add("ex:i8"); } else if (rettype.equals("class java.lang.Byte")) { signature.add("ex:i1"); } else if (rettype.equals("class java.lang.Short")) { signature.add("ex:i2"); } else { signature.add(rettype); } // add method parameters: always nil signature.add("ex:nil"); } } } } catch (IllegalArgumentException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } catch (IllegalAccessException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } } if (!signature.isEmpty()) return signature.toArray(); } return null; } public List<String> getSensorMethods() { List<String> out = new LinkedList<String>(); for (AbstractSensor sensor : sensors) { if (sensor.isEnabled()) { String name = sensor.getClass().getName(); name = name.substring(name.lastIndexOf('.') + 1); Field[] fields = sensor.getClass().getDeclaredFields(); try { for (Field f : fields) { f.setAccessible(true); Object o = f.get(sensor); if (o instanceof SensorValue) { out.add(name + "." + f.getName()); } } } catch (IllegalArgumentException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } catch (IllegalAccessException e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } } } return out; } XMLRPCSensorServerThread xmlrpcserverthread; Thread x; public void startXMLRPCInterface() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); boolean xmlrpc_enabled = prefs.getBoolean(Preferences.INTERFACES_XMLRPC_PREF, true); if(xmlrpc_enabled){ Log.d(SensorRegistry.TAG,"starting XMLRPC interface"); xmlrpcserverthread = new XMLRPCSensorServerThread(); x = new Thread(xmlrpcserverthread); x.start(); return; } else { Log.d(SensorRegistry.TAG,"Not starting XMLRPC interface, preference disabled"); } if (!XMLRPCSensorServerThread.running) { Log.d(SensorRegistry.TAG,"starting XMLRPC interface"); xmlrpcserverthread = new XMLRPCSensorServerThread(); x = new Thread(xmlrpcserverthread); x.start(); //return; } else { Log.d(SensorRegistry.TAG, "XMLRPC thread already running, not spawning another one."); } } public void stopXMLRPCInterface(){ if (XMLRPCSensorServerThread.running){ xmlrpcserverthread.stopThread(); x.interrupt(); try { x.join(); XMLRPCSensorServerThread.running = false; } catch (InterruptedException e) { Log.d("SeattleSensors:", e.toString()); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); Log.d(SensorRegistry.TAG, sw.toString()); } } else { Log.d(SensorRegistry.TAG, "XMLRPC thread not running, not attempting to stop it."); } } public JSONLogger getJSONLogger(){ return jsonlogger; } public void setJSONLogger(JSONLogger jsonlogger){ this.jsonlogger = jsonlogger; } public Context getContext(){ return context; } public Preferences getPreferences() { return preferences; } public void setPreferences(Preferences preferences) { this.preferences = preferences; } public void setDebugView(TextView t) { this.textoutput = t; } public List<AbstractSensor> getSensors() { return this.sensors; } }