Applied patch (FELIX-1052) to add "log" command to shell.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@769156 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/shell/pom.xml b/shell/pom.xml
index 92ffc0a..2fc6abf 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -35,6 +35,11 @@
<artifactId>org.osgi.core</artifactId>
<version>1.2.0</version>
</dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>1.2.0</version>
+ </dependency>
</dependencies>
<build>
<plugins>
@@ -45,7 +50,7 @@
<extensions>true</extensions>
<configuration>
<instructions>
- <Export-Package>org.apache.felix.shell; org.ungoverned.osgi.service.shell; version=1.0.0</Export-Package>
+ <Export-Package>org.osgi.service.log, org.apache.felix.shell; org.ungoverned.osgi.service.shell; version=1.0.0</Export-Package>
<Private-Package>org.apache.felix.*</Private-Package>
<Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
<Bundle-Activator>org.apache.felix.shell.impl.Activator</Bundle-Activator>
diff --git a/shell/src/main/java/org/apache/felix/shell/impl/Activator.java b/shell/src/main/java/org/apache/felix/shell/impl/Activator.java
index 8940ad6..92ff81a 100644
--- a/shell/src/main/java/org/apache/felix/shell/impl/Activator.java
+++ b/shell/src/main/java/org/apache/felix/shell/impl/Activator.java
@@ -122,6 +122,11 @@
org.apache.felix.shell.Command.class.getName(),
new InstallCommandImpl(m_context), null);
+ // Register "log" command service.
+ context.registerService(
+ org.apache.felix.shell.Command.class.getName(),
+ new LogCommandImpl(m_context), null);
+
// Register "ps" command service.
context.registerService(
org.apache.felix.shell.Command.class.getName(),
diff --git a/shell/src/main/java/org/apache/felix/shell/impl/LogCommandImpl.java b/shell/src/main/java/org/apache/felix/shell/impl/LogCommandImpl.java
new file mode 100644
index 0000000..dca09e8
--- /dev/null
+++ b/shell/src/main/java/org/apache/felix/shell/impl/LogCommandImpl.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.felix.shell.impl;
+
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Enumeration;
+
+import org.apache.felix.shell.Command;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogReaderService;
+
+/**
+ * Apache Felix Shell command to display recent log entries
+ */
+public class LogCommandImpl implements Command
+{
+ private final BundleContext m_bundleContext;
+
+ public LogCommandImpl(BundleContext context)
+ {
+ m_bundleContext = context;
+ }
+
+ public void execute(String line, PrintStream out, PrintStream err)
+ {
+ LogOptions options = new LogOptions(line);
+
+ ServiceReference ref =
+ m_bundleContext.getServiceReference(LogReaderService.class.getName());
+ if (ref != null)
+ {
+ LogReaderService service = (LogReaderService) m_bundleContext.getService(ref);
+ Enumeration entries = service.getLog();
+
+ int index = 0;
+ while (entries.hasMoreElements()
+ && (options.getMaxNumberOfLogs() < 0 | index < options.getMaxNumberOfLogs()))
+ {
+ LogEntry entry = (LogEntry) entries.nextElement();
+ if (entry.getLevel() <= options.getMinLevel())
+ {
+ display(entry, out);
+ index++;
+ }
+ }
+ }
+ else
+ {
+ out.println("No LogReaderService available");
+ }
+ }
+
+ private void display(LogEntry entry, PrintStream out)
+ {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
+
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(sdf.format(new Date(entry.getTime()))).append(" ");
+ buffer.append(levelAsAString(entry.getLevel())).append(" - ");
+ buffer.append("Bundle:").append(entry.getBundle().getSymbolicName()).append(" ");
+ if (entry.getServiceReference() != null)
+ {
+ buffer.append(entry.getServiceReference().toString()).append(" ");
+ }
+ buffer.append("- ").append(entry.getMessage()).append(" - ");
+ if (entry.getException() != null)
+ {
+ buffer.append(entry.getException().getClass().getName()).append(": ").append(
+ entry.getException().getMessage());
+ }
+
+ out.println(buffer.toString());
+ }
+
+ private String levelAsAString(int level)
+ {
+ switch (level)
+ {
+ case 1:
+ return "ERROR";
+ case 2:
+ return "WARNING";
+ case 3:
+ return "INFO";
+ default:
+ return "DEBUG";
+ }
+ }
+
+ public String getName()
+ {
+ return "log";
+ }
+
+ public String getShortDescription()
+ {
+ return "list the most recent log entries";
+ }
+
+ public String getUsage()
+ {
+ return "log [<max log entries>] [error | warn | info | debug]";
+ }
+}
\ No newline at end of file
diff --git a/shell/src/main/java/org/apache/felix/shell/impl/LogOptions.java b/shell/src/main/java/org/apache/felix/shell/impl/LogOptions.java
new file mode 100644
index 0000000..1106570
--- /dev/null
+++ b/shell/src/main/java/org/apache/felix/shell/impl/LogOptions.java
@@ -0,0 +1,86 @@
+/*
+ * 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.felix.shell.impl;
+
+import java.util.StringTokenizer;
+
+/**
+ * Parse and encapsulate command line options
+ *
+ */
+public class LogOptions
+{
+ private int minLevel = 4;
+ private int maxNumberOfLogs = -1;
+
+ public LogOptions(String commandLine)
+ {
+ StringTokenizer st = new StringTokenizer(commandLine);
+ readOptions(st);
+ }
+
+ private void readOptions(StringTokenizer st)
+ {
+ if (st.countTokens() > 1)
+ {
+ st.nextToken();
+ String firstOption = st.nextToken();
+ checkOption(firstOption);
+
+ if (st.hasMoreTokens())
+ {
+ checkOption(st.nextToken());
+ }
+ }
+ }
+
+ private void checkOption(String opt)
+ {
+ try
+ {
+ maxNumberOfLogs = Integer.parseInt(opt);
+ }
+ catch (NumberFormatException nfe)
+ {
+ //do nothing, it's not a number
+ }
+ if ("info".equalsIgnoreCase(opt))
+ {
+ minLevel = 3;
+ }
+ else if ("warn".equalsIgnoreCase(opt))
+ {
+ minLevel = 2;
+ }
+ else if ("error".equalsIgnoreCase(opt))
+ {
+ minLevel = 1;
+ }
+ }
+
+ public int getMinLevel()
+ {
+ return minLevel;
+ }
+
+ public int getMaxNumberOfLogs()
+ {
+ return maxNumberOfLogs;
+ }
+}
\ No newline at end of file
diff --git a/shell/src/test/java/org/apache/felix/shell/impl/LogOptionsTest.java b/shell/src/test/java/org/apache/felix/shell/impl/LogOptionsTest.java
new file mode 100644
index 0000000..9a26083
--- /dev/null
+++ b/shell/src/test/java/org/apache/felix/shell/impl/LogOptionsTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.felix.shell.impl;
+
+import junit.framework.TestCase;
+
+public class LogOptionsTest extends TestCase
+{
+ public void testOnlyLogCommand()
+ {
+ LogOptions opt = new LogOptions("log");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log ");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelDebug()
+ {
+ LogOptions opt = new LogOptions("log debug");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log DEBUG");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelInfo()
+ {
+ LogOptions opt = new LogOptions("log info");
+ assertEquals(3, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log INFO");
+ assertEquals(3, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelWarn()
+ {
+ LogOptions opt = new LogOptions("log warn");
+ assertEquals(2, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log WARN");
+ assertEquals(2, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelError()
+ {
+ LogOptions opt = new LogOptions("log error");
+ assertEquals(1, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log ERROR");
+ assertEquals(1, opt.getMinLevel());
+ assertEquals(-1, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMaxNumberOfLogs()
+ {
+ LogOptions opt = new LogOptions("log 42");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(42, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelDebugAndMaxNumberOfLogs()
+ {
+ LogOptions opt = new LogOptions("log debug 12");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(12, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log 13 DEBUG");
+ assertEquals(4, opt.getMinLevel());
+ assertEquals(13, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelInfoAndMaxNumberOfLogs()
+ {
+ LogOptions opt = new LogOptions("log info 14");
+ assertEquals(3, opt.getMinLevel());
+ assertEquals(14, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log 15 INFO");
+ assertEquals(3, opt.getMinLevel());
+ assertEquals(15, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelWarnAndMaxNumberOfLogs()
+ {
+ LogOptions opt = new LogOptions("log warn 16");
+ assertEquals(2, opt.getMinLevel());
+ assertEquals(16, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log 17 WARN");
+ assertEquals(2, opt.getMinLevel());
+ assertEquals(17, opt.getMaxNumberOfLogs());
+ }
+
+ public void testLogWithMinLevelErrorAndMaxNumberOfLogs()
+ {
+ LogOptions opt = new LogOptions("log error 18");
+ assertEquals(1, opt.getMinLevel());
+ assertEquals(18, opt.getMaxNumberOfLogs());
+
+ opt = new LogOptions("log 19 ERROR");
+ assertEquals(1, opt.getMinLevel());
+ assertEquals(19, opt.getMaxNumberOfLogs());
+ }
+}
\ No newline at end of file