/* * 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.syslog.impl; import java.net.InetSocketAddress; import java.net.SocketException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Invalidate; import org.apache.felix.ipojo.annotations.Provides; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.Validate; import org.krakenapps.confdb.Config; import org.krakenapps.confdb.ConfigDatabase; import org.krakenapps.confdb.ConfigService; import org.krakenapps.confdb.Predicates; import org.krakenapps.syslog.Syslog; import org.krakenapps.syslog.SyslogListener; import org.krakenapps.syslog.SyslogProfile; import org.krakenapps.syslog.SyslogServer; import org.krakenapps.syslog.SyslogServerRegistry; import org.krakenapps.syslog.SyslogServerRegistryEventListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(name = "syslog-server-registry") @Provides(specifications = { SyslogServerRegistry.class }) public class SyslogServerRegistryImpl implements SyslogServerRegistry, SyslogListener { private final Logger logger = LoggerFactory.getLogger(SyslogServerRegistryImpl.class.getName()); private ConcurrentMap<String, SyslogServer> serverMap; private Set<SyslogListener> syslogCallbacks; private Set<SyslogServerRegistryEventListener> eventCallbacks; @Requires private ConfigService conf; public SyslogServerRegistryImpl() { serverMap = new ConcurrentHashMap<String, SyslogServer>(); syslogCallbacks = Collections.newSetFromMap(new ConcurrentHashMap<SyslogListener, Boolean>()); eventCallbacks = Collections.newSetFromMap(new ConcurrentHashMap<SyslogServerRegistryEventListener, Boolean>()); } /** * load all persistent syslog servers */ @Validate public void start() { for (SyslogProfile p : getSyslogProfiles()) { try { SyslogReceiver server = new SyslogReceiver(p); server.open(); server.addListener(this); serverMap.put(p.getName(), server); } catch (Throwable t) { logger.error("kraken syslog: cannot open syslog server", t); } } } /** * close all syslog servers */ @Invalidate public void stop() { for (SyslogServer server : serverMap.values()) { try { server.removeListener(this); server.close(); } catch (Throwable t) { logger.error("kraken syslog: cannot close - " + server, t); } } } @Override public boolean contains(String name) { return serverMap.containsKey(name); } @Override public Collection<String> getNames() { return new ArrayList<String>(serverMap.keySet()); } @Override public SyslogServer getServer(String name) { return serverMap.get(name); } @Override public SyslogServer findServer(InetSocketAddress local) { if (local == null) return null; for (String name : serverMap.keySet()) { SyslogServer server = serverMap.get(name); if (server.getListenAddress().equals(local)) return server; } return null; } @Override public void register(String name, SyslogServer server) { SyslogServer old = serverMap.putIfAbsent(name, server); if (old != null) { logger.warn("kraken syslog: duplicated server name [{}]", name); return; } logger.info("kraken syslog: [{}, addr={}] syslog server registered", name, server.getListenAddress()); // add callback server.addListener(this); for (SyslogServerRegistryEventListener callback : eventCallbacks) { try { callback.syslogServerAdded(name, server); } catch (Exception e) { logger.warn("kraken syslog: registry event callback should not throw any exception", e); } } } @Override public void unregister(String name) { SyslogServer server = serverMap.remove(name); logger.info("kraken syslog: [{}, addr={}] syslog server unregistered", name, server.getListenAddress()); // remove callback server.removeListener(this); for (SyslogServerRegistryEventListener callback : eventCallbacks) { try { callback.syslogServerRemoved(name, server); } catch (Exception e) { logger.warn("kraken syslog: registry event callback should not throw any exception", e); } } } @Override public void addSyslogListener(SyslogListener callback) { if (callback == null) { return; } syslogCallbacks.add(callback); } @Override public void removeSyslogListener(SyslogListener callback) { if (callback == null) { return; } syslogCallbacks.remove(callback); } @Override public void addEventListener(SyslogServerRegistryEventListener callback) { if (callback == null) return; eventCallbacks.add(callback); } @Override public void removeEventListener(SyslogServerRegistryEventListener callback) { if (callback == null) return; eventCallbacks.remove(callback); } @Override public void onReceive(Syslog syslog) { for (SyslogListener callback : syslogCallbacks) { try { callback.onReceive(syslog); } catch (Exception e) { logger.warn("kraken syslog: syslog callback should not throw any exception", e); } } } @Override public Collection<SyslogProfile> getSyslogProfiles() { ConfigDatabase db = conf.ensureDatabase("kraken-syslog"); return db.findAll(SyslogProfile.class).getDocuments(SyslogProfile.class); } @Override public void open(SyslogProfile profile) throws SocketException { for (SyslogProfile p : getSyslogProfiles()) { if (p.getName().equals(profile.getName())) throw new IllegalStateException("duplicated syslog server name"); if (p.getListenAddress().equals(profile.getListenAddress())) throw new IllegalStateException("listen address conflict"); } SyslogReceiver server = new SyslogReceiver(profile); server.open(); // add callback server.addListener(this); serverMap.put(profile.getName(), server); ConfigDatabase db = conf.ensureDatabase("kraken-syslog"); db.add(profile); } @Override public void close(String name) { SyslogServer server = serverMap.remove(name); if (server != null) { // remove callback server.removeListener(this); server.close(); } ConfigDatabase db = conf.ensureDatabase("kraken-syslog"); Config c = db.findOne(SyslogProfile.class, Predicates.field("name", name)); if (c != null) db.remove(c); } }