[FELIX-2761][FELIX-2764] Add a listener interface called when executing commands, send an osgi event if EventAdmin is present
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1055258 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/gogo/runtime/pom.xml b/gogo/runtime/pom.xml
index ace4cfa..667d09d 100644
--- a/gogo/runtime/pom.xml
+++ b/gogo/runtime/pom.xml
@@ -60,6 +60,7 @@
org.apache.felix.service.threadio; version=${project.version}; status="provisional"; mandatory:="status"
</Export-Package>
<Import-Package>
+ org.osgi.service.event*; resolution:=optional,
org.osgi.service.log*; resolution:=optional,
org.osgi.service.packageadmin*; resolution:=optional,
org.osgi.service.startlevel*; resolution:=optional,
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
index 724f189..6cbb70b 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandProcessorImpl.java
@@ -21,10 +21,18 @@
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
-import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
-import org.osgi.framework.BundleContext;
+import org.apache.felix.service.command.CommandSessionListener;
import org.apache.felix.service.command.CommandProcessor;
import org.apache.felix.service.command.CommandSession;
import org.apache.felix.service.command.Converter;
@@ -34,6 +42,7 @@
public class CommandProcessorImpl implements CommandProcessor
{
protected final Set<Converter> converters = new HashSet<Converter>();
+ protected final Set<CommandSessionListener> listeners = new CopyOnWriteArraySet<CommandSessionListener>();
protected final Map<String, Object> commands = new LinkedHashMap<String, Object>();
protected final Map<String, Object> constants = new HashMap<String, Object>();
protected final ThreadIO threadIO;
@@ -69,6 +78,17 @@
converters.remove(c);
}
+ public void addListener(CommandSessionListener l)
+ {
+ listeners.add(l);
+ }
+
+ public void removeListener(CommandSessionListener l)
+ {
+ listeners.remove(l);
+ }
+
+
public Set<String> getCommands()
{
return commands.keySet();
@@ -243,4 +263,50 @@
return session.execute(buf);
}
+
+ void beforeExecute(CommandSession session, CharSequence commandline)
+ {
+ for (CommandSessionListener l : listeners)
+ {
+ try
+ {
+ l.beforeExecute(session, commandline);
+ }
+ catch (Throwable t)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ void afterExecute(CommandSession session, CharSequence commandline, Exception exception)
+ {
+ for (CommandSessionListener l : listeners)
+ {
+ try
+ {
+ l.afterExecute(session, commandline, exception);
+ }
+ catch (Throwable t)
+ {
+ // Ignore
+ }
+ }
+ }
+
+ void afterExecute(CommandSession session, CharSequence commandline, Object result)
+ {
+ for (CommandSessionListener l : listeners)
+ {
+ try
+ {
+ l.afterExecute(session, commandline, result);
+ }
+ catch (Throwable t)
+ {
+ // Ignore
+ }
+ }
+ }
+
}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
index 42d7ee1..447e735 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/CommandSessionImpl.java
@@ -81,18 +81,18 @@
throw new IllegalStateException(SESSION_CLOSED);
}
- beforeExecute(commandline);
+ processor.beforeExecute(this, commandline);
try
{
Closure impl = new Closure(this, null, commandline);
Object result = impl.execute(this, null);
- afterExecute(commandline, result);
+ processor.afterExecute(this, commandline, result);
return result;
}
catch (Exception e)
{
- afterExecute(commandline, e);
+ processor.afterExecute(this, commandline, e);
throw e;
}
}
@@ -386,19 +386,4 @@
}
}
- protected void beforeExecute(CharSequence commandline)
- {
- // Centralized callback for derived implementation
- }
-
- protected void afterExecute(CharSequence commandline, Exception exception)
- {
- // Centralized callback for derived implementation
- }
-
- protected void afterExecute(CharSequence commandline, Object result)
- {
- // Centralized callback for derived implementation
- }
-
}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
index d42a898..b60ed65 100644
--- a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/Activator.java
@@ -23,6 +23,7 @@
import org.apache.felix.gogo.runtime.CommandProcessorImpl;
import org.apache.felix.gogo.runtime.CommandProxy;
+import org.apache.felix.service.command.CommandSessionListener;
import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -42,6 +43,7 @@
private ThreadIOImpl threadio;
private ServiceTracker commandTracker;
private ServiceTracker converterTracker;
+ private ServiceTracker listenerTracker;
private ServiceRegistration processorRegistration;
private ServiceRegistration threadioRegistration;
@@ -50,6 +52,14 @@
protected ServiceRegistration newProcessor(ThreadIO tio, BundleContext context)
{
processor = new CommandProcessorImpl(tio);
+ try
+ {
+ processor.addListener(new EventAdminListener(context));
+ }
+ catch (NoClassDefFoundError error)
+ {
+ // Ignore the listener if EventAdmin package isn't present
+ }
// Setup the variables and commands exposed in an OSGi environment.
processor.addConstant(CONTEXT, context);
@@ -90,6 +100,23 @@
}
};
converterTracker.open();
+
+ listenerTracker = new ServiceTracker(context, CommandSessionListener.class.getName(), null)
+ {
+ @Override
+ public Object addingService(ServiceReference reference) {
+ CommandSessionListener listener = (CommandSessionListener) super.addingService(reference);
+ processor.addListener(listener);
+ return listener;
+ }
+
+ @Override
+ public void removedService(ServiceReference reference, Object service) {
+ processor.removeListener((CommandSessionListener) service);
+ super.removedService(reference, service);
+ }
+ };
+ listenerTracker.open();
}
public void stop(BundleContext context) throws Exception
@@ -98,6 +125,7 @@
threadioRegistration.unregister();
commandTracker.close();
converterTracker.close();
+ listenerTracker.close();
threadio.stop();
processor.stop();
}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java
new file mode 100644
index 0000000..2ac94d0
--- /dev/null
+++ b/gogo/runtime/src/main/java/org/apache/felix/gogo/runtime/activator/EventAdminListener.java
@@ -0,0 +1,59 @@
+/*
+ * 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.gogo.runtime.activator;
+
+import java.util.Properties;
+
+import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.CommandSessionListener;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class EventAdminListener implements CommandSessionListener
+{
+
+ private BundleContext bundleContext;
+ private ServiceTracker tracker;
+
+ public EventAdminListener(BundleContext bundleContext)
+ {
+ this.bundleContext = bundleContext;
+ tracker = new ServiceTracker(bundleContext, EventAdmin.class.getName(), null);
+ tracker.open();
+ }
+
+ public void beforeExecute(CommandSession session, CharSequence command) {
+ EventAdmin admin = (EventAdmin) tracker.getService();
+ if (admin != null) {
+ Properties props = new Properties();
+ props.setProperty("command", command.toString());
+ Event event = new Event("org/apache/felix/service/command/EXECUTING", props);
+ admin.postEvent(event);
+ }
+ }
+
+ public void afterExecute(CommandSession session, CharSequence command, Exception exception) {
+ }
+
+ public void afterExecute(CommandSession session, CharSequence command, Object result) {
+ }
+
+}
diff --git a/gogo/runtime/src/main/java/org/apache/felix/service/command/CommandSessionListener.java b/gogo/runtime/src/main/java/org/apache/felix/service/command/CommandSessionListener.java
new file mode 100644
index 0000000..30e9b21
--- /dev/null
+++ b/gogo/runtime/src/main/java/org/apache/felix/service/command/CommandSessionListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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.service.command;
+
+/**
+ * Listener for command executions.
+ *
+ * Such listeners must be registered in the OSGi registry and will be called
+ * by the CommandProcessor when a command line is executed in a given session.
+ */
+public interface CommandSessionListener {
+
+ void beforeExecute(CommandSession session, CharSequence command);
+
+ void afterExecute(CommandSession session, CharSequence command, Exception exception);
+
+ void afterExecute(CommandSession session, CharSequence command, Object result);
+
+}