aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Kropf <josh@slashdev.ca>2011-05-25 20:40:02 (GMT)
committerJosh Kropf <josh@slashdev.ca>2011-05-25 20:40:02 (GMT)
commit5b75f5f5db2233f5d9df7875571cd66f4daa47dc (patch)
tree904d0851ee0fe907d0948ab1b854ec5e20fe6330
parentc3dd82151a0b018b1ac6af59a9ef7d346b603528 (diff)
downloadlog4bb-5b75f5f5db2233f5d9df7875571cd66f4daa47dc.zip
log4bb-5b75f5f5db2233f5d9df7875571cd66f4daa47dc.tar.gz
log4bb-5b75f5f5db2233f5d9df7875571cd66f4daa47dc.tar.bz2
fixed several bugs in un/registering log adapters
-rw-r--r--src/com/jiggak/log/LogAdapter.java14
-rw-r--r--src/com/jiggak/log/Logger.java78
-rw-r--r--src/com/jiggak/log/adapter/UsbAdapter.java146
3 files changed, 190 insertions, 48 deletions
diff --git a/src/com/jiggak/log/LogAdapter.java b/src/com/jiggak/log/LogAdapter.java
index 26be7ba..4f384c1 100644
--- a/src/com/jiggak/log/LogAdapter.java
+++ b/src/com/jiggak/log/LogAdapter.java
@@ -9,7 +9,7 @@
package com.jiggak.log;
/**
- * Interface for logging subsystems.
+ * Interface for logging subsystems.
* @author Josh Kropf <josh@slashdev.ca>
*/
public abstract class LogAdapter {
@@ -18,19 +18,19 @@ public abstract class LogAdapter {
* @param init optional intialization parameter
*/
public abstract void create(Object init);
-
+
/**
* Handles unregistering of the logging system
*/
public abstract void destroy();
-
+
/**
* Logs a message to the logging system.
* @param message
* @param level one of the constants defined in Logger.LEVEL_*
*/
public abstract void log(String message, int level);
-
+
/**
* The {@link Logger} class will use the {@link Object#equals(Object)}
* method and pass it the adapter class name (without the package) to test
@@ -38,11 +38,11 @@ public abstract class LogAdapter {
*/
public boolean equals(Object obj) {
if (obj == null) return false;
-
+
if (obj instanceof String) {
- return this.getClass().getName().indexOf(obj.toString()) != -1;
+ return this.getClass().getName().endsWith(obj.toString());
}
-
+
return super.equals(obj);
}
}
diff --git a/src/com/jiggak/log/Logger.java b/src/com/jiggak/log/Logger.java
index ec4b7b0..25e0252 100644
--- a/src/com/jiggak/log/Logger.java
+++ b/src/com/jiggak/log/Logger.java
@@ -18,38 +18,38 @@ import net.rim.device.api.util.StringUtilities;
* @author Josh Kropf <josh@slashdev.ca>
*/
public final class Logger {
-
+
public static final int LEVEL_ERROR = 1;
public static final int LEVEL_WARN = 2;
public static final int LEVEL_INFO = 4;
public static final int LEVEL_DEBUG = 8;
-
+
private static final String ADAPTER_PACKAGE = "com.jiggak.log.adapter";
private static final String HASH = "com.jiggak.log.logger";
private static final long ID = StringUtilities.stringHashToLong(HASH);
private static RuntimeStore runtime = RuntimeStore.getRuntimeStore();
-
+
static {
// register the event log adapter by default
register("EventLoggerAdapter");
}
-
+
// string prefix for log messages
private String prefix;
-
+
/*
* Creates Log class with the given string prefix for all log messages
*/
private Logger(String prefix) {
this.prefix = prefix;
}
-
+
private static Vector adapters() {
Vector adapters = (Vector)runtime.get(ID);
if (adapters == null) runtime.put(ID, adapters=new Vector());
return adapters;
}
-
+
/**
* Gets an instance of Logger that logs messages for the given class
* @param clazz
@@ -58,12 +58,12 @@ public final class Logger {
public static Logger getLogger(Class clazz) {
// Class.getName returns fully qualified class name
String fqn = clazz.getName();
-
+
// get just the class name
String name = fqn.substring(fqn.lastIndexOf('.')+1);
return new Logger("["+name+"] ");
}
-
+
/**
* Registers a new log adapter
* @param adapterName class name (without package) of log adapter to register
@@ -74,30 +74,30 @@ public final class Logger {
if (adapters.contains(new Finder(adapterName))) {
unregister(adapterName);
}
-
+
LogAdapter adapter = null;
-
+
try {
String className = ADAPTER_PACKAGE + "." + adapterName;
adapter = (LogAdapter)Class.forName(className).newInstance();
- adapter.create(null);
+ adapter.create(init);
} catch (ClassNotFoundException e) {
throw new RuntimeException(adapterName+" class not found");
} catch (Exception e) {
throw new RuntimeException(adapterName+" instantiation failed: "+e);
}
-
+
adapters.addElement(adapter);
}
-
+
/**
- * Regsiter a new log adapter. Passes null for initialization parameter
+ * Register a new log adapter. Passes null for initialization parameter
* @see Logger#register(String, Object)
*/
public static void register(String adapterName) {
register(adapterName, null);
}
-
+
/**
* Unregisters a log adapter
* @param adapterName class name (without package)
@@ -105,20 +105,20 @@ public final class Logger {
*/
public static boolean unregister(String adapterName) {
Vector adapters = adapters();
-
+
int i = adapters.indexOf(new Finder(adapterName));
if (i != -1) {
LogAdapter a = (LogAdapter)adapters.elementAt(i);
a.destroy();
-
+
adapters.removeElementAt(i);
-
+
return true;
}
-
+
return false;
}
-
+
/**
* Get instance of registered adapter
* @param adapterName name of registered adapter
@@ -130,10 +130,10 @@ public final class Logger {
if (adapters.elementAt(i).getClass().getName().endsWith(adapterName))
return (LogAdapter)adapters.elementAt(i);
}
-
+
return null;
}
-
+
/**
* Lists currently registered adapters
* @return registered adapter names
@@ -142,15 +142,15 @@ public final class Logger {
Vector adapters = adapters();
String[] retval = new String[adapters.size()];
String name;
-
+
for (int i=adapters.size()-1; i>=0; i--) {
name = adapters.elementAt(i).getClass().getName();
retval[i] = name.substring(name.lastIndexOf('.')+1);
}
-
+
return retval;
}
-
+
/**
* Lists all available adapters
* @return available adapter names
@@ -158,9 +158,9 @@ public final class Logger {
public static String[] listAvailable() {
//TODO make adapter list dynamic
return new String[] {"BluetoothAdapter", "EventLoggerAdapter",
- "StdoutAdapter", "RollingAdapter"};
+ "StdoutAdapter", "RollingAdapter", "UsbAdapter"};
}
-
+
/*
* Central logging method... logs message to each logging system
*/
@@ -172,7 +172,7 @@ public final class Logger {
a.log(prefix+msg, level);
}
}
-
+
/**
* Returns string representation of the log level
* @param level log leve
@@ -187,7 +187,7 @@ public final class Logger {
default: return "UNKNOWN";
}
}
-
+
/**
* Logs a debug message
* @param msg log message
@@ -195,7 +195,7 @@ public final class Logger {
public void debug(String msg) {
log(msg, LEVEL_DEBUG);
}
-
+
/**
* Logs an information message
* @param msg log message
@@ -203,7 +203,7 @@ public final class Logger {
public void info(String msg) {
log(msg, LEVEL_INFO);
}
-
+
/**
* Logs a warning message
* @param msg log message
@@ -211,7 +211,7 @@ public final class Logger {
public void warn(String msg) {
log(msg, LEVEL_WARN);
}
-
+
/**
* Logs an error message
* @param msg log message
@@ -219,7 +219,7 @@ public final class Logger {
public void error(String msg) {
log(msg, LEVEL_ERROR);
}
-
+
/**
* Logs an error message and appends the class name of the exception
* and the exception message
@@ -234,16 +234,12 @@ public final class Logger {
class Finder {
private String _adapterName;
-
+
public Finder(String adapterName) {
_adapterName = adapterName;
}
-
+
public boolean equals(Object obj) {
- if (obj instanceof LogAdapter) {
- return obj.equals(_adapterName);
- } else {
- return false;
- }
+ return obj.getClass().getName().endsWith(_adapterName);
}
}
diff --git a/src/com/jiggak/log/adapter/UsbAdapter.java b/src/com/jiggak/log/adapter/UsbAdapter.java
new file mode 100644
index 0000000..368837d
--- /dev/null
+++ b/src/com/jiggak/log/adapter/UsbAdapter.java
@@ -0,0 +1,146 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <josh@slashdev.ca> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return Josh Kropf
+ * ----------------------------------------------------------------------------
+ */
+package com.jiggak.log.adapter;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.microedition.io.Connector;
+import javax.microedition.io.StreamConnection;
+
+import net.rim.device.api.system.Application;
+import net.rim.device.api.system.EventLogger;
+import net.rim.device.api.system.SystemListener2;
+import net.rim.device.api.util.DataBuffer;
+import net.rim.device.api.util.StringUtilities;
+
+import com.jiggak.log.LogAdapter;
+import com.jiggak.log.Logger;
+
+/**
+ * Sends log messages to a USB channel. See the USBDemo program inside the
+ * BlackBerry JDE samples, or read more at this link:
+ * http://www.netdirect.ca/software/packages/barry/rawchannel.php
+ * @author Josh Kropf <josh@slashdev.ca>
+ */
+public class UsbAdapter extends LogAdapter implements Runnable, SystemListener2 {
+ private static final String HASH = "com.jiggak.log.UsbAdapter";
+ private static final long GUID = StringUtilities.stringHashToLong(HASH);
+
+ static {
+ EventLogger.register(GUID, "log4bb-usb", EventLogger.VIEWER_STRING);
+ }
+
+ private static void _log(String msg, int level) {
+ EventLogger.logEvent(GUID, msg.getBytes(), level);
+ }
+
+ private String _channelName = "log4bb";
+
+ private boolean _connected = false;
+ private StreamConnection _conn;
+ private OutputStream _out;
+
+ private DataBuffer _buffer = new DataBuffer();
+
+ public void create(Object init) {
+ Application.getApplication().addSystemListener(this);
+ if (init != null) {
+ _channelName = init.toString();
+ }
+ }
+
+ public /**
+ * Sends log messages to the blackberry EventLogger system.
+ * @author Josh Kropf <josh@slashdev.ca>
+ */void destroy() {
+ Application.getApplication().removeSystemListener(this);
+ disconnect();
+ }
+
+ public void log(String message, int level) {
+ if (_connected) {
+ StringBuffer buff = new StringBuffer();
+ buff.append(Logger.levelToString(level)).append(' ');
+ buff.append(message).append('\n').append('\r');
+
+ synchronized (_buffer) {
+ _buffer.write(buff.toString().getBytes());
+ synchronized (this) { notify(); }
+ }
+ }
+ }
+
+ private void connect() {
+ _log("USB connected", EventLogger.INFORMATION);
+
+ try {
+ _conn = (StreamConnection)Connector.open("comm:USB;channel=" + _channelName);
+ _out = _conn.openOutputStream();
+ _connected = true;
+
+ new Thread(this).start();
+ } catch (IOException e) {
+ _log("error setting up USB channel: "+e.toString(), EventLogger.ERROR);
+ }
+ }
+
+ private void disconnect() {
+ _log("USB disconnected", EventLogger.INFORMATION);
+ _connected = false;
+ synchronized (this) { notify(); }
+ }
+
+ public void run() {
+ try {
+ while (_connected) {
+ synchronized (this) { wait(); }
+
+ if (_buffer.getArrayLength() > 0) {
+ synchronized (_buffer) {
+ _out.write(_buffer.getArray(), 0, _buffer.getArrayLength());
+ _out.flush();
+ _buffer.reset();
+ }
+ }
+ }
+ } catch(Exception e) {
+ _log("USB output thread died: "+e.toString(), EventLogger.ERROR);
+ _connected = false;
+ } finally {
+ if (_out != null) {
+ try { _out.close(); }
+ catch (IOException e) { }
+ }
+
+ if (_conn != null) {
+ try { _conn.close(); }
+ catch (IOException e) { }
+ }
+ }
+ }
+
+ public void usbConnectionStateChange(int state) {
+ if (state == USB_STATE_CABLE_CONNECTED) {
+ connect();
+ } else if (state == USB_STATE_CABLE_DISCONNECTED) {
+ disconnect();
+ }
+ }
+
+ public void backlightStateChange(boolean on) { }
+ public void batteryGood() { }
+ public void batteryLow() { }
+ public void batteryStatusChange(int status) { }
+ public void cradleMismatch(boolean mismatch) { }
+ public void fastReset() { }
+ public void powerOff() { }
+ public void powerOffRequested(int reason) { }
+ public void powerUp() { }
+}