/* * Copyright 2010 NCHOVY * * Licensed 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.krakenapps.rpc.impl; import java.util.Collection; import org.krakenapps.rpc.RpcConnection; import org.krakenapps.rpc.RpcService; import org.krakenapps.rpc.RpcServiceBinding; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RpcServiceTracker implements ServiceListener { private final Logger logger = LoggerFactory.getLogger(RpcServiceTracker.class.getName()); private BundleContext bc; private RpcHandler handler; public RpcServiceTracker(BundleContext bc, RpcHandler handler) { this.bc = bc; this.handler = handler; } public void scan() { try { ServiceReference[] refs = bc.getAllServiceReferences(RpcService.class.getName(), null); if (refs == null) return; for (ServiceReference ref : refs) { serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, ref)); } } catch (InvalidSyntaxException e) { } } @Override public void serviceChanged(ServiceEvent event) { ServiceReference reference = event.getServiceReference(); Object service = bc.getService(reference); if (!(service instanceof RpcService)) return; String className = service.getClass().getName(); logger.trace("kraken-rpc: inspecting service {}, event {}", className, event.getType()); String rpcName = (String) reference.getProperty("rpc.name"); if (rpcName == null) return; Collection<RpcConnection> connections = handler.getConnections(); if (event.getType() == ServiceEvent.REGISTERED) { handler.addService((RpcService) service, rpcName); for (RpcConnection conn : connections) { try { logger.info("kraken-rpc: auto-binding [{}] as [{}] service for connection [{}:{}]", new Object[] { className, rpcName, conn.getId(), conn.getRemoteAddress() }); conn.bind(rpcName, (RpcService) service); } catch (Exception e) { logger.warn("kraken-rpc: [" + className + "] auto-binding failed", e); } } } else if (event.getType() == ServiceEvent.UNREGISTERING) { handler.removeService((RpcService) service); for (RpcConnection conn : connections) { try { RpcServiceBinding binding = conn.findServiceBinding(rpcName); if (binding == null) continue; // if service references are same, unbind it. if (binding.getService() == service) { conn.unbind(rpcName); logger.info("kraken-rpc: [{} ({})] service unbound for connection [{}:{}]", new Object[] { rpcName, className, conn.getId(), conn.getRemoteAddress() }); } } catch (Exception e) { logger.error("kraken-rpc: [" + className + "] auto-binding for connection " + conn.getId() + " failed", e); } } } } }