You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/10 16:15:57 UTC
[35/59] [abbrv] [KARAF-2852] Merge log/core and log/command
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java b/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java
new file mode 100644
index 0000000..ea51b34
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.karaf.log.core.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+ * A list that only keep the last N elements added
+ */
+public class LruList implements PaxAppender {
+
+ private PaxLoggingEvent[] elements;
+ private transient int start = 0;
+ private transient int end = 0;
+ private transient boolean full = false;
+ private final int maxElements;
+ private final List<PaxAppender> appenders;
+
+ public LruList(int size) {
+ if (size <= 0) {
+ throw new IllegalArgumentException("The size must be greater than 0");
+ }
+ elements = new PaxLoggingEvent[size];
+ maxElements = elements.length;
+ appenders = new ArrayList<PaxAppender>();
+ }
+
+ public synchronized int size() {
+ int size = 0;
+ if (end < start) {
+ size = maxElements - start + end;
+ } else if (end == start) {
+ size = (full ? maxElements : 0);
+ } else {
+ size = end - start;
+ }
+ return size;
+ }
+
+ public synchronized void clear() {
+ start = 0;
+ end = 0;
+ elements = new PaxLoggingEvent[maxElements];
+ }
+
+ public synchronized void add(PaxLoggingEvent element) {
+ if (null == element) {
+ throw new NullPointerException("Attempted to add null object to buffer");
+ }
+ if (size() == maxElements) {
+ Object e = elements[start];
+ if (null != e) {
+ elements[start++] = null;
+ if (start >= maxElements) {
+ start = 0;
+ }
+ full = false;
+ }
+ }
+ elements[end++] = element;
+ if (end >= maxElements) {
+ end = 0;
+ }
+ if (end == start) {
+ full = true;
+ }
+ for (PaxAppender appender : appenders) {
+ try {
+ appender.doAppend(element);
+ } catch (Throwable t) {
+ // Ignore
+ }
+ }
+ }
+
+ public synchronized Iterable<PaxLoggingEvent> getElements() {
+ return getElements(size());
+ }
+
+ public synchronized Iterable<PaxLoggingEvent> getElements(int nb) {
+ int s = size();
+ nb = Math.min(Math.max(0, nb), s);
+ PaxLoggingEvent[] e = new PaxLoggingEvent[nb];
+ for (int i = 0; i < nb; i++) {
+ e[i] = elements[(i + s - nb + start) % maxElements];
+ }
+ return Arrays.asList(e);
+ }
+
+ public synchronized void addAppender(PaxAppender appender) {
+ this.appenders.add(appender);
+ }
+
+ public synchronized void removeAppender(PaxAppender appender) {
+ this.appenders.remove(appender);
+ }
+
+ public void doAppend(PaxLoggingEvent event) {
+ event.getProperties(); // ensure MDC properties are copied
+ add(event);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
new file mode 100644
index 0000000..8bb3ff3
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.layout;
+
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Copied from log4j
+ */
+/**
+ Formats a {@link Date} in the format "HH:mm:ss,SSS" for example,
+ "15:49:37,459".
+
+ @since 0.7.5
+*/
+public class AbsoluteTimeDateFormat extends DateFormat {
+
+ /**
+ String constant used to specify {@link
+ org.apache.log4j.helpers.AbsoluteTimeDateFormat} in layouts. Current
+ value is <b>ABSOLUTE</b>. */
+ public final static String ABS_TIME_DATE_FORMAT = "ABSOLUTE";
+
+ /**
+ String constant used to specify {@link
+ org.apache.log4j.helpers.DateTimeDateFormat} in layouts. Current
+ value is <b>DATE</b>.
+ */
+ public final static String DATE_AND_TIME_DATE_FORMAT = "DATE";
+
+ /**
+ String constant used to specify {@link
+ org.apache.log4j.helpers.ISO8601DateFormat} in layouts. Current
+ value is <b>ISO8601</b>.
+ */
+ public final static String ISO8601_DATE_FORMAT = "ISO8601";
+
+ public
+ AbsoluteTimeDateFormat() {
+ setCalendar(Calendar.getInstance());
+ }
+
+ public
+ AbsoluteTimeDateFormat(TimeZone timeZone) {
+ setCalendar(Calendar.getInstance(timeZone));
+ }
+
+ private static long previousTime;
+ private static char[] previousTimeWithoutMillis = new char[9]; // "HH:mm:ss."
+
+ /**
+ Appends to <code>sbuf</code> the time in the format
+ "HH:mm:ss,SSS" for example, "15:49:37,459"
+
+ @param date the date to format
+ @param sbuf the string buffer to write to
+ @param fieldPosition remains untouched
+ */
+ public
+ StringBuffer format(Date date, StringBuffer sbuf,
+ FieldPosition fieldPosition) {
+
+ long now = date.getTime();
+ int millis = (int)(now % 1000);
+
+ if ((now - millis) != previousTime) {
+ // We reach this point at most once per second
+ // across all threads instead of each time format()
+ // is called. This saves considerable CPU time.
+
+ calendar.setTime(date);
+
+ int start = sbuf.length();
+
+ int hour = calendar.get(Calendar.HOUR_OF_DAY);
+ if(hour < 10) {
+ sbuf.append('0');
+ }
+ sbuf.append(hour);
+ sbuf.append(':');
+
+ int mins = calendar.get(Calendar.MINUTE);
+ if(mins < 10) {
+ sbuf.append('0');
+ }
+ sbuf.append(mins);
+ sbuf.append(':');
+
+ int secs = calendar.get(Calendar.SECOND);
+ if(secs < 10) {
+ sbuf.append('0');
+ }
+ sbuf.append(secs);
+ sbuf.append(',');
+
+ // store the time string for next time to avoid recomputation
+ sbuf.getChars(start, sbuf.length(), previousTimeWithoutMillis, 0);
+
+ previousTime = now - millis;
+ }
+ else {
+ sbuf.append(previousTimeWithoutMillis);
+ }
+
+
+
+ if(millis < 100)
+ sbuf.append('0');
+ if(millis < 10)
+ sbuf.append('0');
+
+ sbuf.append(millis);
+ return sbuf;
+ }
+
+ /**
+ This method does not do anything but return <code>null</code>.
+ */
+ public
+ Date parse(String s, ParsePosition pos) {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
new file mode 100644
index 0000000..1aa884d
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.layout;
+
+import java.text.DateFormatSymbols;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Copied from log4j
+ */
+/**
+ Formats a {@link Date} in the format "dd MMM yyyy HH:mm:ss,SSS" for example,
+ "06 Nov 1994 15:49:37,459".
+
+ @since 0.7.5
+*/
+public class DateTimeDateFormat extends AbsoluteTimeDateFormat {
+
+ String[] shortMonths;
+
+ public
+ DateTimeDateFormat() {
+ super();
+ shortMonths = new DateFormatSymbols().getShortMonths();
+ }
+
+ public
+ DateTimeDateFormat(TimeZone timeZone) {
+ this();
+ setCalendar(Calendar.getInstance(timeZone));
+ }
+
+ /**
+ Appends to <code>sbuf</code> the date in the format "dd MMM yyyy
+ HH:mm:ss,SSS" for example, "06 Nov 1994 08:49:37,459".
+
+ @param sbuf the string buffer to write to
+ */
+ public
+ StringBuffer format(Date date, StringBuffer sbuf,
+ FieldPosition fieldPosition) {
+
+ calendar.setTime(date);
+
+ int day = calendar.get(Calendar.DAY_OF_MONTH);
+ if(day < 10)
+ sbuf.append('0');
+ sbuf.append(day);
+ sbuf.append(' ');
+ sbuf.append(shortMonths[calendar.get(Calendar.MONTH)]);
+ sbuf.append(' ');
+
+ int year = calendar.get(Calendar.YEAR);
+ sbuf.append(year);
+ sbuf.append(' ');
+
+ return super.format(date, sbuf, fieldPosition);
+ }
+
+ /**
+ This method does not do anything but return <code>null</code>.
+ */
+ public
+ Date parse(java.lang.String s, ParsePosition pos) {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
new file mode 100644
index 0000000..6fd728f
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.layout;
+
+
+/**
+ * Copied from log4j
+ */
+/**
+ FormattingInfo instances contain the information obtained when parsing
+ formatting modifiers in conversion modifiers.
+
+ @since 0.8.2
+ */
+public class FormattingInfo {
+ int min = -1;
+ int max = 0x7FFFFFFF;
+ boolean leftAlign = false;
+
+ void reset() {
+ min = -1;
+ max = 0x7FFFFFFF;
+ leftAlign = false;
+ }
+
+ void dump() {
+ //LogLog.debug("min="+min+", max="+max+", leftAlign="+leftAlign);
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
new file mode 100644
index 0000000..80155a0
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.layout;
+
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Copied from log4j
+ */
+// Contributors: Arndt Schoenewald <ar...@ibm23093i821.mc.schoenewald.de>
+/**
+ Formats a {@link Date} in the format "yyyy-MM-dd HH:mm:ss,SSS" for example
+ "1999-11-27 15:49:37,459".
+
+ <p>Refer to the <a
+ href=http://www.cl.cam.ac.uk/~mgk25/iso-time.html>summary of the
+ International Standard Date and Time Notation</a> for more
+ information on this format.
+
+ @since 0.7.5
+*/
+public class ISO8601DateFormat extends AbsoluteTimeDateFormat {
+
+ public
+ ISO8601DateFormat() {
+ }
+
+ public
+ ISO8601DateFormat(TimeZone timeZone) {
+ super(timeZone);
+ }
+
+ static private long lastTime;
+ static private char[] lastTimeString = new char[20];
+
+ /**
+ Appends a date in the format "YYYY-mm-dd HH:mm:ss,SSS"
+ to <code>sbuf</code>. For example: "1999-11-27 15:49:37,459".
+
+ @param sbuf the <code>StringBuffer</code> to write to
+ */
+ public
+ StringBuffer format(Date date, StringBuffer sbuf,
+ FieldPosition fieldPosition) {
+
+ long now = date.getTime();
+ int millis = (int)(now % 1000);
+
+ if ((now - millis) != lastTime) {
+ // We reach this point at most once per second
+ // across all threads instead of each time format()
+ // is called. This saves considerable CPU time.
+
+ calendar.setTime(date);
+
+ int start = sbuf.length();
+
+ int year = calendar.get(Calendar.YEAR);
+ sbuf.append(year);
+
+ String month;
+ switch(calendar.get(Calendar.MONTH)) {
+ case Calendar.JANUARY: month = "-01-"; break;
+ case Calendar.FEBRUARY: month = "-02-"; break;
+ case Calendar.MARCH: month = "-03-"; break;
+ case Calendar.APRIL: month = "-04-"; break;
+ case Calendar.MAY: month = "-05-"; break;
+ case Calendar.JUNE: month = "-06-"; break;
+ case Calendar.JULY: month = "-07-"; break;
+ case Calendar.AUGUST: month = "-08-"; break;
+ case Calendar.SEPTEMBER: month = "-09-"; break;
+ case Calendar.OCTOBER: month = "-10-"; break;
+ case Calendar.NOVEMBER: month = "-11-"; break;
+ case Calendar.DECEMBER: month = "-12-"; break;
+ default: month = "-NA-"; break;
+ }
+ sbuf.append(month);
+
+ int day = calendar.get(Calendar.DAY_OF_MONTH);
+ if(day < 10)
+ sbuf.append('0');
+ sbuf.append(day);
+
+ sbuf.append(' ');
+
+ int hour = calendar.get(Calendar.HOUR_OF_DAY);
+ if(hour < 10) {
+ sbuf.append('0');
+ }
+ sbuf.append(hour);
+ sbuf.append(':');
+
+ int mins = calendar.get(Calendar.MINUTE);
+ if(mins < 10) {
+ sbuf.append('0');
+ }
+ sbuf.append(mins);
+ sbuf.append(':');
+
+ int secs = calendar.get(Calendar.SECOND);
+ if(secs < 10) {
+ sbuf.append('0');
+ }
+ sbuf.append(secs);
+
+ sbuf.append(',');
+
+ // store the time string for next time to avoid recomputation
+ sbuf.getChars(start, sbuf.length(), lastTimeString, 0);
+ lastTime = now - millis;
+ }
+ else {
+ sbuf.append(lastTimeString);
+ }
+
+
+ if (millis < 100)
+ sbuf.append('0');
+ if (millis < 10)
+ sbuf.append('0');
+
+ sbuf.append(millis);
+ return sbuf;
+ }
+
+ /**
+ This method does not do anything but return <code>null</code>.
+ */
+ public
+ Date parse(java.lang.String s, ParsePosition pos) {
+ return null;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
new file mode 100644
index 0000000..0d91e8c
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.layout;
+
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+ <p>PatternConverter is an abtract class that provides the
+ formatting functionality that derived classes need.
+
+ <p>Conversion specifiers in a conversion patterns are parsed to
+ individual PatternConverters. Each of which is responsible for
+ converting a logging event in a converter specific manner.
+
+ @since 0.8.2
+ */
+public abstract class PatternConverter {
+ public PatternConverter next;
+ int min = -1;
+ int max = 0x7FFFFFFF;
+ boolean leftAlign = false;
+
+ protected
+ PatternConverter() { }
+
+ protected
+ PatternConverter(FormattingInfo fi) {
+ min = fi.min;
+ max = fi.max;
+ leftAlign = fi.leftAlign;
+ }
+
+ /**
+ Derived pattern converters must override this method in order to
+ convert conversion specifiers in the correct way.
+ */
+ abstract
+ protected
+ String convert(PaxLoggingEvent event);
+
+ /**
+ A template method for formatting in a converter specific way.
+ */
+ public
+ void format(StringBuffer sbuf, PaxLoggingEvent e) {
+ String s = convert(e);
+
+ if(s == null) {
+ if(0 < min)
+ spacePad(sbuf, min);
+ return;
+ }
+
+ int len = s.length();
+
+ if(len > max)
+ sbuf.append(s.substring(len-max));
+ else if(len < min) {
+ if(leftAlign) {
+ sbuf.append(s);
+ spacePad(sbuf, min-len);
+ }
+ else {
+ spacePad(sbuf, min-len);
+ sbuf.append(s);
+ }
+ }
+ else
+ sbuf.append(s);
+ }
+
+ static String[] SPACES = {" ", " ", " ", " ", //1,2,4,8 spaces
+ " ", // 16 spaces
+ " " }; // 32 spaces
+
+ /**
+ Fast space padding method.
+ */
+ public
+ void spacePad(StringBuffer sbuf, int length) {
+ while(length >= 32) {
+ sbuf.append(SPACES[5]);
+ length -= 32;
+ }
+
+ for(int i = 4; i >= 0; i--) {
+ if((length & (1<<i)) != 0) {
+ sbuf.append(SPACES[i]);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
new file mode 100644
index 0000000..f61b278
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
@@ -0,0 +1,560 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.layout;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
+
+import org.apache.log4j.spi.LoggingEvent;
+import org.ops4j.pax.logging.spi.PaxLocationInfo;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+ * Copied from log4j
+ */
+/**
+ Most of the work of the {@link org.apache.log4j.PatternLayout} class
+ is delegated to the PatternParser class.
+
+ @since 0.8.2
+*/
+public class PatternParser {
+
+ private static final String LINE_SEP = System.getProperty("line.separator");
+
+ private static final char ESCAPE_CHAR = '%';
+
+ private static final int LITERAL_STATE = 0;
+ private static final int CONVERTER_STATE = 1;
+ private static final int MINUS_STATE = 2;
+ private static final int DOT_STATE = 3;
+ private static final int MIN_STATE = 4;
+ private static final int MAX_STATE = 5;
+
+ static final int FULL_LOCATION_CONVERTER = 1000;
+ static final int METHOD_LOCATION_CONVERTER = 1001;
+ static final int CLASS_LOCATION_CONVERTER = 1002;
+ static final int LINE_LOCATION_CONVERTER = 1003;
+ static final int FILE_LOCATION_CONVERTER = 1004;
+
+ static final int RELATIVE_TIME_CONVERTER = 2000;
+ static final int THREAD_CONVERTER = 2001;
+ static final int LEVEL_CONVERTER = 2002;
+ static final int NDC_CONVERTER = 2003;
+ static final int MESSAGE_CONVERTER = 2004;
+
+ int state;
+ protected StringBuffer currentLiteral = new StringBuffer(32);
+ protected int patternLength;
+ protected int i;
+ PatternConverter head;
+ PatternConverter tail;
+ protected FormattingInfo formattingInfo = new FormattingInfo();
+ protected String pattern;
+
+ public
+ PatternParser(String pattern) {
+ this.pattern = pattern;
+ patternLength = pattern.length();
+ state = LITERAL_STATE;
+ }
+
+ private
+ void addToList(PatternConverter pc) {
+ if(head == null) {
+ head = tail = pc;
+ } else {
+ tail.next = pc;
+ tail = pc;
+ }
+ }
+
+ protected
+ String extractOption() {
+ if((i < patternLength) && (pattern.charAt(i) == '{')) {
+ int end = pattern.indexOf('}', i);
+ if (end > i) {
+ String r = pattern.substring(i + 1, end);
+ i = end+1;
+ return r;
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ The option is expected to be in decimal and positive. In case of
+ error, zero is returned. */
+ protected
+ int extractPrecisionOption() {
+ String opt = extractOption();
+ int r = 0;
+ if(opt != null) {
+ try {
+ r = Integer.parseInt(opt);
+ if(r <= 0) {
+ //LogLog.error("Precision option (" + opt + ") isn't a positive integer.");
+ r = 0;
+ }
+ }
+ catch (NumberFormatException e) {
+ //LogLog.error("Category option \""+opt+"\" not a decimal integer.", e);
+ }
+ }
+ return r;
+ }
+
+ public
+ PatternConverter parse() {
+ char c;
+ i = 0;
+ while(i < patternLength) {
+ c = pattern.charAt(i++);
+ switch(state) {
+ case LITERAL_STATE:
+ // In literal state, the last char is always a literal.
+ if(i == patternLength) {
+ currentLiteral.append(c);
+ continue;
+ }
+ if(c == ESCAPE_CHAR) {
+ // peek at the next char.
+ switch(pattern.charAt(i)) {
+ case ESCAPE_CHAR:
+ currentLiteral.append(c);
+ i++; // move pointer
+ break;
+ case 'n':
+ currentLiteral.append(LINE_SEP);
+ i++; // move pointer
+ break;
+ default:
+ if(currentLiteral.length() != 0) {
+ addToList(new LiteralPatternConverter(
+ currentLiteral.toString()));
+ //LogLog.debug("Parsed LITERAL converter: \""
+ // +currentLiteral+"\".");
+ }
+ currentLiteral.setLength(0);
+ currentLiteral.append(c); // append %
+ state = CONVERTER_STATE;
+ formattingInfo.reset();
+ }
+ }
+ else {
+ currentLiteral.append(c);
+ }
+ break;
+ case CONVERTER_STATE:
+ currentLiteral.append(c);
+ switch(c) {
+ case '-':
+ formattingInfo.leftAlign = true;
+ break;
+ case '.':
+ state = DOT_STATE;
+ break;
+ default:
+ if(c >= '0' && c <= '9') {
+ formattingInfo.min = c - '0';
+ state = MIN_STATE;
+ }
+ else
+ finalizeConverter(c);
+ } // switch
+ break;
+ case MIN_STATE:
+ currentLiteral.append(c);
+ if(c >= '0' && c <= '9')
+ formattingInfo.min = formattingInfo.min*10 + (c - '0');
+ else if(c == '.')
+ state = DOT_STATE;
+ else {
+ finalizeConverter(c);
+ }
+ break;
+ case DOT_STATE:
+ currentLiteral.append(c);
+ if(c >= '0' && c <= '9') {
+ formattingInfo.max = c - '0';
+ state = MAX_STATE;
+ }
+ else {
+ //LogLog.error("Error occured in position "+i+".\n Was expecting digit, instead got char \""+c+"\".");
+ state = LITERAL_STATE;
+ }
+ break;
+ case MAX_STATE:
+ currentLiteral.append(c);
+ if(c >= '0' && c <= '9')
+ formattingInfo.max = formattingInfo.max*10 + (c - '0');
+ else {
+ finalizeConverter(c);
+ state = LITERAL_STATE;
+ }
+ break;
+ } // switch
+ } // while
+ if(currentLiteral.length() != 0) {
+ addToList(new LiteralPatternConverter(currentLiteral.toString()));
+ //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
+ }
+ return head;
+ }
+
+ protected
+ void finalizeConverter(char c) {
+ PatternConverter pc = null;
+ switch(c) {
+ case 'c':
+ pc = new CategoryPatternConverter(formattingInfo,
+ extractPrecisionOption());
+ //LogLog.debug("CATEGORY converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'C':
+ pc = new ClassNamePatternConverter(formattingInfo,
+ extractPrecisionOption());
+ //LogLog.debug("CLASS_NAME converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'd':
+ String dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT;
+ DateFormat df;
+ String dOpt = extractOption();
+ if(dOpt != null)
+ dateFormatStr = dOpt;
+
+ if(dateFormatStr.equalsIgnoreCase(
+ AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT))
+ df = new ISO8601DateFormat();
+ else if(dateFormatStr.equalsIgnoreCase(
+ AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT))
+ df = new AbsoluteTimeDateFormat();
+ else if(dateFormatStr.equalsIgnoreCase(
+ AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT))
+ df = new DateTimeDateFormat();
+ else {
+ try {
+ df = new SimpleDateFormat(dateFormatStr);
+ }
+ catch (IllegalArgumentException e) {
+ //LogLog.error("Could not instantiate SimpleDateFormat with " + dateFormatStr, e);
+ df = new ISO8601DateFormat();
+ }
+ }
+ pc = new DatePatternConverter(formattingInfo, df);
+ //LogLog.debug("DATE converter {"+dateFormatStr+"}.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'F':
+ pc = new LocationPatternConverter(formattingInfo,
+ FILE_LOCATION_CONVERTER);
+ //LogLog.debug("File name converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ /*case 'l':
+ pc = new LocationPatternConverter(formattingInfo,
+ FULL_LOCATION_CONVERTER);
+ //LogLog.debug("Location converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;*/
+ case 'L':
+ pc = new LocationPatternConverter(formattingInfo,
+ LINE_LOCATION_CONVERTER);
+ //LogLog.debug("LINE NUMBER converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'm':
+ pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
+ //LogLog.debug("MESSAGE converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'M':
+ pc = new LocationPatternConverter(formattingInfo,
+ METHOD_LOCATION_CONVERTER);
+ //LogLog.debug("METHOD converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'p':
+ pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER);
+ //LogLog.debug("LEVEL converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 'r':
+ pc = new BasicPatternConverter(formattingInfo,
+ RELATIVE_TIME_CONVERTER);
+ //LogLog.debug("RELATIVE time converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ case 't':
+ pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
+ //LogLog.debug("THREAD converter.");
+ //formattingInfo.dump();
+ currentLiteral.setLength(0);
+ break;
+ /*case 'u':
+ if(i < patternLength) {
+ char cNext = pattern.charAt(i);
+ if(cNext >= '0' && cNext <= '9') {
+ pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
+ LogLog.debug("USER converter ["+cNext+"].");
+ formattingInfo.dump();
+ currentLiteral.setLength(0);
+ i++;
+ }
+ else
+ LogLog.error("Unexpected char" +cNext+" at position "+i);
+ }
+ break;*/
+ /*case 'x':
+ pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
+ //LogLog.debug("NDC converter.");
+ currentLiteral.setLength(0);
+ break;*/
+ case 'X':
+ String xOpt = extractOption();
+ pc = new MDCPatternConverter(formattingInfo, xOpt);
+ currentLiteral.setLength(0);
+ break;
+ default:
+ //LogLog.error("Unexpected char [" +c+"] at position "+i+" in conversion patterrn.");
+ pc = new LiteralPatternConverter(currentLiteral.toString());
+ currentLiteral.setLength(0);
+ }
+
+ addConverter(pc);
+ }
+
+ protected
+ void addConverter(PatternConverter pc) {
+ currentLiteral.setLength(0);
+ // Add the pattern converter to the list.
+ addToList(pc);
+ // Next pattern is assumed to be a literal.
+ state = LITERAL_STATE;
+ // Reset formatting info
+ formattingInfo.reset();
+ }
+
+ // ---------------------------------------------------------------------
+ // PatternConverters
+ // ---------------------------------------------------------------------
+
+ private static class BasicPatternConverter extends PatternConverter {
+ int type;
+
+ BasicPatternConverter(FormattingInfo formattingInfo, int type) {
+ super(formattingInfo);
+ this.type = type;
+ }
+
+ public
+ String convert(PaxLoggingEvent event) {
+ switch(type) {
+ case RELATIVE_TIME_CONVERTER:
+ return (Long.toString(event.getTimeStamp() - LoggingEvent.getStartTime()));
+ case THREAD_CONVERTER:
+ return event.getThreadName();
+ case LEVEL_CONVERTER:
+ return event.getLevel().toString();
+ // case NDC_CONVERTER:
+ //return event.getNDC();
+ case MESSAGE_CONVERTER: {
+ return event.getRenderedMessage();
+ }
+ default: return null;
+ }
+ }
+ }
+
+ private static class LiteralPatternConverter extends PatternConverter {
+ private String literal;
+
+ LiteralPatternConverter(String value) {
+ literal = value;
+ }
+
+ public
+ final
+ void format(StringBuffer sbuf, LoggingEvent event) {
+ sbuf.append(literal);
+ }
+
+ public
+ String convert(PaxLoggingEvent event) {
+ return literal;
+ }
+ }
+
+ private static class DatePatternConverter extends PatternConverter {
+ private DateFormat df;
+ private Date date;
+
+ DatePatternConverter(FormattingInfo formattingInfo, DateFormat df) {
+ super(formattingInfo);
+ date = new Date();
+ this.df = df;
+ }
+
+ public
+ String convert(PaxLoggingEvent event) {
+ date.setTime(event.getTimeStamp());
+ String converted = null;
+ try {
+ converted = df.format(date);
+ }
+ catch (Exception ex) {
+ //LogLog.error("Error occured while converting date.", ex);
+ }
+ return converted;
+ }
+ }
+
+ private class LocationPatternConverter extends PatternConverter {
+ int type;
+
+ LocationPatternConverter(FormattingInfo formattingInfo, int type) {
+ super(formattingInfo);
+ this.type = type;
+ }
+
+ public
+ String convert(PaxLoggingEvent event) {
+ PaxLocationInfo locationInfo = event.getLocationInformation();
+ switch(type) {
+ /*case FULL_LOCATION_CONVERTER:
+ return locationInfo.fullInfo;*/
+ case METHOD_LOCATION_CONVERTER:
+ return locationInfo.getMethodName();
+ case LINE_LOCATION_CONVERTER:
+ return locationInfo.getLineNumber();
+ case FILE_LOCATION_CONVERTER:
+ return locationInfo.getFileName();
+ default: return null;
+ }
+ }
+ }
+
+ private static abstract class NamedPatternConverter extends PatternConverter {
+ int precision;
+
+ NamedPatternConverter(FormattingInfo formattingInfo, int precision) {
+ super(formattingInfo);
+ this.precision = precision;
+ }
+
+ abstract
+ String getFullyQualifiedName(PaxLoggingEvent event);
+
+ public
+ String convert(PaxLoggingEvent event) {
+ String n = getFullyQualifiedName(event);
+ if(precision <= 0)
+ return n;
+ else {
+ int len = n.length();
+
+ // We substract 1 from 'len' when assigning to 'end' to avoid out of
+ // bounds exception in return r.substring(end+1, len). This can happen if
+ // precision is 1 and the category name ends with a dot.
+ int end = len -1 ;
+ for(int i = precision; i > 0; i--) {
+ end = n.lastIndexOf('.', end-1);
+ if(end == -1)
+ return n;
+ }
+ return n.substring(end+1, len);
+ }
+ }
+ }
+
+ private class ClassNamePatternConverter extends NamedPatternConverter {
+
+ ClassNamePatternConverter(FormattingInfo formattingInfo, int precision) {
+ super(formattingInfo, precision);
+ }
+
+ String getFullyQualifiedName(PaxLoggingEvent event) {
+ return event.getLocationInformation().getClassName();
+ }
+ }
+
+ private class CategoryPatternConverter extends NamedPatternConverter {
+
+ CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
+ super(formattingInfo, precision);
+ }
+
+ String getFullyQualifiedName(PaxLoggingEvent event) {
+ return event.getLoggerName();
+ }
+ }
+
+ private class MDCPatternConverter extends PatternConverter {
+ String key;
+
+ MDCPatternConverter(FormattingInfo formattingInfo, String key) {
+ super(formattingInfo);
+ this.key = key;
+ }
+
+ public
+ String convert(PaxLoggingEvent event) {
+ if (key == null) {
+ StringBuffer buf = new StringBuffer("{");
+ Map properties = event.getProperties();
+ if (properties.size() > 0) {
+ Object[] keys = properties.keySet().toArray();
+ Arrays.sort(keys);
+ for (int i = 0; i < keys.length; i++) {
+ buf.append('{');
+ buf.append(keys[i]);
+ buf.append(',');
+ buf.append(properties.get(keys[i]));
+ buf.append('}');
+ }
+ }
+ buf.append('}');
+ return buf.toString();
+ } else {
+ Object val = event.getProperties().get(key);
+ if(val == null) {
+ return null;
+ } else {
+ return val.toString();
+ }
+ }
+ }
+
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java b/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..2e8c4d8
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal.osgi;
+
+import java.util.Hashtable;
+
+import org.apache.karaf.log.core.LogEventFormatter;
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.log.core.internal.LogEventFormatterImpl;
+import org.apache.karaf.log.core.internal.LogMBeanImpl;
+import org.apache.karaf.log.core.internal.LogServiceImpl;
+import org.apache.karaf.log.core.internal.LruList;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+
+public class Activator extends BaseActivator implements ManagedService {
+
+ @Override
+ protected void doOpen() throws Exception {
+ manage("org.apache.karaf.log");
+ trackService(ConfigurationAdmin.class);
+ }
+
+ protected void doStart() throws Exception {
+ ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
+ if (configurationAdmin == null) {
+ return;
+ }
+
+ int size = getInt("size", 500);
+ String pattern = getString("pattern", "%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n");
+ String fatalColor = getString("fatalColor", "31");
+ String errorColor = getString("errorColor", "31");
+ String warnColor = getString("warnColor", "35");
+ String infoColor = getString("infoColor", "36");
+ String debugColor = getString("debugColor", "39");
+ String traceColor = getString("traceColor", "39");
+
+ LruList events = new LruList(size);
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+ props.put("org.ops4j.pax.logging.appender.name", "VmLogAppender");
+ register(PaxAppender.class, events, props);
+
+ LogEventFormatterImpl formatter = new LogEventFormatterImpl();
+ formatter.setPattern(pattern);
+ formatter.setFatalColor(fatalColor);
+ formatter.setErrorColor(errorColor);
+ formatter.setWarnColor(warnColor);
+ formatter.setInfoColor(infoColor);
+ formatter.setDebugColor(debugColor);
+ formatter.setTraceColor(traceColor);
+ register(LogEventFormatter.class, formatter);
+
+ LogServiceImpl logService = new LogServiceImpl(configurationAdmin, events);
+ register(LogService.class, logService);
+
+ LogMBeanImpl securityMBean = new LogMBeanImpl(logService);
+ registerMBean(securityMBean, "type=log");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/log/src/main/resources/OSGI-INF/bundle.info b/log/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..2bd45bd
--- /dev/null
+++ b/log/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,24 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+The log mbean management bundle exposes a Log MBean that can be used with any JMX client (for instance JConsole).
+
+The Log MBean allows quite the same actions that can be performed using log:* commands:
+ * display()
+ * display(logger)
+ * get()
+ * get(logger)
+ * set(level)
+ * list(level, logger)
+
+h1. See also
+
+ * Monitoring and Administration using JMX - section of the Karaf User Guide
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/log/src/main/resources/OSGI-INF/metatype/metatype.properties b/log/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..713283f
--- /dev/null
+++ b/log/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor
+
+log.name = Apache Karaf Log
+log.description = Configuration of Apache Karaf Log
+
+size.name = Size
+size.description = size of the log to keep in memory
+
+pattern.name = Pattern
+pattern.description = Pattern used to display log entries
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/log/src/main/resources/OSGI-INF/metatype/metatype.xml b/log/src/main/resources/OSGI-INF/metatype/metatype.xml
new file mode 100644
index 0000000..147cb82
--- /dev/null
+++ b/log/src/main/resources/OSGI-INF/metatype/metatype.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
+ <OCD id="org.apache.karaf.log" name="%log.name" description="%log.description">
+ <AD id="size" type="Integer" default="500" name="%size.name"
+ description="%size.description"/>
+ <AD id="pattern" type="String" default="%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n" name="%pattern.name"
+ description="%pattern.description"/>
+ </OCD>
+ <Designate pid="org.apache.karaf.log">
+ <Object ocdref="org.apache.karaf.log"/>
+ </Designate>
+</metatype:MetaData>
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
----------------------------------------------------------------------
diff --git a/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java b/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
new file mode 100644
index 0000000..73459d3
--- /dev/null
+++ b/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.log.core.internal;
+
+import java.util.Hashtable;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.log.core.LogMBean;
+import org.apache.karaf.log.core.LogService;
+import org.easymock.EasyMock;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Test cases for {@link SetLogLevel}
+ */
+@SuppressWarnings("unchecked")
+public class SetLogLevelTest extends TestCase {
+
+ private static final String ROOT_LOGGER = "log4j.rootLogger";
+ private static final String PACKAGE_LOGGER = "log4j.logger.org.apache.karaf.test";
+
+ private LogService logService;
+ private LogMBean logMBean;
+ @SuppressWarnings("rawtypes")
+ private Hashtable properties;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ properties = new Hashtable<String, String>();
+ final Configuration configuration = EasyMock.createMock(Configuration.class);
+ EasyMock.expect(configuration.getProperties()).andReturn(properties);
+ configuration.update(properties);
+ ConfigurationAdmin configAdmin = EasyMock.createMock(ConfigurationAdmin.class);
+ EasyMock.expect(configAdmin.getConfiguration(LogServiceImpl.CONFIGURATION_PID, null)).andReturn(configuration);
+ logService = new LogServiceImpl(configAdmin, new LruList(100));
+ logMBean = new LogMBeanImpl(logService);
+ EasyMock.replay(configAdmin);
+ EasyMock.replay(configuration);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testInvalidLogLevel() throws Exception {
+ try {
+ logMBean.setLevel("INVALID");
+ fail("Exception expected");
+ } catch(IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ public void testSetLogLevel() throws Exception {
+ logMBean.setLevel("org.apache.karaf.test", "INFO");
+ assertEquals("INFO", properties.get(PACKAGE_LOGGER));
+ }
+
+ public void testSetRootLogLevel() throws Exception {
+ logMBean.setLevel("INFO");
+ assertEquals("INFO", properties.get(ROOT_LOGGER));
+ }
+
+ public void testSetLogLevelLowerCase() throws Exception {
+ logMBean.setLevel("org.apache.karaf.test", "info");
+ assertEquals("INFO", properties.get(PACKAGE_LOGGER));
+ }
+
+ public void testSetRootLogLevelLowerCase() throws Exception {
+ logMBean.setLevel("info");
+ assertEquals("INFO", properties.get(ROOT_LOGGER));
+ }
+
+ public void testChangeLogLevel() throws Exception {
+ properties.put(PACKAGE_LOGGER, "DEBUG");
+ logMBean.setLevel("org.apache.karaf.test", "INFO");
+ assertEquals("INFO", properties.get(PACKAGE_LOGGER));
+ }
+
+ public void testChangeRootLogLevel() throws Exception {
+ properties.put(ROOT_LOGGER, "DEBUG");
+ logMBean.setLevel("INFO");
+ assertEquals("INFO", properties.get(ROOT_LOGGER));
+ }
+
+ public void testChangeLogLevelWithAppender() throws Exception {
+ properties.put(PACKAGE_LOGGER, "DEBUG, APPENDER1");
+ logMBean.setLevel("org.apache.karaf.test", "INFO");
+ assertEquals("INFO, APPENDER1", properties.get(PACKAGE_LOGGER));
+ }
+
+ public void testChangeRootLogLevelWithAppender() throws Exception {
+ properties.put(ROOT_LOGGER, "DEBUG, APPENDER1");
+ logMBean.setLevel("INFO");
+ assertEquals("INFO, APPENDER1", properties.get(ROOT_LOGGER));
+ }
+
+ public void testUnsetLogLevel() throws Exception {
+ properties.put(PACKAGE_LOGGER, "DEBUG");
+ logMBean.setLevel("org.apache.karaf.test", "DEFAULT");
+ assertFalse("Configuration for logger org.apache.karaf.test has been removed", properties.containsKey(PACKAGE_LOGGER));
+ }
+
+ public void testUnsetRootLogLevel() throws Exception {
+ properties.put(ROOT_LOGGER, "INFO");
+ logMBean.setLevel("org.apache.karaf.test", "DEFAULT");
+ assertEquals("Configuration for root logger should not be removed", "INFO", properties.get(ROOT_LOGGER));
+ }
+
+}