diff --git a/.gitignore b/.gitignore
index d84d4b06..1ac281bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,8 @@ target
integration/bundle/
integration/felix-cache/
runner
+.DS_Store
+*.iml
+*.ipr
+*.iws
diff --git a/pom.xml b/pom.xml
index 307c1fcf..d51b1d7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,7 @@
slf4j-jdk14slf4j-log4j12slf4j-jcl
+ slf4j-androidslf4j-extjcl-over-slf4jlog4j-over-slf4j
diff --git a/slf4j-android/.gitignore b/slf4j-android/.gitignore
new file mode 100755
index 00000000..d4790469
--- /dev/null
+++ b/slf4j-android/.gitignore
@@ -0,0 +1,9 @@
+/target
+/.settings
+/.classpath
+/.project
+/gen
+.DS_Store
+*.iml
+*.ipr
+*.iws
diff --git a/slf4j-android/AndroidManifest.xml b/slf4j-android/AndroidManifest.xml
new file mode 100755
index 00000000..b582bd8d
--- /dev/null
+++ b/slf4j-android/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/slf4j-android/LICENSE.txt b/slf4j-android/LICENSE.txt
new file mode 100644
index 00000000..508a2728
--- /dev/null
+++ b/slf4j-android/LICENSE.txt
@@ -0,0 +1,24 @@
+Copyright (c) 2004-2007 QOS.ch
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
diff --git a/slf4j-android/README.md b/slf4j-android/README.md
new file mode 100644
index 00000000..f87002da
--- /dev/null
+++ b/slf4j-android/README.md
@@ -0,0 +1,14 @@
+# SLF4J Android
+
+The motivation for the SLF4J Android project was to ease using existing libraries
+which use SLF4J as their logging framework on the [Google Android platform](http://developer.android.com).
+
+This project is a basic implementation that simply forwards all SLF4J log requests to the
+[logger](http://developer.android.com/reference/android/util/Log.html) provided by the Google Android platform.
+
+As slf4j-jdk14, slf4j-log4j etc. slf4j-android is a maven module that depends on slf4j-api only
+so it can easily be built with maven and synced with [the original slf4j codebase](https://github.com/qos-ch/slf4j).
+
+### Status
+The implementation is currently fully functional but has not yet been fully tested in a
+production environment. Let us know if you have used it in production!
diff --git a/slf4j-android/default.properties b/slf4j-android/default.properties
new file mode 100755
index 00000000..6e13d714
--- /dev/null
+++ b/slf4j-android/default.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+android.library=true
+# Project target.
+target=android-3
+apk-configurations=
diff --git a/slf4j-android/pom.xml b/slf4j-android/pom.xml
new file mode 100644
index 00000000..22b71be3
--- /dev/null
+++ b/slf4j-android/pom.xml
@@ -0,0 +1,81 @@
+
+
+
+ org.slf4j
+ slf4j-parent
+ 1.7.4
+
+
+ 4.0.0
+
+ slf4j-android
+
+ jar
+ SLF4J Android Binding
+ SLF4J Android Binding
+ http://www.slf4j.org
+
+
+
+ nordligulv
+ Andrey Korzhevskiy
+ Investment holding "FINAM" CJSC
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ org.slf4j
+ slf4j-api
+ test-jar
+ ${project.version}
+ test
+
+
+
+ com.google.android
+ android
+ 1.5_r4
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ false
+ ${parsedVersion.osgiVersion}
+ ${project.description}
+ ${project.version}
+
+ ${project.build.outputDirectory}/META-INF/MANIFEST.MF
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.5
+ 1.5
+
+
+
+
+
+
\ No newline at end of file
diff --git a/slf4j-android/src/main/java/org/slf4j/impl/AndroidLoggerAdapter.java b/slf4j-android/src/main/java/org/slf4j/impl/AndroidLoggerAdapter.java
new file mode 100755
index 00000000..78fc3641
--- /dev/null
+++ b/slf4j-android/src/main/java/org/slf4j/impl/AndroidLoggerAdapter.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.impl;
+
+import android.util.Log;
+import org.slf4j.helpers.FormattingTuple;
+import org.slf4j.helpers.MarkerIgnoringBase;
+import org.slf4j.helpers.MessageFormatter;
+
+/**
+ * A simple implementation that delegates all log requests to the Google Android
+ * logging facilities. Note that this logger does not support {@link org.slf4j.Marker}.
+ * That is, methods taking marker data simply invoke the corresponding method
+ * without the Marker argument, discarding any marker data passed as argument.
+ *
+ * The logging levels specified for SLF4J can be almost directly mapped to
+ * the levels that exist in the Google Android platform. The following table
+ * shows the mapping implemented by this logger.
+ *
+ *
+ *
SLF4J
Android
+ *
TRACE
{@link android.util.Log#VERBOSE}
+ *
DEBUG
{@link android.util.Log#DEBUG}
+ *
INFO
{@link android.util.Log#INFO}
+ *
WARN
{@link android.util.Log#WARN}
+ *
ERROR
{@link android.util.Log#ERROR}
+ *
+ *
+ * @author Andrey Korzhevskiy
+ */
+public class AndroidLoggerAdapter extends MarkerIgnoringBase {
+ private static final long serialVersionUID = -1227274521521287937L;
+
+ /**
+ * Package access allows only {@link AndroidLoggerFactory} to instantiate
+ * SimpleLogger instances.
+ */
+ AndroidLoggerAdapter(final String name) {
+ this.name = name;
+ }
+
+ /**
+ * Is this logger instance enabled for the VERBOSE level?
+ *
+ * @return True if this Logger is enabled for level VERBOSE, false otherwise.
+ */
+ @Override
+ public boolean isTraceEnabled() {
+ return Log.isLoggable(name, Log.VERBOSE);
+ }
+
+ /**
+ * Log a message object at level VERBOSE.
+ *
+ * @param msg
+ * - the message object to be logged
+ */
+ @Override
+ public void trace(final String msg) {
+ Log.v(name, msg);
+ }
+
+ /**
+ * Log a message at level VERBOSE according to the specified format and
+ * argument.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for level VERBOSE.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg
+ * the argument
+ */
+ @Override
+ public void trace(final String format, final Object arg) {
+ if (Log.isLoggable(name, Log.VERBOSE)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg);
+ Log.v(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level VERBOSE according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the VERBOSE level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg1
+ * the first argument
+ * @param arg2
+ * the second argument
+ */
+ @Override
+ public void trace(final String format, final Object arg1, final Object arg2) {
+ if (Log.isLoggable(name, Log.VERBOSE)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+ Log.v(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level VERBOSE according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the VERBOSE level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param argArray
+ * an array of arguments
+ */
+ @Override
+ public void trace(final String format, final Object... argArray) {
+ if (Log.isLoggable(name, Log.VERBOSE)) {
+ FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+ Log.v(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log an exception (throwable) at level VERBOSE with an accompanying message.
+ *
+ * @param msg
+ * the message accompanying the exception
+ * @param t
+ * the exception (throwable) to log
+ */
+ @Override
+ public void trace(final String msg, final Throwable t) {
+ Log.v(name, msg, t);
+ }
+
+ /**
+ * Is this logger instance enabled for the DEBUG level?
+ *
+ * @return True if this Logger is enabled for level DEBUG, false otherwise.
+ */
+ @Override
+ public boolean isDebugEnabled() {
+ return Log.isLoggable(name, Log.DEBUG);
+ }
+
+ /**
+ * Log a message object at level DEBUG.
+ *
+ * @param msg
+ * - the message object to be logged
+ */
+ @Override
+ public void debug(final String msg) {
+ Log.d(name, msg);
+ }
+
+ /**
+ * Log a message at level DEBUG according to the specified format and argument.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for level DEBUG.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg
+ * the argument
+ */
+ @Override
+ public void debug(final String format, final Object arg) {
+ if (Log.isLoggable(name, Log.DEBUG)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg);
+ Log.d(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level DEBUG according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the DEBUG level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg1
+ * the first argument
+ * @param arg2
+ * the second argument
+ */
+ @Override
+ public void debug(final String format, final Object arg1, final Object arg2) {
+ if (Log.isLoggable(name, Log.DEBUG)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+ Log.d(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level DEBUG according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the DEBUG level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param argArray
+ * an array of arguments
+ */
+ @Override
+ public void debug(final String format, final Object... argArray) {
+ if (Log.isLoggable(name, Log.DEBUG)) {
+ FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+ Log.d(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log an exception (throwable) at level DEBUG with an accompanying message.
+ *
+ * @param msg
+ * the message accompanying the exception
+ * @param t
+ * the exception (throwable) to log
+ */
+ @Override
+ public void debug(final String msg, final Throwable t) {
+ Log.d(name, msg, t);
+ }
+
+ /**
+ * Is this logger instance enabled for the INFO level?
+ *
+ * @return True if this Logger is enabled for the INFO level, false otherwise.
+ */
+ @Override
+ public boolean isInfoEnabled() {
+ return Log.isLoggable(name, Log.INFO);
+ }
+
+ /**
+ * Log a message object at the INFO level.
+ *
+ * @param msg
+ * - the message object to be logged
+ */
+ @Override
+ public void info(final String msg) {
+ Log.i(name, msg);
+ }
+
+ /**
+ * Log a message at level INFO according to the specified format and argument.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the INFO level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg
+ * the argument
+ */
+ @Override
+ public void info(final String format, final Object arg) {
+ if (Log.isLoggable(name, Log.INFO)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg);
+ Log.i(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at the INFO level according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the INFO level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg1
+ * the first argument
+ * @param arg2
+ * the second argument
+ */
+ @Override
+ public void info(final String format, final Object arg1, final Object arg2) {
+ if (Log.isLoggable(name, Log.INFO)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+ Log.i(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level INFO according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the INFO level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param argArray
+ * an array of arguments
+ */
+ @Override
+ public void info(final String format, final Object... argArray) {
+ if (Log.isLoggable(name, Log.INFO)) {
+ FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+ Log.i(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log an exception (throwable) at the INFO level with an accompanying
+ * message.
+ *
+ * @param msg
+ * the message accompanying the exception
+ * @param t
+ * the exception (throwable) to log
+ */
+ @Override
+ public void info(final String msg, final Throwable t) {
+ Log.i(name, msg, t);
+ }
+
+ /**
+ * Is this logger instance enabled for the WARN level?
+ *
+ * @return True if this Logger is enabled for the WARN level, false
+ * otherwise.
+ */
+ @Override
+ public boolean isWarnEnabled() {
+ return Log.isLoggable(name, Log.WARN);
+ }
+
+ /**
+ * Log a message object at the WARN level.
+ *
+ * @param msg
+ * - the message object to be logged
+ */
+ @Override
+ public void warn(final String msg) {
+ Log.w(name, msg);
+ }
+
+ /**
+ * Log a message at the WARN level according to the specified format and
+ * argument.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the WARN level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg
+ * the argument
+ */
+ @Override
+ public void warn(final String format, final Object arg) {
+ if (Log.isLoggable(name, Log.WARN)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg);
+ Log.w(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at the WARN level according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the WARN level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg1
+ * the first argument
+ * @param arg2
+ * the second argument
+ */
+ @Override
+ public void warn(final String format, final Object arg1, final Object arg2) {
+ if (Log.isLoggable(name, Log.WARN)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+ Log.w(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level WARN according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the WARN level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param argArray
+ * an array of arguments
+ */
+ @Override
+ public void warn(final String format, final Object... argArray) {
+ if (Log.isLoggable(name, Log.WARN)) {
+ FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+ Log.w(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log an exception (throwable) at the WARN level with an accompanying
+ * message.
+ *
+ * @param msg
+ * the message accompanying the exception
+ * @param t
+ * the exception (throwable) to log
+ */
+ @Override
+ public void warn(final String msg, final Throwable t) {
+ Log.w(name, msg, t);
+ }
+
+ /**
+ * Is this logger instance enabled for level ERROR?
+ *
+ * @return True if this Logger is enabled for level ERROR, false otherwise.
+ */
+ @Override
+ public boolean isErrorEnabled() {
+ return Log.isLoggable(name, Log.ERROR);
+ }
+
+ /**
+ * Log a message object at the ERROR level.
+ *
+ * @param msg
+ * - the message object to be logged
+ */
+ @Override
+ public void error(final String msg) {
+ Log.e(name, msg);
+ }
+
+ /**
+ * Log a message at the ERROR level according to the specified format and
+ * argument.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the ERROR level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg
+ * the argument
+ */
+ @Override
+ public void error(final String format, final Object arg) {
+ if (Log.isLoggable(name, Log.ERROR)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg);
+ Log.e(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at the ERROR level according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the ERROR level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param arg1
+ * the first argument
+ * @param arg2
+ * the second argument
+ */
+ @Override
+ public void error(final String format, final Object arg1, final Object arg2) {
+ if (Log.isLoggable(name, Log.ERROR)) {
+ FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
+ Log.e(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log a message at level ERROR according to the specified format and
+ * arguments.
+ *
+ *
+ * This form avoids superfluous object creation when the logger is disabled
+ * for the ERROR level.
+ *
+ *
+ * @param format
+ * the format string
+ * @param argArray
+ * an array of arguments
+ */
+ @Override
+ public void error(final String format, final Object... argArray) {
+ if (Log.isLoggable(name, Log.ERROR)) {
+ FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
+ Log.e(name, ft.getMessage(), ft.getThrowable());
+ }
+ }
+
+ /**
+ * Log an exception (throwable) at the ERROR level with an accompanying
+ * message.
+ *
+ * @param msg
+ * the message accompanying the exception
+ * @param t
+ * the exception (throwable) to log
+ */
+ @Override
+ public void error(final String msg, final Throwable t) {
+ Log.e(name, msg, t);
+ }
+}
diff --git a/slf4j-android/src/main/java/org/slf4j/impl/AndroidLoggerFactory.java b/slf4j-android/src/main/java/org/slf4j/impl/AndroidLoggerFactory.java
new file mode 100755
index 00000000..b322a479
--- /dev/null
+++ b/slf4j-android/src/main/java/org/slf4j/impl/AndroidLoggerFactory.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.impl;
+
+import android.util.Log;
+import org.slf4j.ILoggerFactory;
+import org.slf4j.Logger;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+/**
+ * AndroidLoggerFactory is an implementation of {@link ILoggerFactory} returning
+ * the appropriately named {@link AndroidLoggerFactory} instance.
+ *
+ * @author Andrey Korzhevskiy
+ */
+public class AndroidLoggerFactory implements ILoggerFactory {
+ private final Map loggerMap;
+
+ static final int TAG_MAX_LENGTH = 23; // tag names cannot be longer on Android platform
+ // see also android/system/core/include/cutils/property.h
+ // and android/frameworks/base/core/jni/android_util_Log.cpp
+
+ public AndroidLoggerFactory() {
+ loggerMap = new HashMap();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.slf4j.ILoggerFactory#getLogger(java.lang.String)
+ */
+ @Override
+ public Logger getLogger(String name) {
+ final String passedName = name;
+ name = forceValidName(passedName); // fix for bug #173
+ if (!passedName.equals(name)) {
+ Log.i(AndroidLoggerFactory.class.getSimpleName(),
+ "Logger name '" + passedName + "' exceeds maximum length of " + TAG_MAX_LENGTH +
+ " characters, using '" + name + "' instead.");
+ }
+ Logger ulogger;
+ // protect against concurrent access of loggerMap
+ synchronized (this) {
+ ulogger = loggerMap.get(name);
+ if (ulogger == null) {
+ ulogger = new AndroidLoggerAdapter(name);
+ loggerMap.put(name, ulogger);
+ }
+ }
+ return ulogger;
+ }
+
+ /**
+ * Trim name in case it exceeds maximum length of {@value #TAG_MAX_LENGTH} characters.
+ */
+ private static String forceValidName(String name) {
+ if (name != null && name.length() > TAG_MAX_LENGTH) {
+ final StringTokenizer st = new StringTokenizer(name, ".");
+ if (st.hasMoreTokens()) { // note that empty tokens are skipped, i.e., "aa..bb" has tokens "aa", "bb"
+ final StringBuilder sb = new StringBuilder();
+ String token;
+ do {
+ token = st.nextToken();
+ if (token.length() == 1) { // token of one character appended as is
+ sb.append(token);
+ sb.append('.');
+ } else if (st.hasMoreTokens()) { // truncate all but the last token
+ sb.append(token.charAt(0));
+ sb.append("*.");
+ } else { // last token (usually class name) appended as is
+ sb.append(token);
+ }
+ } while (st.hasMoreTokens());
+
+ name = sb.toString();
+ }
+
+ // Either we had no useful dot location at all or name still too long.
+ // Take leading part and append '*' to indicate that it was truncated
+ if (name.length() > TAG_MAX_LENGTH) {
+ name = name.substring(0, TAG_MAX_LENGTH - 1) + '*';
+ }
+ }
+ return name;
+ }
+}
diff --git a/slf4j-android/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-android/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
new file mode 100644
index 00000000..269c1875
--- /dev/null
+++ b/slf4j-android/src/main/java/org/slf4j/impl/StaticLoggerBinder.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.impl;
+
+import org.slf4j.ILoggerFactory;
+import org.slf4j.LoggerFactory;
+import org.slf4j.spi.LoggerFactoryBinder;
+
+/**
+ * The binding of {@link LoggerFactory} class with an actual instance of
+ * {@link ILoggerFactory} is performed using information returned by this class.
+ *
+ * @author Ceki Gülcü
+ */
+public class StaticLoggerBinder implements LoggerFactoryBinder {
+
+ /**
+ * The unique instance of this class.
+ */
+ private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
+
+ /**
+ * Return the singleton of this class.
+ *
+ * @return the StaticLoggerBinder singleton
+ */
+ public static StaticLoggerBinder getSingleton() {
+ return SINGLETON;
+ }
+
+ /**
+ * Declare the version of the SLF4J API this implementation is compiled against.
+ * The value of this field is usually modified with each release.
+ */
+ // to avoid constant folding by the compiler, this field must *not* be final
+ public static String REQUESTED_API_VERSION = "1.6.99"; // !final
+
+
+ private static final String loggerFactoryClassStr = AndroidLoggerFactory.class.getName();
+
+ /**
+ * The ILoggerFactory instance returned by the {@link #getLoggerFactory} method
+ * should always be the same object
+ */
+ private final ILoggerFactory loggerFactory;
+
+ private StaticLoggerBinder() {
+ loggerFactory = new AndroidLoggerFactory();
+ }
+
+ @Override
+ public ILoggerFactory getLoggerFactory() {
+ return loggerFactory;
+ }
+
+ @Override
+ public String getLoggerFactoryClassStr() {
+ return loggerFactoryClassStr;
+ }
+}
diff --git a/slf4j-android/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-android/src/main/java/org/slf4j/impl/StaticMDCBinder.java
new file mode 100644
index 00000000..de3b2a4d
--- /dev/null
+++ b/slf4j-android/src/main/java/org/slf4j/impl/StaticMDCBinder.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.impl;
+
+import org.slf4j.helpers.BasicMDCAdapter;
+import org.slf4j.spi.MDCAdapter;
+
+
+/**
+ * This implementation is bound to {@link BasicMDCAdapter}.
+ *
+ * @author Ceki Gülcü
+ */
+public class StaticMDCBinder {
+
+
+ /**
+ * The unique instance of this class.
+ */
+ public static final StaticMDCBinder SINGLETON = new StaticMDCBinder();
+
+ private StaticMDCBinder() {
+ }
+
+ /**
+ * Currently this method always returns an instance of
+ * {@link BasicMDCAdapter}.
+ */
+ public MDCAdapter getMDCA() {
+ // note that this method is invoked only from within the static initializer of
+ // the org.slf4j.MDC class.
+ return new BasicMDCAdapter();
+ }
+
+ public String getMDCAdapterClassStr() {
+ return BasicMDCAdapter.class.getName();
+ }
+}
diff --git a/slf4j-android/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/slf4j-android/src/main/java/org/slf4j/impl/StaticMarkerBinder.java
new file mode 100644
index 00000000..02817079
--- /dev/null
+++ b/slf4j-android/src/main/java/org/slf4j/impl/StaticMarkerBinder.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.impl;
+
+import org.slf4j.IMarkerFactory;
+import org.slf4j.MarkerFactory;
+import org.slf4j.helpers.BasicMarkerFactory;
+import org.slf4j.spi.MarkerFactoryBinder;
+
+/**
+ *
+ * The binding of {@link MarkerFactory} class with an actual instance of
+ * {@link IMarkerFactory} is performed using information returned by this class.
+ *
+ * @author Ceki Gülcü
+ */
+public class StaticMarkerBinder implements MarkerFactoryBinder {
+
+ /**
+ * The unique instance of this class.
+ */
+ public static final StaticMarkerBinder SINGLETON = new StaticMarkerBinder();
+
+ final IMarkerFactory markerFactory = new BasicMarkerFactory();
+
+ private StaticMarkerBinder() {
+ }
+
+ /**
+ * Currently this method always returns an instance of
+ * {@link BasicMarkerFactory}.
+ */
+ public IMarkerFactory getMarkerFactory() {
+ return markerFactory;
+ }
+
+ /**
+ * Currently, this method returns the class name of
+ * {@link BasicMarkerFactory}.
+ */
+ public String getMarkerFactoryClassStr() {
+ return BasicMarkerFactory.class.getName();
+ }
+
+
+}
diff --git a/slf4j-android/src/main/resources/META-INF/MANIFEST.MF b/slf4j-android/src/main/resources/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..d71f94cb
--- /dev/null
+++ b/slf4j-android/src/main/resources/META-INF/MANIFEST.MF
@@ -0,0 +1,9 @@
+Implementation-Title: slf4j-android
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: slf4j.android
+Bundle-Name: slf4j-android
+Bundle-Vendor: SLF4J.ORG
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Export-Package: org.slf4j.impl;version=${parsedVersion.osgiVersion}
+Import-Package: org.slf4j;version=${parsedVersion.osgiVersion}, org.slf4j.spi;version=${parsedVersion.osgiVersion}, org.slf4j.helpers;version=${parsedVersion.osgiVersion}
+Fragment-Host: slf4j.api
\ No newline at end of file