importjava.util.Arrays;
importjava.util.Collections;
importjava.util.Map;
importjava.util.Set;
importjava.util.concurrent.CopyOnWriteArraySet;
importjava.util.logging.Level;
importjava.util.logging.Logger;
importjavax.script.Bindings;
importtigase.server.AbstractMessageReceiver;
importtigase.server.Packet;
importtigase.stats.StatisticsList;
importtigase.util.JIDUtils;
importtigase.xmpp.StanzaType;
publicclassTestComponentextendsAbstractMessageReceiver {
privatestaticfinalLogger log =
Logger.getLogger(TestComponent.class.getName());
privatestaticfinalString BAD_WORDS_KEY ="bad-words";
privatestaticfinalString WHITELIST_KEY ="white-list";
privatestaticfinalString PREPEND_TEXT_KEY ="log-prepend";
privatestaticfinalString SECURE_LOGGING_KEY ="secure-logging";
privatestaticfinalString ABUSE_ADDRESS_KEY ="abuse-address";
privatestaticfinalString NOTIFICATION_FREQ_KEY ="notification-freq";
privatestaticfinalString BAD_WORDS_VAR ="badWords";
privatestaticfinalString WHITE_LIST_VAR ="whiteList";
privatestaticfinalString[] INITIAL_BAD_WORDS = {"word1","word2","word3"};
privatestaticfinalString[] INITIAL_WHITE_LIST = {"admin@localhost"};
/**
* 当Set在一个线程当中进行遍历的时候内容有可能被另一个线程修改,我们认为这种修改是非常小并且很少会发生的,因为绝大多数的操作仅仅是遍历
*/
privateSet<String> badWords =newCopyOnWriteArraySet<String>();
/**
* 当Set在一个线程当中进行遍历的时候内容有可能被另一个线程修改,我们认为这种修改是非常小并且很少会发生的,因为绝大多数的操作仅仅是调用contains(...)方法
*/
privateSet<String> whiteList =newConcurrentSkipListSet<String>();
privateString prependText ="Spam detected: ";
privateString abuseAddress ="abuse@locahost";
privateintnotificationFrequency =10;
privateintdelayCounter =0;
privatebooleansecureLogging =false;
privatelongspamCounter =0;
privatelongtotalSpamCounter =0;
privatelongmessagesCounter =0;
@Override
publicvoidprocessPacket(Packet packet) {
// 这是一个message packet吗?
if("message"== packet.getElemName()) {
updateServiceDiscoveryItem(getName(),"messages",
"Messages processed: ["+ (++messagesCounter) +"]",true);
String from = JIDUtils.getNodeID(packet.getElemFrom());
// 消息的发送者在白名单内吗?
if(!whiteList.contains(from)) {
// 如果ta不在白名单里面,那么检查消息的内容
String body = packet.getElemCData("/message/body");
if(body !=null&& !body.isEmpty()) {
body = body.toLowerCase();
for(String word : badWords) {
if(body.contains(word)) {
log.finest(prependText + packet.toString(secureLogging));
++spamCounter;
updateServiceDiscoveryItem(getName(),"spam","Spam caught: ["+
(++totalSpamCounter) +"]",true);
return;
}
}
}
}
}
// 不是垃圾信息,返回以便做下一步处理
Packet result = packet.swapElemFromTo();
addOutPacket(result);
}
@Override
publicintprocessingThreads() {
returnRuntime.getRuntime().availableProcessors();
}
@Override
publicinthashCodeForPacket(Packet packet) {
if(packet.getElemTo() !=null) {
returnpacket.getElemTo().hashCode();
}
// 程序不应该运行到这里,所有的packet都必须具有一个目的地地址,但是也许垃圾过滤器也许会过滤一些奇怪的地址
if(packet.getElemFrom() !=null) {
returnpacket.getElemFrom().hashCode();
}
// 如果程序真的运行到这一部,就应该好好检查一下到达组件的packet是否正常,然后找到一个更好的计算hashCode方法。
return1;
}
@Override
publicMap<String, Object> getDefaults(Map<String, Object> params) {
Map<String, Object> defs =super.getDefaults(params);
Collections.addAll(badWords, INITIAL_BAD_WORDS);
Collections.addAll(whiteList, INITIAL_WHITE_LIST);
defs.put(BAD_WORDS_KEY, INITIAL_BAD_WORDS);
defs.put(WHITELIST_KEY, INITIAL_WHITE_LIST);
defs.put(PREPEND_TEXT_KEY, prependText);
defs.put(SECURE_LOGGING_KEY, secureLogging);
defs.put(ABUSE_ADDRESS_KEY, abuseAddress);
defs.put(NOTIFICATION_FREQ_KEY, notificationFrequency);
returndefs;
}
@Override
publicvoidsetProperties(Map<String, Object> props) {
super.setProperties(props);
Collections.addAll(badWords, (String[])props.get(BAD_WORDS_KEY));
Collections.addAll(whiteList, (String[])props.get(WHITELIST_KEY));
prependText = (String)props.get(PREPEND_TEXT_KEY);
secureLogging = (Boolean)props.get(SECURE_LOGGING_KEY);
abuseAddress = (String)props.get(ABUSE_ADDRESS_KEY);
notificationFrequency = (Integer)props.get(NOTIFICATION_FREQ_KEY);
updateServiceDiscoveryItem(getName(),null, getDiscoDescription(),
"automation","spam-filtering",true,
"tigase:x:spam-filter","tigase:x:spam-reporting");
}
@Override
publicsynchronizedvoideveryMinute() {
super.everyMinute();
if((++delayCounter) >= notificationFrequency) {
addOutPacket(Packet.getMessage(abuseAddress, getComponentId(),
StanzaType.chat,"Detected spam messages: "+ spamCounter,
"Spam counter",null, newPacketId("spam-")));
delayCounter =0;
spamCounter =0;
}
}
@Override
publicString getDiscoDescription() {
return"Spam filtering";
}
@Override
publicString getDiscoCategoryType() {
return"spam";
}
@Override
publicvoidgetStatistics(StatisticsList list) {
super.getStatistics(list);
list.add(getName(),"Spam messages found", totalSpamCounter,
Level.INFO);
list.add(getName(),"All messages processed", messagesCounter,
Level.FINE);
if(list.checkLevel(Level.FINEST)) {
// 可以把那些非常消耗系统资源的统计数据产生代码写在下面
}
}
@Override
publicvoidinitBindings(Bindings binds) {
super.initBindings(binds);
binds.put(BAD_WORDS_VAR, badWords);
binds.put(WHITE_LIST_VAR, whiteList);
}
}