001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.irc; 018 019 import java.util.List; 020 021 import org.apache.camel.Exchange; 022 import org.apache.camel.ExchangePattern; 023 import org.apache.camel.Processor; 024 import org.apache.camel.impl.DefaultEndpoint; 025 import org.apache.camel.impl.DefaultExchange; 026 import org.apache.camel.util.ObjectHelper; 027 import org.schwering.irc.lib.IRCConnection; 028 import org.schwering.irc.lib.IRCEventAdapter; 029 import org.schwering.irc.lib.IRCModeParser; 030 import org.schwering.irc.lib.IRCUser; 031 import org.slf4j.Logger; 032 import org.slf4j.LoggerFactory; 033 034 /** 035 * Defines the <a href="http://camel.apache.org/irc.html">IRC Endpoint</a> 036 * 037 * @version 038 */ 039 public class IrcEndpoint extends DefaultEndpoint { 040 private static final transient Logger LOG = LoggerFactory.getLogger(IrcEndpoint.class); 041 042 private IrcBinding binding; 043 private IrcConfiguration configuration; 044 private IrcComponent component; 045 046 public IrcEndpoint(String endpointUri, IrcComponent component, IrcConfiguration configuration) { 047 super(endpointUri, component); 048 this.component = component; 049 this.configuration = configuration; 050 } 051 052 public boolean isSingleton() { 053 return true; 054 } 055 056 public Exchange createExchange(ExchangePattern pattern) { 057 DefaultExchange exchange = new DefaultExchange(this, pattern); 058 exchange.setProperty(Exchange.BINDING, getBinding()); 059 return exchange; 060 } 061 062 public Exchange createOnPrivmsgExchange(String target, IRCUser user, String msg) { 063 DefaultExchange exchange = getExchange(); 064 exchange.setIn(new IrcMessage("PRIVMSG", target, user, msg)); 065 return exchange; 066 } 067 068 public Exchange createOnNickExchange(IRCUser user, String newNick) { 069 DefaultExchange exchange = getExchange(); 070 exchange.setIn(new IrcMessage("NICK", user, newNick)); 071 return exchange; 072 } 073 074 public Exchange createOnQuitExchange(IRCUser user, String msg) { 075 DefaultExchange exchange = getExchange(); 076 exchange.setIn(new IrcMessage("QUIT", user, msg)); 077 return exchange; 078 } 079 080 public Exchange createOnJoinExchange(String channel, IRCUser user) { 081 DefaultExchange exchange = getExchange(); 082 exchange.setIn(new IrcMessage("JOIN", channel, user)); 083 return exchange; 084 } 085 086 public Exchange createOnKickExchange(String channel, IRCUser user, String whoWasKickedNick, String msg) { 087 DefaultExchange exchange = getExchange(); 088 exchange.setIn(new IrcMessage("KICK", channel, user, whoWasKickedNick, msg)); 089 return exchange; 090 } 091 092 public Exchange createOnModeExchange(String channel, IRCUser user, IRCModeParser modeParser) { 093 DefaultExchange exchange = getExchange(); 094 exchange.setIn(new IrcMessage("MODE", channel, user, modeParser.getLine())); 095 return exchange; 096 } 097 098 public Exchange createOnPartExchange(String channel, IRCUser user, String msg) { 099 DefaultExchange exchange = getExchange(); 100 exchange.setIn(new IrcMessage("PART", channel, user, msg)); 101 return exchange; 102 } 103 104 public Exchange createOnReplyExchange(int num, String value, String msg) { 105 DefaultExchange exchange = getExchange(); 106 exchange.setIn(new IrcMessage("REPLY", num, value, msg)); 107 return exchange; 108 } 109 110 public Exchange createOnTopicExchange(String channel, IRCUser user, String topic) { 111 DefaultExchange exchange = getExchange(); 112 exchange.setIn(new IrcMessage("TOPIC", channel, user, topic)); 113 return exchange; 114 } 115 116 public IrcProducer createProducer() throws Exception { 117 return new IrcProducer(this, component.getIRCConnection(configuration)); 118 } 119 120 public IrcConsumer createConsumer(Processor processor) throws Exception { 121 return new IrcConsumer(this, processor, component.getIRCConnection(configuration)); 122 } 123 124 public IrcComponent getComponent() { 125 return component; 126 } 127 128 public void setComponent(IrcComponent component) { 129 this.component = component; 130 } 131 132 public IrcBinding getBinding() { 133 if (binding == null) { 134 binding = new IrcBinding(); 135 } 136 return binding; 137 } 138 139 public void setBinding(IrcBinding binding) { 140 this.binding = binding; 141 } 142 143 public IrcConfiguration getConfiguration() { 144 return configuration; 145 } 146 147 public void setConfiguration(IrcConfiguration configuration) { 148 this.configuration = configuration; 149 } 150 151 152 public void handleIrcError(int num, String msg) { 153 if (IRCEventAdapter.ERR_NICKNAMEINUSE == num) { 154 handleNickInUse(); 155 } 156 } 157 158 private void handleNickInUse() { 159 IRCConnection connection = component.getIRCConnection(configuration); 160 String nick = connection.getNick() + "-"; 161 162 // hackish but working approach to prevent an endless loop. Abort after 4 nick attempts. 163 if (nick.endsWith("----")) { 164 LOG.error("Unable to set nick: " + nick + " disconnecting"); 165 } else { 166 LOG.warn("Unable to set nick: " + nick + " Retrying with " + nick + "-"); 167 connection.doNick(nick); 168 // if the nick failure was doing startup channels weren't joined. So join 169 // the channels now. It's a no-op if the channels are already joined. 170 joinChannels(); 171 } 172 } 173 174 private DefaultExchange getExchange() { 175 DefaultExchange exchange = new DefaultExchange(this, getExchangePattern()); 176 exchange.setProperty(Exchange.BINDING, getBinding()); 177 return exchange; 178 } 179 180 181 public void joinChannels() { 182 for (String channel : configuration.getChannels()) { 183 joinChannel(channel); 184 } 185 } 186 187 public void joinChannel(String channel) { 188 189 List<String> channels = configuration.getChannels(); 190 191 IRCConnection connection = component.getIRCConnection(configuration); 192 193 // check for key for channel 194 String key = configuration.getKey(channel); 195 196 if (ObjectHelper.isNotEmpty(key)) { 197 if (LOG.isDebugEnabled()) { 198 LOG.debug("Joining: " + channel + " using " + connection.getClass().getName() + " with key " + key); 199 } 200 connection.doJoin(channel, key); 201 } else { 202 if (LOG.isDebugEnabled()) { 203 LOG.debug("Joining: " + channel + " using " + connection.getClass().getName()); 204 } 205 connection.doJoin(channel); 206 } 207 } 208 } 209