/*
* Copyright 2011 Future Systems
*
* 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.syslogmon.impl;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
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.log.api.AbstractLoggerFactory;
import org.krakenapps.log.api.Logger;
import org.krakenapps.log.api.LoggerConfigOption;
import org.krakenapps.log.api.LoggerSpecification;
import org.krakenapps.log.api.StringConfigType;
import org.krakenapps.syslog.Syslog;
import org.krakenapps.syslog.SyslogListener;
import org.krakenapps.syslog.SyslogServerRegistry;
import org.krakenapps.syslogmon.SyslogClassifier;
import org.krakenapps.syslogmon.SyslogClassifierRegistry;
@Component(name = "syslog-relay-logger-factory")
@Provides
public class SyslogRelayLoggerFactory extends AbstractLoggerFactory implements SyslogListener {
private org.slf4j.Logger slog = org.slf4j.LoggerFactory.getLogger(SyslogRelayLoggerFactory.class.getName());
@Requires
private SyslogClassifierRegistry classifierRegistry;
@Requires
private SyslogServerRegistry syslogRegistry;
private ConcurrentMap<InetAddress, String> classifierMappings;
private ConcurrentMap<VirtualLoggerKey, SyslogRelayLogger> loggerMappings;
private List<LoggerConfigOption> configOptions;
@Validate
public void start() {
classifierMappings = new ConcurrentHashMap<InetAddress, String>();
loggerMappings = new ConcurrentHashMap<SyslogRelayLoggerFactory.VirtualLoggerKey, SyslogRelayLogger>();
prepareConfigOptions();
syslogRegistry.addSyslogListener(this);
}
@Invalidate
public void stop() {
if (syslogRegistry != null)
syslogRegistry.removeSyslogListener(this);
}
@Override
public String getName() {
return "syslog-relay";
}
@Override
public String getDescription(Locale locale) {
return "relayed syslog logger";
}
@Override
public String getDisplayName(Locale locale) {
return "syslogger for relayed syslog";
}
@Override
public Collection<LoggerConfigOption> getConfigOptions() {
return configOptions;
}
@Override
protected Logger createLogger(LoggerSpecification spec) {
SyslogRelayLogger virtualLogger = new SyslogRelayLogger(spec, this);
try {
Properties config = spec.getConfig();
InetAddress remote = InetAddress.getByName(config.getProperty("remote_ip"));
String classifier = config.getProperty("classifier");
if (classifier == null)
throw new IllegalArgumentException("classifier name should not be null");
String identifier = config.getProperty("identifier");
if (identifier == null)
throw new IllegalArgumentException("identifier should not be null");
// create mapping. classifier should be only one per remote address
String oldClassifier = classifierMappings.putIfAbsent(remote, classifier);
if (oldClassifier != null && !oldClassifier.equals(classifier))
throw new IllegalArgumentException("classifier should be " + oldClassifier + " for " + remote);
// set logger mapping
loggerMappings.put(new VirtualLoggerKey(remote, identifier), virtualLogger);
} catch (UnknownHostException e) {
throw new IllegalArgumentException("unknown remote_ip", e);
}
return virtualLogger;
}
private void prepareConfigOptions() {
configOptions = new ArrayList<LoggerConfigOption>();
{
Map<Locale, String> names = new HashMap<Locale, String>();
Map<Locale, String> descriptions = new HashMap<Locale, String>();
names.put(Locale.ENGLISH, "remote ip");
descriptions.put(Locale.ENGLISH, "remote syslog sender's ip address");
configOptions.add(new StringConfigType("remote_ip", names, descriptions, true));
}
{
Map<Locale, String> names = new HashMap<Locale, String>();
Map<Locale, String> descriptions = new HashMap<Locale, String>();
names.put(Locale.ENGLISH, "syslog classifier");
descriptions.put(Locale.ENGLISH, "syslog classifier name");
configOptions.add(new StringConfigType("classifier", names, descriptions, true));
}
{
Map<Locale, String> names = new HashMap<Locale, String>();
Map<Locale, String> descriptions = new HashMap<Locale, String>();
names.put(Locale.ENGLISH, "identifier");
descriptions.put(Locale.ENGLISH, "logger identifier");
configOptions.add(new StringConfigType("identifier", names, descriptions, true));
}
}
@Override
public void onReceive(Syslog syslog) {
InetAddress remoteAddr = syslog.getRemoteAddress().getAddress();
String classifierName = classifierMappings.get(remoteAddr);
if (classifierName == null)
return;
SyslogClassifier classifier = classifierRegistry.getClassifier(classifierName);
if (classifier == null) {
slog.warn("kraken syslogmon: classifier not found, ip [{}], classifier [{}]", remoteAddr, classifierName);
return;
}
String identifier = classifier.classify(syslog);
if (identifier == null) {
if (slog.isDebugEnabled())
slog.debug("kraken syslogmon: identifier not found, ip [{}], syslog [{}]", remoteAddr, syslog);
return;
}
VirtualLoggerKey key = new VirtualLoggerKey(remoteAddr, identifier);
SyslogRelayLogger logger = loggerMappings.get(key);
if (logger == null)
return;
logger.push(syslog);
}
private static class VirtualLoggerKey {
public InetAddress ip;
public String identifier;
public VirtualLoggerKey(InetAddress ip, String identifier) {
this.ip = ip;
this.identifier = identifier;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
result = prime * result + ((ip == null) ? 0 : ip.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VirtualLoggerKey other = (VirtualLoggerKey) obj;
if (identifier == null) {
if (other.identifier != null)
return false;
} else if (!identifier.equals(other.identifier))
return false;
if (ip == null) {
if (other.ip != null)
return false;
} else if (!ip.equals(other.ip))
return false;
return true;
}
}
}