Commits

Fred Grott committed 8146b08

first commit

Comments (0)

Files changed (36)

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
+bin/*
+gen/*
+local.properties
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>GWSLAE</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

.settings/org.eclipse.jdt.core.prefs

+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.source=1.5

AndroidManifest.xml

+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.bitbucket.fredgrott.gwslae"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-sdk android:minSdkVersion="12" android:targetSdkVersion="15" />
+
+    <application android:label="@string/app_name"
+        android:icon="@drawable/ic_launcher"
+        android:theme="@style/AppTheme">
+
+    </application>
+
+</manifest>

libs/activation.jar

Binary file added.

libs/additionnal.jar

Binary file added.

libs/android-support-v4.jar

Binary file added.

libs/logback-android-1.0.7-1.jar

Binary file added.

libs/mail.jar

Binary file added.

libs/slf4j-api-1.6.6.jar

Binary file added.

proguard-project.txt

+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

project.properties

+# 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 edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
+android.library=true
+GWSLAE
+---
+
+Android Project Library to support using LogbackAndroid logging instead 
+of the default android logging system. With great power comes great 
+respect, please respect your application users by setting proper 
+controls such as ensuring that logs are only saved as files in 
+the CacheDir to ensure only your application can access them.
+
+# License
+
+Modications under Apache 2.0 License, original code from Logbackandroid examples
+is under GNU LPL or EPL.
+
+# Credits
+
+[Fred Grott(GrottWorkShop)](http://shareme.github.com)
+
+# LogbackAndroid  Tips
+
+Short tutorial on logback in the android app dev context.
+Basically, in the Logback tutorial when they are using individual 
+logback config files we can but that in the main one and not
+use joran to hav to read inanother config file.
+
+## logpath Workspace Setting and System.properties
+
+We can use in the file element of the logback config file to set 
+a logpath entry to our workspace:
+<code>
+<file>${logpath:-}logfile.log</file>
+</code>
+Than in our first activity called or the application class:
+<code>
+System.properties("logpath", mylogpath);
+</code>
+mylogpath would be setusing Environment calls to get the 
+CacheDir path.
+
+Ceki, project leadof Logback states not use the ContextInitializer
+but to use something like:
+
+<code>
+LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
+
+    RollingFileAppender rfAppender = new RollingFileAppender();
+    rfAppender.setContext(loggerContext);
+    rfAppender.setFile("testFile.log");
+    FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy();
+    rollingPolicy.setContext(loggerContext);
+    // rolling policies need to know their parent
+    // it's one of the rare cases, where a sub-component knows about its parent
+    rollingPolicy.setParent(rfAppender);
+    rollingPolicy.setFileNamePattern("testFile.%i.log.zip");
+    rollingPolicy.start();
+
+    SizeBasedTriggeringPolicy triggeringPolicy = new ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy();
+    triggeringPolicy.setMaxFileSize("5MB");
+    triggeringPolicy.start();
+
+    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
+    encoder.setContext(loggerContext);
+    encoder.setPattern("%-4relative [%thread] %-5level %logger{35} - %msg%n");
+    encoder.start();
+
+    rfAppender.setEncoder(encoder);
+    rfAppender.setRollingPolicy(rollingPolicy);
+    rfAppender.setTriggeringPolicy(triggeringPolicy);
+
+    rfAppender.start();
+
+    // attach the rolling file appender to the logger of your choice
+    Logger logbackLogger = loggerContext.getLogger("Main");
+    logbackLogger.addAppender(rfAppender);
+
+    // OPTIONAL: print logback internal status messages
+    StatusPrinter.print(loggerContext);
+
+    // log something
+    logbackLogger.debug("hello");
+</code>
+
+SO post: [setting-logback-appender-path-programmatically](http://stackoverflow.com/questions/3803184/setting-logback-appender-path-programmatically)
+
+## CheckLoggable
+
+You can set appenders as checkloggable:
+<code>
+<checkLoggable>false</checkLoggable>
+</code>
+
+For example, LOGCAT appender would be set false while log to file would 
+be set true.
+
+## file name as datetime stamped
+
+File appenders have a FileNamePattern element thus we can set that as:
+<code>
+${log_path:-}agent.%d{yyyy-MM-dd}.%i.zip.
+</code>
+The i variable is the counter.
+
+## Syslog with StrictMode
+
+Settings to use Syslog with SrictMode are:
+
+<code>
+StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+.detectDiskReads().detectDiskWrites().detectNetwork()
+.penaltyLog().build());
+StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+.detectLeakedSqlLiteObjects().detectLeakedClosableObjects()
+.penaltyLog().build());
+
+    super.onCreate(savedInstanceState);
+    logger = LoggerFactory.getLogger(SyslogLogbackActivity.class);
+    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+    StatusPrinter.print(lc);
+    setContentView(R.layout.main);
+    logger.debug("Hello Test Strict Mode");
+</code>
+
+With the logback configuration file settigns being:
+
+<code>
+< configuration debug="true" >
+< appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender" >
+< syslogHost>AAA.REMOVED.com
+< port>11111
+< facility>AUTH
+< suffixPattern>[%thread] %logger %msg
+</ appender >
+< root level="DEBUG" >
+< appender-ref ref="SYSLOG" />
+</ root >
+</ configuration >
+</code>
+
+## Log Separation
+
+In Android we of course do not have JNDI and thus cannot use the 
+JNDI context selector and appenders to sepearate log concerns.
+
+In android we would separate logging concerns by using the 
+logger name context, ie have logger named by package name of activity.
+
+On the Instrumented testing side we can use MDC filter event 
+classes to separate out our test loggign concenrs according to:
+    -plain unit logic tests
+    -basic robotium tests
+    -robogherk story type tests
+    
+ In the case of running something like the sdkcontroller apk or
+ say the openintents GPS simulator we could also  log that into 
+ a separate logging concern.
+ 
+ 
+
+
+## File output formatting
+
+We will use HTMLLayout:
+
+<code>
+<configuration debug="true">
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
+      <layout class="ch.qos.logback.classic.html.HTMLLayout">
+        <pattern>%relative%thread%mdc%level%logger%msg</pattern>
+        <cssBuilder class="ch.qos.logback.classic.html.UrlCssBuilder">
+    <!-- url where the css file is located -->
+    <url>http://...</url>
+  </cssBuilder> 
+      </layout>
+    </encoder>
+    <file>test.html</file>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+</code>
+
+Notice no spaces in pattern element items and the CssBuilder entry.
+Not sure if css file url entry needs to point to css in assets folder, 
+probably does as that is the most logical place to put the css file.
+
+One could also set a Log4j XML output since that would probably be more 
+integrateable with CI builder tools:
+
+<code>
+<configuration>
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <file>test.xml</file>
+    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
+      <layout class="ch.qos.logback.classic.log4j.XMLLayout">
+        <locationInfo>true</locationInfo>
+      </layout>
+    </encoder> 
+  </appender> 
+
+  <root level="DEBUG">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration> 
+</code>
+
+## HtmlToConsole
+
+<code>
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
+      <layout class="ch.qos.logback.classic.html.HTMLLayout">
+        <cssBuilder class="ch.qos.logback.classic.html.UrlCssBuilder">
+          <url>path_to_StyleFile.css</url>
+        </cssBuilder>   
+        <pattern>%-4relative [%thread] %-5level - %msg%n</pattern>
+      </layout>
+    </encoder>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+</code>
+
+## TimestampContextBirth
+
+<code>
+<configuration>
+
+  <!-- Insert the logger context bith date formatted as
+       "yyyyMMdd'T'HHmmss" under the key "bySecond" into the logger
+       context. This value will be available to all subsequent
+       configuration elements. -->
+  <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss" 
+             timeReference="contextBirth"/>
+
+  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+    <!-- use the previously created timestamp to create a uniquely
+         named log file -->
+    <file>log-${bySecond}.txt</file>
+    <encoder>
+      <pattern>%logger{35} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="DEBUG">
+    <appender-ref ref="FILE" />
+  </root>
+</configuration>
+</code>
+
+## RollingSizeAndTime
+
+<code>
+<configuration>
+
+  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
+
+  <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <file>mylog.txt</file>
+    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+      <!-- rollover daily -->
+      <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
+      <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+        <!-- or whenever the file size reaches 100MB -->
+        <maxFileSize>100MB</maxFileSize>
+      </timeBasedFileNamingAndTriggeringPolicy>
+    </rollingPolicy>
+    <encoder>
+      <pattern>%msg%n</pattern>
+    </encoder>
+  </appender>
+
+
+  <root level="debug">
+    <appender-ref ref="ROLLING" />
+  </root>
+
+</configuration>
+</code>
+
+## ContextName
+
+<code>
+<configuration>
+
+  <contextName>myAppName</contextName>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
+    </encoder>
+  </appender>
+
+  <root level="debug">
+    <appender-ref ref="STDOUT" />
+  </root>
+
+</configuration>
+</code>
+
+## Multiple Appenders
+
+<code>
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>myApp.log</file>
+    <!-- encoders are assigned by default the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
+    <encoder>
+            <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
+    </encoder>
+    </appender>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%msg%n</pattern>
+    </encoder>
+    </appender>
+
+    <root level="debug">
+        <appender-ref ref="FILE" />
+        <appender-ref ref="STDOUT" />
+    </root>
+</configuration>
+</code>
+
+## Highlighted
+
+<code>
+<configuration debug="true">
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- On Windows machines setting withJansi to true enables ANSI
+         color code interpretation by the Jansi library. This requires
+         org.fusesource.jansi:jansi:1.8 on the class path.  Note that
+         Unix-based operating systems such as Linux and Mac OS X
+         support ANSI color codes by default.  codes.-->
+    <withJansi>false</withJansi>
+    <encoder>
+      <pattern>%date [%thread] %highlight(%-5level) %cyan(%-15logger{15}) %X - %msg %n</pattern>
+    </encoder>
+  </appender>
+  <root level="DEBUG">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>
+</code>
+
+

res/drawable-hdpi/ic_action_search.png

Added
New image

res/drawable-hdpi/ic_launcher.png

Added
New image

res/drawable-mdpi/ic_action_search.png

Added
New image

res/drawable-mdpi/ic_launcher.png

Added
New image

res/drawable-xhdpi/ic_action_search.png

Added
New image

res/drawable-xhdpi/ic_launcher.png

Added
New image

res/values-v11/styles.xml

+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light" />
+
+</resources>

res/values-v14/styles.xml

+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
+
+</resources>

res/values/strings.xml

+<resources>
+    <string name="app_name">GWSLAE</string>
+</resources>

res/values/styles.xml

+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Light" />
+
+</resources>

src/org/bitbucket/fredgrott/gwslae/GWSLAEBar.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import org.slf4j.LoggerFactory;
+
+import org.slf4j.Logger;
+
+
+public class GWSLAEBar {
+
+	 Logger logger = LoggerFactory.getLogger(GWSLAEBar.class);
+	  
+	  public String toString() {
+	    return "test 123";
+	  }
+	  
+	  public void createLoggingRequest() {
+	    subMethodToCreateRequest();
+	  }
+	  
+	  //this is done to create a stacktrace of more than one line
+	  private void subMethodToCreateRequest() {
+	    logger.error("error-level request", new Exception("test exception"));
+	  }
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAEConfigurator.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import java.util.List;
+import java.util.Map;
+
+import ch.qos.logback.core.joran.GenericConfigurator;
+import ch.qos.logback.core.joran.action.Action;
+import ch.qos.logback.core.joran.action.ImplicitAction;
+import ch.qos.logback.core.joran.spi.Interpreter;
+import ch.qos.logback.core.joran.spi.Pattern;
+import ch.qos.logback.core.joran.spi.RuleStore;
+
+public class GWSLAEConfigurator extends GenericConfigurator {
+
+	  final Map<Pattern, Action> ruleMap;
+	  final List<ImplicitAction> iaList;
+
+	  public GWSLAEConfigurator(Map<Pattern, Action> ruleMap) {
+	    this(ruleMap, null);
+	  }
+
+	  public GWSLAEConfigurator(Map<Pattern, Action> ruleMap, List<ImplicitAction> iaList) {
+	    this.ruleMap = ruleMap;
+	    this.iaList = iaList;
+	  }
+
+	  @Override
+	  protected void addInstanceRules(RuleStore rs) {
+	    for (Pattern pattern : ruleMap.keySet()) {
+	      Action action = ruleMap.get(pattern);
+	      rs.addRule(pattern, action);
+	    }
+	  }
+
+	  @Override
+	  protected void addImplicitRules(Interpreter interpreter) {
+	    if(iaList == null) {
+	      return;
+	    }
+	    for (ImplicitAction ia : iaList) {
+	      interpreter.addImplicitAction(ia);
+	    }
+	  }
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAECountingConsoleAppender.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+
+package org.bitbucket.fredgrott.gwslae;
+
+import java.io.IOException;
+
+import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+
+/**
+ * GWSLAECountingConsoleAppender config xml file like  this:
+ * 
+ * <code>
+ * <configuration>
+ *
+ *
+ * <appender name="CUSTOM" class="org.bitbucket.fredgrott.gwslae.GWSLAECountingConsoleAppender">
+ *   <layout>
+ *     <Pattern>%date [%thread] %-5level %logger - %msg%n</Pattern>
+ *   </layout>
+ *   <limit>5</limit>
+ * </appender>
+ *
+ * <root level="debug">
+ *   <appender-ref ref="CUSTOM" />
+ * </root>  
+ * </configuration>
+ *
+ * </code>
+ * 
+ * @author fredgrott
+ *
+ */
+public class GWSLAECountingConsoleAppender extends AppenderBase<ILoggingEvent> {
+
+	static int DEFAULT_LIMIT = 10;
+	  int counter = 0;
+	  int limit = DEFAULT_LIMIT;
+	  
+	  PatternLayoutEncoder encoder;
+	  
+	  public void setLimit(int limit) {
+	    this.limit = limit;
+	  }
+
+	  public int getLimit() {
+	    return limit;
+	  }  
+	  
+	  @Override
+	  public void start() {
+	    if (this.encoder == null) {
+	      addError("No layout set for the appender named ["+ name +"].");
+	      return;
+	    }
+	    
+	    try {
+	      encoder.init(System.out);
+	    } catch (IOException e) {
+	    }
+	    super.start();
+	  }
+
+	  public void append(ILoggingEvent event) {
+	    if (counter >= limit) {
+	      return;
+	    }
+	    // output the events as formatted by our layout
+	    try {
+	      this.encoder.doEncode(event);
+	    } catch (IOException e) {
+	    }
+
+	    // prepare for next event
+	    counter++;
+	  }
+
+	  public PatternLayoutEncoder getEncoder() {
+	    return encoder;
+	  }
+
+	  public void setEncoder(PatternLayoutEncoder encoder) {
+	    this.encoder = encoder;
+	  }
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAEEmailCounterBasedEvaluator.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import ch.qos.logback.core.boolex.EvaluationException;
+import ch.qos.logback.core.boolex.EventEvaluator;
+import ch.qos.logback.core.spi.ContextAwareBase;
+
+/**
+ * A simple EventEvaluator implementation that triggers email transmission after
+ * 1024 events regardless of event level.
+ * 
+ * Obviously this gets a configuration file entry to trigger.
+ * Replace GEEvaltuor with this one as:
+ * <code>
+ * <configuration>
+ * <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />  
+ *
+ * <appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
+ *  <evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator">
+ *     <expression>
+ *       e.marker?.contains("NOTIFY_ADMIN") || e.marker?.contains("TRANSACTION_FAILURE")
+ *     </expression>
+ *   </evaluator>
+ *   <SMTPHost>${smtpHost}</SMTPHost>
+ *   <To>${to}</To>
+ *   <From>${from}</From>
+ *   <layout class="ch.qos.logback.classic.html.HTMLLayout"/>
+ * </appender>
+ *
+ * <root>
+ *   <level value ="debug"/>
+ *   <appender-ref ref="EMAIL" />
+ * </root>  
+ * </configuration>
+ * </code>
+ * 
+ */
+public class GWSLAEEmailCounterBasedEvaluator extends ContextAwareBase implements EventEvaluator {
+
+	static int LIMIT = 1024;
+	  int counter = 0;
+	  String name;
+	  boolean started;
+
+	  public boolean evaluate(Object event) throws NullPointerException,
+	      EvaluationException {
+	    counter++;
+
+	    if (counter == LIMIT) {
+	      counter = 0;
+
+	      return true;
+	    } else {
+	      return false;
+	    }
+	  }
+
+	  public String getName() {
+	    return name;
+	  }
+
+	  public void setName(String name) {
+	    this.name = name;
+	  }
+
+	  public boolean isStarted() {
+	    return started;
+	  }
+
+	  public void start() {
+	    started = true;
+	  }
+
+	  public void stop() {
+	    started = false;
+	  }
+	  
+	  public static void setLIMIT(int lIMIT) {
+		LIMIT = lIMIT;
+	}
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAEGeneralSelectionRule.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import ch.qos.logback.classic.Level;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * GWSLAEGeneralSelectionRule, you would extend this 
+ * and modify the default constructor to set up your own
+ * Selection rules.
+ * 
+ * @author fredgrott
+ *
+ */
+public class GWSLAEGeneralSelectionRule {
+	
+	public GWSLAEGeneralSelectionRule() {
+		try {
+			// get a logger instance named "com.foo". Let us further assume that the
+		    // logger is of type  ch.qos.logback.classic.Logger so that we can
+		    // set its level
+		    ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.foo");
+		    //set its Level to INFO. The setLevel() method requires a logback logger
+		    logger.setLevel(Level.INFO);
+
+		    Logger barlogger = LoggerFactory.getLogger("com.foo.Bar");
+
+		    // This request is enabled, because WARN >= INFO
+		    logger.warn("Low fuel level.");
+
+		    // This request is disabled, because DEBUG < INFO.
+		    logger.debug("Starting search for nearest gas station.");
+
+		    // The logger instance barlogger, named "com.foo.Bar",
+		    // will inherit its level from the logger named
+		    // "com.foo" Thus, the following request is enabled
+		    // because INFO >= INFO.
+		    barlogger.info("Located nearest gas station.");
+
+		    // This request is disabled, because DEBUG < INFO.
+		    barlogger.debug("Exiting gas station search");
+			
+		} catch(Exception e){
+			
+		}
+	}
+
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAELayout.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.CoreConstants;
+import ch.qos.logback.core.LayoutBase;
+
+/**
+ * GWSLAELayout, config looks like this:
+ * 
+ * <code>
+ * <configuration>
+ *
+ *  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ *
+ *   <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
+ *    <layout class="org.bitbucket.fredgrott.gwslae.GWSLAELayout">
+ *       <prefix>MyPrefix</prefix>
+ *       <printThreadName>false</printThreadName>
+ *    </layout>
+ *   </encoder>
+ * </appender>
+ *
+ * <root level="debug">
+ *   <appender-ref ref="STDOUT" />
+ * </root>
+ * </configuration>
+ * </code>
+ * 
+ * @author fredgrott
+ *
+ */
+public class GWSLAELayout extends LayoutBase<ILoggingEvent> {
+
+	 String prefix = null;
+	  boolean printThreadName = true;
+
+	  public void setPrefix(String prefix) {
+	    this.prefix = prefix;
+	  }
+
+	  public void setPrintThreadName(boolean printThreadName) {
+	    this.printThreadName = printThreadName;
+	  }
+
+	  public String doLayout(ILoggingEvent event) {
+	    StringBuffer sbuf = new StringBuffer(128);
+	    if (prefix != null) {
+	      sbuf.append(prefix + ": ");
+	    }
+	    sbuf.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime());
+	    sbuf.append(" ");
+	    sbuf.append(event.getLevel());
+	    if (printThreadName) {
+	      sbuf.append(" [");
+	      sbuf.append(event.getThreadName());
+	      sbuf.append("] ");
+	    } else {
+	      sbuf.append(" ");
+	    }
+	    sbuf.append(event.getLoggerName());
+	    sbuf.append(" - ");
+	    sbuf.append(event.getFormattedMessage());
+	    sbuf.append(CoreConstants.LINE_SEPARATOR);
+	    return sbuf.toString();
+	  }
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAEMarkerFilter.java

+package org.bitbucket.fredgrott.gwslae;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.AbstractMatcherFilter;
+import ch.qos.logback.core.spi.FilterReply;
+
+/**
+ * <code>
+ * <filter class="your.pkg.MarkerFilter">
+ *   <marker>YOUR_MARKER</marker>
+ *  <onMatch>ACCEPT</onMatch>
+ *   <onMismatch>DENY</onMismatch>
+ * </filter>
+ * </code>
+ * @author fredgrott
+ *
+ */
+public class GWSLAEMarkerFilter extends AbstractMatcherFilter<ILoggingEvent> {
+
+	 /** The marker to match. */
+    private Marker markerToMatch = null;
+    
+    /**
+     * Start.
+     *
+     * @see ch.qos.logback.core.filter.Filter#start()
+     */
+    @Override
+    public void start() {
+        if (null != this.markerToMatch)
+            super.start();
+         else
+            addError("!!! no marker yet !!!");
+    }
+    
+    /**
+     * Decide.
+     *
+     * @param event the event
+     * @return the filter reply
+     * @see ch.qos.logback.core.filter.Filter#decide(java.lang.Object)
+     */
+    @Override
+    public FilterReply decide(ILoggingEvent event) {
+        Marker marker = event.getMarker();
+        if (!isStarted())
+            return FilterReply.NEUTRAL;
+        if (null == marker)
+            return onMismatch;
+        if (markerToMatch.contains(marker))
+            return onMatch;
+        return onMismatch;
+    }
+    
+    /**
+     * Sets the marker.
+     *
+     * @param markerStr the new marker
+     */
+    public void setMarker(String markerStr) {
+        if(null != markerStr)
+            markerToMatch = MarkerFactory.getMarker(markerStr);
+    }
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAENanoConverter.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import ch.qos.logback.classic.pattern.ClassicConverter;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+
+/**
+ * GWSLAENanoConverter, config xml file like this:
+ * 
+ * <code>
+ * <configuration>
+ *
+ *	<conversionRule conversionWord="nano" 
+ *                 converterClass="chapters.layouts.MySampleConverter" />
+ *
+ * <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ *   <encoder>
+ *     <pattern>%-6nano [%thread] %level - %msg%n</pattern>
+ *   </encoder>
+ * </appender>
+ *
+ * <root level="DEBUG">
+ *  <appender-ref ref="STDOUT" />
+ *  </root>
+ * </configuration>
+ * </code>
+ * 
+ * @author fredgrott
+ *
+ */
+public class GWSLAENanoConverter extends ClassicConverter {
+
+	long start = System.nanoTime();
+
+	  @Override
+	  public String convert(ILoggingEvent event) {
+	    long nowInNanos = System.nanoTime();
+	    return Long.toString(nowInNanos-start);
+	  }
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAEThresholdLoggerFilter.java

+package org.bitbucket.fredgrott.gwslae;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.FilterReply;
+
+/**
+ * <code>
+ * <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ *   <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ *       <level>INFO</level>
+ *   </filter>
+ *   <filter class="com.myapp.ThresholdLoggerFilter">
+ *       <logger>org.springframework</logger>
+ *      <level>ERROR</level>
+ *   </filter>
+ *  </appender>
+ * </code>
+ * @author fredgrott
+ *
+ */
+public class GWSLAEThresholdLoggerFilter extends Filter<ILoggingEvent> {
+
+	/** The level. */
+    private Level level;
+    
+    /** The logger. */
+    private String logger;
+
+    /**
+     * Decide.
+     *
+     * @param event the event
+     * @return the filter reply
+     * @see ch.qos.logback.core.filter.Filter#decide(java.lang.Object)
+     */
+    @Override
+    public FilterReply decide(ILoggingEvent event) {
+        if (!isStarted()) {
+            return FilterReply.NEUTRAL;
+        }
+
+        if (!event.getLoggerName().startsWith(logger))
+            return FilterReply.NEUTRAL;
+
+        if (event.getLevel().isGreaterOrEqual(level)) {
+            return FilterReply.NEUTRAL;
+        } else {
+            return FilterReply.DENY;
+        }
+    }
+
+    /**
+     * Sets the level.
+     *
+     * @param level the new level
+     */
+    public void setLevel(Level level) {
+        this.level = level;
+    }
+
+    /**
+     * Sets the logger.
+     *
+     * @param logger the new logger
+     */
+    public void setLogger(String logger) {
+        this.logger = logger;
+    }
+
+    /**
+     * Start.
+     *
+     * @see ch.qos.logback.core.filter.Filter#start()
+     */
+    public void start() {
+        if (this.level != null && this.logger != null) {
+            super.start();
+        }
+    }
+	
+	
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAETurboFilter.java

+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package org.bitbucket.fredgrott.gwslae;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.turbo.TurboFilter;
+import ch.qos.logback.core.spi.FilterReply;
+
+/**
+ * GWSLAETurboFilter configuration xml file would be:
+ * 
+ * <code>
+ * <configuration>
+ *
+ *  <turboFilter class="org.bitbucket.fredgrott.gwslae.GWSLAETurboFilter">
+ *   <Marker>sample</Marker>
+ * </turboFilter>
+ *
+ * <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ *   <layout class="ch.qos.logback.classic.PatternLayout">
+ *    <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
+ *   </layout>
+ * </appender>
+ *
+ * <root>
+ *   <appender-ref ref="STDOUT" />
+ * </root>
+ * </configuration>
+ * </code>
+ * @author fredgrott
+ *
+ */
+public class GWSLAETurboFilter extends TurboFilter {
+
+	String marker;
+	  Marker markerToAccept;
+
+	  @Override
+	  public FilterReply decide(Marker marker, Logger logger, Level level,
+	      String format, Object[] params, Throwable t) {
+	    
+	    if (!isStarted()) {
+	      return FilterReply.NEUTRAL;
+	    }
+
+	    if ((markerToAccept.equals(marker))) {
+	      return FilterReply.ACCEPT;
+	    } else {
+	      return FilterReply.NEUTRAL;
+	    }
+	  }
+
+	  public String getMarker() {
+	    return marker;
+	  }
+
+	  public void setMarker(String markerStr) {
+	    this.marker = markerStr;
+	  }
+
+	  @Override
+	  public void start() {
+	    if (marker != null && marker.trim().length() > 0) {
+	      markerToAccept = MarkerFactory.getMarker(marker);
+	      super.start(); 
+	    }
+	  }
+
+}

src/org/bitbucket/fredgrott/gwslae/GWSLAEUtils.java

+package org.bitbucket.fredgrott.gwslae;
+
+import java.net.URL;
+
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.util.Loader;
+import ch.qos.logback.core.util.StatusPrinter;
+
+public class GWSLAEUtils {
+	
+	static String XmlConfigFilePath;
+	
+	public void setXmlConfigFilePath(String xmlConfigFilePath) {
+		XmlConfigFilePath = xmlConfigFilePath;
+	}
+	
+	public String getXmlConfigFilePath() {
+		return XmlConfigFilePath;
+	}
+	
+	/**
+	 * set the XmlConfigFilePath first and than
+	 * configureViaXML_File();
+	 * than you can do 
+	 * Logger logger = LoggerFactory.getLogger(Our.class);
+	 * 
+	 * and start using..easy example is doing MDC
+	 * 
+	 */
+	static void configureViaXML_File() {
+	    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
+	    try {
+	      JoranConfigurator configurator = new JoranConfigurator();
+	      configurator.setContext(lc);
+	      lc.reset();
+	      URL url = Loader.getResourceBySelfClassLoader(XmlConfigFilePath);
+	      configurator.doConfigure(url);
+	    } catch (JoranException je) {
+	      StatusPrinter.print(lc);
+	    }
+	  }
+
+}

src/org/bitbucket/fredgrott/gwslae/package-info.java

+/**
+ * 
+ */
+/**
+ * @author fredgrott
+ *
+ */
+package org.bitbucket.fredgrott.gwslae;