Repository: karaf Updated Branches: refs/heads/master 8fd6385a6 -> b5c0ec02b
Revert KARAF-2761 and the standalone extender for annotations from KARAF-2763 Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/b5c0ec02 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/b5c0ec02 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/b5c0ec02 Branch: refs/heads/master Commit: b5c0ec02b692dea047c38b80dcadf47237579aa0 Parents: 8fd6385 Author: Guillaume Nodet <[email protected]> Authored: Thu Feb 20 20:23:18 2014 +0100 Committer: Guillaume Nodet <[email protected]> Committed: Thu Feb 20 20:24:01 2014 +0100 ---------------------------------------------------------------------- .../apache/karaf/shell/commands/Commands.java | 345 ------------------ .../shell/inject/impl/InjectionExtender.java | 100 ------ .../shell/inject/impl/InjectionExtension.java | 350 ------------------- .../shell/inject/impl/MultiServiceTracker.java | 89 ----- .../karaf/shell/inject/impl/Satisfiable.java | 30 -- .../shell/inject/impl/SingleServiceTracker.java | 160 --------- .../OSGI-INF/blueprint/karaf-console.xml | 7 - 7 files changed, 1081 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/java/org/apache/karaf/shell/commands/Commands.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/commands/Commands.java b/shell/console/src/main/java/org/apache/karaf/shell/commands/Commands.java deleted file mode 100644 index b9e782f..0000000 --- a/shell/console/src/main/java/org/apache/karaf/shell/commands/Commands.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * 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.shell.commands; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.felix.service.command.CommandProcessor; -import org.apache.felix.service.command.Function; -import org.apache.karaf.shell.commands.basic.AbstractCommand; -import org.apache.karaf.shell.commands.converter.DefaultConverter; -import org.apache.karaf.shell.commands.converter.GenericType; -import org.apache.karaf.shell.commands.converter.ReifiedType; -import org.apache.karaf.shell.console.CompletableFunction; -import org.apache.karaf.shell.console.Completer; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.ServiceRegistration; - -/** - * - */ -public class Commands { - - protected final List<CommandBuilder> commandBuilders = new ArrayList<CommandBuilder>(); - protected final List<CompleterBuilder> completerBuilders = new ArrayList<CompleterBuilder>(); - - protected DefaultConverter converter; - - protected BundleContext context; - - public BundleContext getContext() { - if (context == null) { - context = FrameworkUtil.getBundle(getClass()).getBundleContext(); - } - return context; - } - - public void setContext(BundleContext context) { - this.context = context; - } - - public DefaultConverter getConverter() { - if (converter == null) { - converter = new DefaultConverter(getContext().getBundle()); - } - return converter; - } - - public void setConverter(DefaultConverter converter) { - this.converter = converter; - } - - public void register() { - for (CompleterBuilder builder : completerBuilders) { - builder.register(); - } - for (CommandBuilder builder : commandBuilders) { - builder.register(); - } - } - - public void unregister() { - for (CommandBuilder commandBuilder : commandBuilders) { - commandBuilder.unregister(); - } - for (CompleterBuilder builder : completerBuilders) { - builder.unregister(); - } - } - - public CommandBuilder command() { - CommandBuilder commandBuilder = new CommandBuilder(); - commandBuilders.add(commandBuilder); - return commandBuilder; - } - - public CommandBuilder command(Class<? extends Action> actionClass) { - return command().action(actionClass); - } - - public CompleterBuilder completer(Completer completer) { - CompleterBuilder completerBuilder = new CompleterBuilder(completer); - completerBuilders.add(completerBuilder); - return completerBuilder; - } - - public class CompleterBuilder { - protected Completer completer; - protected ServiceRegistration registration; - - public CompleterBuilder(Completer completer) { - this.completer = completer; - } - - public void register() { - if (registration == null) { - Hashtable<String, String> props = new Hashtable<String, String>(); - String[] classes = { - Completer.class.getName(), - completer.getClass().getName() - }; - registration = getContext().registerService(classes, completer, props); - } - } - - protected void unregister() { - if (registration != null) { - registration.unregister(); - } - } - - } - - public class CommandBuilder { - protected Class<? extends Action> clazz; - protected final List<Object> arguments = new ArrayList<Object>(); - protected final List<Object> properties = new ArrayList<Object>(); - protected ServiceRegistration registration; - protected final List<Completer> argCompleters = new ArrayList<Completer>(); - protected final Map<String, Completer> optionCompleters = new HashMap<String, Completer>(); - protected final Map<String, String> serviceProperties = new HashMap<String, String>(); - - public CommandBuilder action(Class<? extends Action> actionClass) { - this.clazz = actionClass; - return this; - } - - public CommandBuilder arguments(Object... arguments) { - this.arguments.addAll(Arrays.asList(arguments)); - return this; - } - - public CommandBuilder properties(Object... properties) { - this.properties.addAll(Arrays.asList(properties)); - return this; - } - - public CommandBuilder argCompleter(Completer completer) { - this.argCompleters.add(completer); - return this; - } - - public CommandBuilder optionCompleter(String option, Completer completer) { - this.optionCompleters.put(option, completer); - return this; - } - - public CommandBuilder serviceProp(String key, String val) { - this.serviceProperties.put(key, val); - return this; - } - - public void register() { - if (registration == null) { - Command cmd = getCommand(); - Hashtable<String, String> props = new Hashtable<String, String>(); - props.put(CommandProcessor.COMMAND_SCOPE, cmd.scope()); - props.put(CommandProcessor.COMMAND_FUNCTION, cmd.name()); - props.putAll(serviceProperties); - String[] classes = { - Function.class.getName(), - CompletableFunction.class.getName(), - CommandWithAction.class.getName(), - AbstractCommand.class.getName() - }; - registration = getContext().registerService(classes, new CommandWrapper(this), props); - } - } - - protected void unregister() { - if (registration != null) { - registration.unregister(); - } - } - - private Action createNewAction() { - try { - Action action; - // Instantiate action - Map<Constructor, List<Object>> matches = findMatchingConstructors(clazz, arguments); - if (matches.size() == 1) { - Map.Entry<Constructor, List<Object>> match = matches.entrySet().iterator().next(); - action = (Action) match.getKey().newInstance(match.getValue().toArray()); - } else if (matches.size() == 0) { - throw new IllegalArgumentException("Unable to find a matching constructor on class " + clazz.getName() + " for arguments " + arguments + " when instanciating command " + getName()); - } else { - throw new IllegalArgumentException("Multiple matching constructors found on class " + clazz + " for arguments " + arguments + " when instanciating bean " + getName() + ": " + matches.keySet()); - } - // Inject action - for (Object prop : properties) { - Method setter = null; - for (Method method : clazz.getMethods()) { - if (method.getName().startsWith("set") && method.getReturnType() == void.class - && method.getParameterTypes().length == 1 - && method.getParameterTypes()[0].isInstance(prop)) { - if (setter == null) { - setter = method; - } else { - throw new IllegalArgumentException("Property " + prop + " matches multiple setters on class " + clazz.getName()); - } - } - } - if (setter == null) { - throw new IllegalArgumentException("Property " + prop + " has no matching setter on class " + clazz.getName()); - } - setter.invoke(action, prop); - } - return action; - } catch (Exception e) { - throw new RuntimeException("Unable to create action", e); - } - } - - private String getName() { - Command cmd = getCommand(); - return cmd.scope() + ":" + cmd.name(); - } - - private Command getCommand() { - Command cmd = clazz.getAnnotation(Command.class); - if (cmd == null) - { - throw new IllegalArgumentException("Action class is not annotated with @Command"); - } - return cmd; - } - - } - - public static class CommandWrapper extends AbstractCommand implements CompletableFunction { - private final CommandBuilder builder; - - public CommandWrapper(CommandBuilder builder) { - this.builder = builder; - } - - @Override - public org.apache.felix.gogo.commands.Action createNewAction() { - return builder.createNewAction(); - } - - @Override - public List<Completer> getCompleters() { - return builder.argCompleters; - } - - @Override - public Map<String, Completer> getOptionalCompleters() { - return builder.optionCompleters; - } - } - - private Map<Constructor, List<Object>> findMatchingConstructors(Class type, List<Object> args) { - Map<Constructor, List<Object>> matches = new HashMap<Constructor, List<Object>>(); - // Get constructors - List<Constructor> constructors = new ArrayList<Constructor>(Arrays.asList(type.getConstructors())); - // Discard any signature with wrong cardinality - for (Iterator<Constructor> it = constructors.iterator(); it.hasNext();) { - if (it.next().getParameterTypes().length != args.size()) { - it.remove(); - } - } - // Find a direct match with assignment - if (matches.size() != 1) { - Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>(); - for (Constructor cns : constructors) { - boolean found = true; - List<Object> match = new ArrayList<Object>(); - for (int i = 0; i < args.size(); i++) { - ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]); - //If the arg is an Unwrappered bean then we need to do the assignment check against the - //unwrappered bean itself. - Object arg = args.get(i); - Object argToTest = arg; - if (!DefaultConverter.isAssignable(argToTest, argType)) { - found = false; - break; - } - try { - match.add(getConverter().convert(arg, cns.getGenericParameterTypes()[i])); - } catch (Throwable t) { - found = false; - break; - } - } - if (found) { - nmatches.put(cns, match); - } - } - if (nmatches.size() > 0) { - matches = nmatches; - } - } - // Find a direct match with conversion - if (matches.size() != 1) { - Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>(); - for (Constructor cns : constructors) { - boolean found = true; - List<Object> match = new ArrayList<Object>(); - for (int i = 0; i < args.size(); i++) { - ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]); - try { - Object val = getConverter().convert(args.get(i), argType); - match.add(val); - } catch (Throwable t) { - found = false; - break; - } - } - if (found) { - nmatches.put(cns, match); - } - } - if (nmatches.size() > 0) { - matches = nmatches; - } - } - return matches; - } - -} http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtender.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtender.java b/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtender.java deleted file mode 100644 index 6177390..0000000 --- a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtender.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.shell.inject.impl; - -import org.apache.felix.utils.extender.AbstractExtender; -import org.apache.felix.utils.extender.Extension; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Bundle extender scanning for command classes. - */ -public class InjectionExtender extends AbstractExtender { - - public static final String KARAF_COMMANDS = "Karaf-Injection"; - - private static final Logger LOGGER = LoggerFactory.getLogger(InjectionExtender.class); - - // - // Adapt BundleActivator to make it blueprint friendly - // - - private BundleContext bundleContext; - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - public void init() throws Exception { - start(bundleContext); - } - - public void destroy() throws Exception { - stop(bundleContext); - } - - // - // Extender implementation - // - - @Override - protected Extension doCreateExtension(Bundle bundle) throws Exception { - if (bundle.getHeaders().get(KARAF_COMMANDS) != null) { - return new InjectionExtension(bundle); - } - return null; - } - - @Override - protected void debug(Bundle bundle, String msg) { - StringBuilder buf = new StringBuilder(); - if ( bundle != null ) - { - buf.append( bundle.getSymbolicName() ); - buf.append( " (" ); - buf.append( bundle.getBundleId() ); - buf.append( "): " ); - } - buf.append(msg); - LOGGER.debug(buf.toString()); - } - - @Override - protected void warn(Bundle bundle, String msg, Throwable t) { - StringBuilder buf = new StringBuilder(); - if ( bundle != null ) - { - buf.append( bundle.getSymbolicName() ); - buf.append( " (" ); - buf.append( bundle.getBundleId() ); - buf.append( "): " ); - } - buf.append(msg); - LOGGER.warn(buf.toString(), t); - } - - @Override - protected void error(String msg, Throwable t) { - LOGGER.error(msg, t); - } - -} http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtension.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtension.java b/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtension.java deleted file mode 100644 index fd807a3..0000000 --- a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/InjectionExtension.java +++ /dev/null @@ -1,350 +0,0 @@ -/* - * 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.shell.inject.impl; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.apache.felix.gogo.commands.Action; -import org.apache.felix.service.command.CommandProcessor; -import org.apache.felix.service.command.Function; -import org.apache.felix.utils.extender.Extension; -import org.apache.felix.utils.manifest.Clause; -import org.apache.felix.utils.manifest.Parser; -import org.apache.karaf.shell.commands.Command; -import org.apache.karaf.shell.commands.CommandWithAction; -import org.apache.karaf.shell.inject.Destroy; -import org.apache.karaf.shell.inject.Init; -import org.apache.karaf.shell.inject.Reference; -import org.apache.karaf.shell.inject.Service; -import org.apache.karaf.shell.commands.basic.AbstractCommand; -import org.apache.karaf.shell.console.BundleContextAware; -import org.apache.karaf.shell.console.CompletableFunction; -import org.apache.karaf.shell.console.Completer; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; -import org.osgi.framework.wiring.BundleWiring; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Commands extension - */ -public class InjectionExtension implements Extension, Satisfiable { - - private static final Logger LOGGER = LoggerFactory.getLogger(InjectionExtension.class); - - private final Bundle bundle; - private final CountDownLatch started; - private final MultiServiceTracker tracker; - private final List<Satisfiable> satisfiables = new ArrayList<Satisfiable>(); - - - public InjectionExtension(Bundle bundle) { - this.bundle = bundle; - this.started = new CountDownLatch(1); - this.tracker = new MultiServiceTracker(bundle.getBundleContext(), this); - } - - @Override - public void found() { - for (Satisfiable s : satisfiables) { - s.found(); - } - } - - @Override - public void updated() { - for (Satisfiable s : satisfiables) { - s.updated(); - } - } - - @Override - public void lost() { - for (Satisfiable s : satisfiables) { - s.lost(); - } - } - - public void start() throws Exception { - try { - String header = bundle.getHeaders().get(InjectionExtender.KARAF_COMMANDS); - Clause[] clauses = Parser.parseHeader(header); - BundleWiring wiring = bundle.adapt(BundleWiring.class); - for (Clause clause : clauses) { - String name = clause.getName(); - int options = BundleWiring.LISTRESOURCES_LOCAL; - name = name.replace('.', '/'); - if (name.endsWith("*")) { - options |= BundleWiring.LISTRESOURCES_RECURSE; - name = name.substring(0, name.length() - 1); - } - if (!name.startsWith("/")) { - name = "/" + name; - } - if (name.endsWith("/")) { - name = name.substring(0, name.length() - 1); - } - Collection<String> classes = wiring.listResources(name, "*.class", options); - for (String className : classes) { - className = className.replace('/', '.').replace(".class", ""); - inspectClass(bundle.loadClass(className)); - } - } - tracker.open(); - } finally { - started.countDown(); - } - } - - public void destroy() { - try { - started.await(5000, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - LOGGER.warn("The wait for bundle being started before destruction has been interrupted.", e); - } - tracker.close(); - } - - private void inspectClass(final Class<?> clazz) throws Exception { - Service reg = clazz.getAnnotation(Service.class); - if (reg == null) { - return; - } - if (Action.class.isAssignableFrom(clazz)) { - final Command cmd = clazz.getAnnotation(Command.class); - if (cmd == null) { - throw new IllegalArgumentException("Command " + clazz.getName() + " is not annotated with @Command"); - } - // Create trackers - for (Class<?> cl = clazz; cl != Object.class; cl = cl.getSuperclass()) { - for (Field field : cl.getDeclaredFields()) { - if (field.getAnnotation(Reference.class) != null) { - if (field.getType() != BundleContext.class) { - tracker.track(field.getType()); - } - } - } - } - satisfiables.add(new AutoRegisterCommand((Class<? extends Action>) clazz)); - } - if (Completer.class.isAssignableFrom(clazz)) { - // Create trackers - for (Class<?> cl = clazz; cl != Object.class; cl = cl.getSuperclass()) { - for (Field field : cl.getDeclaredFields()) { - if (field.getAnnotation(Reference.class) != null) { - if (field.getType() != BundleContext.class) { - tracker.track(field.getType()); - } - } - } - } - satisfiables.add(new AutoRegisterService(clazz)); - } - } - - public class AutoRegisterService implements Satisfiable { - - private final Class<?> clazz; - private Object service; - private ServiceRegistration registration; - - public AutoRegisterService(Class<?> clazz) { - this.clazz = clazz; - } - - @Override - public void found() { - try { - // Create completer - service = clazz.newInstance(); - Set<String> classes = new HashSet<String>(); - // Inject services - for (Class<?> cl = clazz; cl != Object.class; cl = cl.getSuperclass()) { - classes.add(cl.getName()); - for (Class c : cl.getInterfaces()) { - classes.add(c.getName()); - } - for (Field field : cl.getDeclaredFields()) { - if (field.getAnnotation(Reference.class) != null) { - Object value; - if (field.getType() == BundleContext.class) { - value = InjectionExtension.this.bundle.getBundleContext(); - } else { - value = InjectionExtension.this.tracker.getService(field.getType()); - } - if (value == null) { - throw new RuntimeException("No OSGi service matching " + field.getType().getName()); - } - field.setAccessible(true); - field.set(service, value); - } - } - } - for (Method method : clazz.getDeclaredMethods()) { - Init ann = method.getAnnotation(Init.class); - if (ann != null && method.getParameterTypes().length == 0 && method.getReturnType() == void.class) { - method.setAccessible(true); - method.invoke(service); - } - } - Hashtable<String, String> props = new Hashtable<String, String>(); - registration = bundle.getBundleContext().registerService(classes.toArray(new String[classes.size()]), service, props); - } catch (Exception e) { - throw new RuntimeException("Unable to creation service " + clazz.getName(), e); - } - } - - @Override - public void updated() { - lost(); - found(); - } - - @Override - public void lost() { - if (registration != null) { - for (Method method : clazz.getDeclaredMethods()) { - Destroy ann = method.getAnnotation(Destroy.class); - if (ann != null && method.getParameterTypes().length == 0 && method.getReturnType() == void.class) { - method.setAccessible(true); - try { - method.invoke(service); - } catch (Exception e) { - LOGGER.warn("Error destroying service", e); - } - } - } - registration.unregister(); - registration = null; - } - } - - } - - public class AutoRegisterCommand extends AbstractCommand implements Satisfiable, CompletableFunction { - - private final Class<? extends Action> actionClass; - private ServiceRegistration registration; - - public AutoRegisterCommand(Class<? extends Action> actionClass) { - this.actionClass = actionClass; - } - - @Override - public void found() { - // Register command - Command cmd = actionClass.getAnnotation(Command.class); - Hashtable<String, String> props = new Hashtable<String, String>(); - props.put(CommandProcessor.COMMAND_SCOPE, cmd.scope()); - props.put(CommandProcessor.COMMAND_FUNCTION, cmd.name()); - String[] classes = { - Function.class.getName(), - CompletableFunction.class.getName(), - CommandWithAction.class.getName(), - AbstractCommand.class.getName() - }; - registration = bundle.getBundleContext().registerService(classes, this, props); - } - - @Override - public void updated() { - - } - - @Override - public void lost() { - if (registration != null) { - registration.unregister(); - registration = null; - } - } - - @Override - public Action createNewAction() { - try { - Action action = actionClass.newInstance(); - // Inject services - for (Class<?> cl = actionClass; cl != Object.class; cl = cl.getSuperclass()) { - for (Field field : cl.getDeclaredFields()) { - if (field.getAnnotation(Reference.class) != null) { - Object value; - if (field.getType() == BundleContext.class) { - value = InjectionExtension.this.bundle.getBundleContext(); - } else { - value = InjectionExtension.this.tracker.getService(field.getType()); - } - if (value == null) { - throw new RuntimeException("No OSGi service matching " + field.getType().getName()); - } - field.setAccessible(true); - field.set(action, value); - } - } - } - if (action instanceof BundleContextAware) { - ((BundleContextAware) action).setBundleContext(bundle.getBundleContext()); - } - for (Method method : actionClass.getDeclaredMethods()) { - Init ann = method.getAnnotation(Init.class); - if (ann != null && method.getParameterTypes().length == 0 && method.getReturnType() == void.class) { - method.setAccessible(true); - method.invoke(action); - } - } - return action; - } catch (Exception e) { - throw new RuntimeException("Unable to creation command action " + actionClass.getName(), e); - } - } - - @Override - public void releaseAction(Action action) throws Exception { - for (Method method : actionClass.getDeclaredMethods()) { - Destroy ann = method.getAnnotation(Destroy.class); - if (ann != null && method.getParameterTypes().length == 0 && method.getReturnType() == void.class) { - method.setAccessible(true); - method.invoke(action); - } - } - super.releaseAction(action); - } - - @Override - public List<Completer> getCompleters() { - return null; - } - - @Override - public Map<String, Completer> getOptionalCompleters() { - return null; - } - } -} http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/MultiServiceTracker.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/MultiServiceTracker.java b/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/MultiServiceTracker.java deleted file mode 100644 index 5394dca..0000000 --- a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/MultiServiceTracker.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.shell.inject.impl; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.osgi.framework.BundleContext; - -/** - * Track multiple services by their type - */ -public class MultiServiceTracker { - - private final BundleContext bundleContext; - private final Satisfiable satisfiable; - private final ConcurrentMap<Class, SingleServiceTracker> trackers = new ConcurrentHashMap<Class, SingleServiceTracker>(); - private final AtomicInteger count = new AtomicInteger(); - - public MultiServiceTracker(BundleContext bundleContext, Satisfiable satisfiable) { - this.bundleContext = bundleContext; - this.satisfiable = satisfiable; - } - - @SuppressWarnings("unchecked") - public void track(Class service) { - if (trackers.get(service) == null) { - SingleServiceTracker tracker = new SingleServiceTracker(bundleContext, service, new Satisfiable() { - @Override - public void found() { - if (count.incrementAndGet() == trackers.size()) { - satisfiable.found(); - } - } - - @Override - public void updated() { - if (count.get() == trackers.size()) { - satisfiable.updated(); - } - } - - @Override - public void lost() { - if (count.getAndDecrement() == trackers.size()) { - satisfiable.lost(); - } - } - - }); - trackers.putIfAbsent(service, tracker); - } - } - - public <T> T getService(Class<T> clazz) { - SingleServiceTracker tracker = trackers.get(clazz); - return tracker != null ? clazz.cast(tracker.getService()) : null; - } - - public void open() { - for (SingleServiceTracker tracker : trackers.values()) { - tracker.open(); - } - } - - public void close() { - for (SingleServiceTracker tracker : trackers.values()) { - tracker.close(); - } - } - -} http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/Satisfiable.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/Satisfiable.java b/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/Satisfiable.java deleted file mode 100644 index ed5ceb6..0000000 --- a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/Satisfiable.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.shell.inject.impl; - -/** - * Interface to be called with a boolean satisfaction status. - */ -public interface Satisfiable { - - void found(); - void updated(); - void lost(); - -} http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/SingleServiceTracker.java ---------------------------------------------------------------------- diff --git a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/SingleServiceTracker.java b/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/SingleServiceTracker.java deleted file mode 100644 index 9ecec4d..0000000 --- a/shell/console/src/main/java/org/apache/karaf/shell/inject/impl/SingleServiceTracker.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * 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.shell.inject.impl; - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.Filter; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceEvent; -import org.osgi.framework.ServiceListener; -import org.osgi.framework.ServiceReference; - -/** - * Track a single service by its type. - * - * @param <T> - */ -public final class SingleServiceTracker<T> { - - private final BundleContext ctx; - private final String className; - private final AtomicReference<T> service = new AtomicReference<T>(); - private final AtomicReference<ServiceReference> ref = new AtomicReference<ServiceReference>(); - private final AtomicBoolean open = new AtomicBoolean(false); - private final Satisfiable serviceListener; - private Filter filter; - - private final ServiceListener listener = new ServiceListener() { - public void serviceChanged(ServiceEvent event) { - if (open.get()) { - if (event.getType() == ServiceEvent.UNREGISTERING) { - ServiceReference deadRef = event.getServiceReference(); - if (deadRef.equals(ref.get())) { - findMatchingReference(deadRef); - } - } else if (event.getType() == ServiceEvent.REGISTERED && ref.get() == null) { - findMatchingReference(null); - } - } - } - }; - - public SingleServiceTracker(BundleContext context, Class<T> clazz, Satisfiable sl) { - ctx = context; - this.className = clazz.getName(); - serviceListener = sl; - } - - public T getService() { - return service.get(); - } - - public ServiceReference getServiceReference() { - return ref.get(); - } - - public void open() { - if (open.compareAndSet(false, true)) { - try { - String filterString = '(' + Constants.OBJECTCLASS + '=' + className + ')'; - if (filter != null) filterString = "(&" + filterString + filter + ')'; - ctx.addServiceListener(listener, filterString); - findMatchingReference(null); - } catch (InvalidSyntaxException e) { - // this can never happen. (famous last words :) - } - } - } - - private void findMatchingReference(ServiceReference original) { - boolean clear = true; - ServiceReference ref = ctx.getServiceReference(className); - if (ref != null && (filter == null || filter.match(ref))) { - @SuppressWarnings("unchecked") - T service = (T) ctx.getService(ref); - if (service != null) { - clear = false; - - // We do the unget out of the lock so we don't exit this class while holding a lock. - if (!!!update(original, ref, service)) { - ctx.ungetService(ref); - } - } - } else if (original == null) { - clear = false; - } - - if (clear) { - update(original, null, null); - } - } - - private boolean update(ServiceReference deadRef, ServiceReference newRef, T service) { - boolean result = false; - int foundLostReplaced = -1; - - // Make sure we don't try to get a lock on null - Object lock; - - // we have to choose our lock. - if (newRef != null) lock = newRef; - else if (deadRef != null) lock = deadRef; - else lock = this; - - // This lock is here to ensure that no two threads can set the ref and service - // at the same time. - synchronized (lock) { - if (open.get()) { - result = this.ref.compareAndSet(deadRef, newRef); - if (result) { - this.service.set(service); - - if (deadRef == null && newRef != null) foundLostReplaced = 0; - if (deadRef != null && newRef == null) foundLostReplaced = 1; - if (deadRef != null && newRef != null) foundLostReplaced = 2; - } - } - } - - if (serviceListener != null) { - if (foundLostReplaced == 0) serviceListener.found(); - else if (foundLostReplaced == 1) serviceListener.lost(); - else if (foundLostReplaced == 2) serviceListener.updated(); - } - - return result; - } - - public void close() { - if (open.compareAndSet(true, false)) { - ctx.removeServiceListener(listener); - - synchronized (this) { - ServiceReference deadRef = ref.getAndSet(null); - service.set(null); - if (deadRef != null) ctx.ungetService(deadRef); - } - } - } - -} http://git-wip-us.apache.org/repos/asf/karaf/blob/b5c0ec02/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml ---------------------------------------------------------------------- diff --git a/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml b/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml index 1abeb1e..bbe0c5b 100644 --- a/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml +++ b/shell/console/src/main/resources/OSGI-INF/blueprint/karaf-console.xml @@ -82,11 +82,4 @@ </bean> <service ref="secureCommandConfigTransformer" interface="org.osgi.service.cm.ConfigurationListener"/> - <!-- Console commands extender --> - <bean id="consoleExtender" - class="org.apache.karaf.shell.inject.impl.InjectionExtender" - init-method="init" destroy-method="destroy"> - <property name="bundleContext" ref="blueprintBundleContext"/> - </bean> - </blueprint>
