blob: 7f4f2420e0739fbc4a9655ee8b93c119a63eba8e [file] [log] [blame]
/*
* 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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.felix.gogo.runtime.CommandProcessorImpl;
import org.apache.felix.gogo.runtime.CommandProxy;
import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
import org.apache.felix.service.command.CommandSessionListener;
import org.apache.felix.service.command.CommandProcessor;
import org.apache.felix.service.command.Converter;
import org.apache.felix.service.threadio.ThreadIO;
import org.osgi.annotation.bundle.Header;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
@Header(name = Constants.BUNDLE_ACTIVATOR, value = "${@class}")
public class Activator implements BundleActivator
{
protected CommandProcessorImpl processor;
private ThreadIOImpl threadio;
private ServiceTracker<?,?> commandTracker;
private ServiceTracker<?,?> converterTracker;
private ServiceTracker<?,?> listenerTracker;
private ServiceRegistration<?> processorRegistration;
private ServiceRegistration<?> threadioRegistration;
public static final String CONTEXT = ".context";
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);
processor.addCommand("osgi", processor, "addCommand");
processor.addCommand("osgi", processor, "removeCommand");
processor.addCommand("osgi", processor, "eval");
return context.registerService(CommandProcessor.class.getName(), processor, null);
}
public void start(final BundleContext context) throws Exception
{
threadio = new ThreadIOImpl();
threadio.start();
threadioRegistration = context.registerService(ThreadIO.class.getName(), threadio, null);
processorRegistration = newProcessor(threadio, context);
commandTracker = trackOSGiCommands(context);
commandTracker.open();
converterTracker = new ServiceTracker<Converter, Converter>(context, Converter.class, null)
{
@Override
public Converter addingService(ServiceReference<Converter> reference)
{
Converter converter = super.addingService(reference);
processor.addConverter(converter);
return converter;
}
@Override
public void removedService(ServiceReference<Converter> reference, Converter service)
{
processor.removeConverter(service);
super.removedService(reference, service);
}
};
converterTracker.open();
listenerTracker = new ServiceTracker<CommandSessionListener, CommandSessionListener>(context, CommandSessionListener.class.getName(), null)
{
@Override
public CommandSessionListener addingService(ServiceReference<CommandSessionListener> reference)
{
CommandSessionListener listener = super.addingService(reference);
processor.addListener(listener);
return listener;
}
@Override
public void removedService(ServiceReference<CommandSessionListener> reference, CommandSessionListener service)
{
processor.removeListener(service);
super.removedService(reference, service);
}
};
listenerTracker.open();
}
public void stop(BundleContext context) {
processorRegistration.unregister();
threadioRegistration.unregister();
commandTracker.close();
converterTracker.close();
listenerTracker.close();
threadio.stop();
processor.stop();
}
private ServiceTracker<?,?> trackOSGiCommands(final BundleContext context)
throws InvalidSyntaxException
{
Filter filter = context.createFilter(String.format("(&(%s=*)(%s=*))",
CommandProcessor.COMMAND_SCOPE, CommandProcessor.COMMAND_FUNCTION));
return new ServiceTracker<Object, List<Object>>(context, filter, null)
{
private final ConcurrentMap<ServiceReference<Object>, Map<String, CommandProxy>> proxies
= new ConcurrentHashMap<>();
@Override
public List<Object> addingService(ServiceReference<Object> reference)
{
Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
Object ranking = reference.getProperty(Constants.SERVICE_RANKING);
List<Object> commands = new ArrayList<>();
int rank = 0;
if (ranking != null)
{
try
{
rank = Integer.parseInt(ranking.toString());
}
catch (NumberFormatException e)
{
// Ignore
}
}
if (scope != null && function != null)
{
Map<String, CommandProxy> proxyMap = new HashMap<>();
if (function.getClass().isArray())
{
for (Object f : ((Object[]) function))
{
CommandProxy target = new CommandProxy(context, reference, f.toString());
proxyMap.put(f.toString(), target);
processor.addCommand(scope.toString(), target, f.toString(), rank);
commands.add(target);
}
}
else
{
CommandProxy target = new CommandProxy(context, reference, function.toString());
proxyMap.put(function.toString(), target);
processor.addCommand(scope.toString(), target, function.toString(), rank);
commands.add(target);
}
proxies.put(reference, proxyMap);
return commands;
}
return null;
}
@Override
public void removedService(ServiceReference<Object> reference, List<Object> service)
{
Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
if (scope != null && function != null)
{
Map<String, CommandProxy> proxyMap = proxies.remove(reference);
for (Map.Entry<String, CommandProxy> entry : proxyMap.entrySet())
{
processor.removeCommand(scope.toString(), entry.getKey(), entry.getValue());
}
}
super.removedService(reference, service);
}
};
}
}