/*
* 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.impl.console;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import org.apache.karaf.shell.api.console.Command;
import org.apache.karaf.shell.api.console.Registry;
public class RegistryImpl implements Registry {
protected final Registry parent;
protected final Map<Object, Object> services = new LinkedHashMap<Object, Object>();
private final Map<String, List<Command>> commands = new HashMap<String, List<Command>>();
public RegistryImpl(Registry parent) {
this.parent = parent;
}
@Override
public List<Command> getCommands() {
return getServices(Command.class);
}
@Override
public Command getCommand(String scope, String name) {
if (parent != null) {
Command command = parent.getCommand(scope, name);
if (command != null) {
return command;
}
}
synchronized (services) {
List<Command> cmds = commands.get(scope + ":" + name);
if (cmds != null && !cmds.isEmpty()) {
return cmds.get(0);
}
}
return null;
}
@Override
public <T> void register(Callable<T> factory, Class<T> clazz) {
synchronized (services) {
services.put(factory, new Factory<T>(clazz, factory));
}
}
@Override
public void register(Object service) {
synchronized (services) {
services.put(service, service);
if (service instanceof Command) {
Command cmd = (Command) service;
String key = cmd.getScope() + ":" + cmd.getName();
List<Command> cmds = commands.get(key);
if (cmds == null) {
cmds = new ArrayList<Command>();
commands.put(key, cmds);
}
cmds.add(cmd);
}
}
}
@Override
public void unregister(Object service) {
synchronized (services) {
services.remove(service);
if (service instanceof Command) {
Command cmd = (Command) service;
String key = cmd.getScope() + ":" + cmd.getName();
List<Command> cmds = commands.get(key);
if (cmds != null) {
cmds.remove(cmd);
if (cmds.isEmpty()) {
commands.remove(key);
}
}
}
}
}
@Override
public <T> T getService(Class<T> clazz) {
synchronized (services) {
for (Object service : services.values()) {
if (service instanceof Factory) {
if (clazz.isAssignableFrom(((Factory<?>) service).clazz)) {
if (isVisible(service)) {
try {
return clazz.cast(((Factory<?>) service).callable.call());
} catch (Exception e) {
// TODO: log exception
}
}
}
} else if (clazz.isInstance(service)) {
if (isVisible(service)) {
return clazz.cast(service);
}
}
}
}
if (parent != null) {
return parent.getService(clazz);
}
return null;
}
@Override
public <T> List<T> getServices(Class<T> clazz) {
List<T> list = new ArrayList<T>();
synchronized (services) {
for (Object service : services.values()) {
if (service instanceof Factory) {
if (clazz.isAssignableFrom(((Factory<?>) service).clazz)) {
if (isVisible(service)) {
try {
list.add(clazz.cast(((Factory<?>) service).callable.call()));
} catch (Exception e) {
// TODO: log exception
}
}
}
} else if (clazz.isInstance(service)) {
if (isVisible(service)) {
list.add(clazz.cast(service));
}
}
}
}
if (parent != null) {
list.addAll(parent.getServices(clazz));
}
return list;
}
@Override
public boolean hasService(Class<?> clazz) {
synchronized (services) {
for (Object service : services.values()) {
if (service instanceof Factory) {
if (clazz.isAssignableFrom(((Factory<?>) service).clazz)) {
if (isVisible(service)) {
return true;
}
}
} else if (clazz.isInstance(service)) {
if (isVisible(service)) {
return true;
}
}
}
}
if (parent != null) {
return parent.hasService(clazz);
}
return false;
}
protected boolean isVisible(Object service) {
return true;
}
static class Factory<T> {
final Class<T> clazz;
final Callable<T> callable;
Factory(Class<T> clazz, Callable<T> callable) {
this.clazz = clazz;
this.callable = callable;
}
}
}