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
028 import org.apache.commons.logging.Log;
029 import org.apache.commons.logging.LogFactory;
030
031 import org.schwering.irc.lib.IRCConnection;
032 import org.schwering.irc.lib.IRCEventAdapter;
033 import org.schwering.irc.lib.IRCModeParser;
034 import org.schwering.irc.lib.IRCUser;
035
036 /**
037 * Defines the <a href="http://camel.apache.org/irc.html">IRC Endpoint</a>
038 *
039 * @version $Revision: 1043319 $
040 */
041 public class IrcEndpoint extends DefaultEndpoint {
042 private static final transient Log LOG = LogFactory.getLog(IrcEndpoint.class);
043
044 private IrcBinding binding;
045 private IrcConfiguration configuration;
046 private IrcComponent component;
047
048 public IrcEndpoint(String endpointUri, IrcComponent component, IrcConfiguration configuration) {
049 super(endpointUri, component);
050 this.component = component;
051 this.configuration = configuration;
052 }
053
054 public boolean isSingleton() {
055 return true;
056 }
057
058 public Exchange createExchange(ExchangePattern pattern) {
059 DefaultExchange exchange = new DefaultExchange(this, pattern);
060 exchange.setProperty(Exchange.BINDING, getBinding());
061 return exchange;
062 }
063
064 public Exchange createOnPrivmsgExchange(String target, IRCUser user, String msg) {
065 DefaultExchange exchange = getExchange();
066 exchange.setIn(new IrcMessage("PRIVMSG", target, user, msg));
067 return exchange;
068 }
069
070 public Exchange createOnNickExchange(IRCUser user, String newNick) {
071 DefaultExchange exchange = getExchange();
072 exchange.setIn(new IrcMessage("NICK", user, newNick));
073 return exchange;
074 }
075
076 public Exchange createOnQuitExchange(IRCUser user, String msg) {
077 DefaultExchange exchange = getExchange();
078 exchange.setIn(new IrcMessage("QUIT", user, msg));
079 return exchange;
080 }
081
082 public Exchange createOnJoinExchange(String channel, IRCUser user) {
083 DefaultExchange exchange = getExchange();
084 exchange.setIn(new IrcMessage("JOIN", channel, user));
085 return exchange;
086 }
087
088 public Exchange createOnKickExchange(String channel, IRCUser user, String whoWasKickedNick, String msg) {
089 DefaultExchange exchange = getExchange();
090 exchange.setIn(new IrcMessage("KICK", channel, user, whoWasKickedNick, msg));
091 return exchange;
092 }
093
094 public Exchange createOnModeExchange(String channel, IRCUser user, IRCModeParser modeParser) {
095 DefaultExchange exchange = getExchange();
096 exchange.setIn(new IrcMessage("MODE", channel, user, modeParser.getLine()));
097 return exchange;
098 }
099
100 public Exchange createOnPartExchange(String channel, IRCUser user, String msg) {
101 DefaultExchange exchange = getExchange();
102 exchange.setIn(new IrcMessage("PART", channel, user, msg));
103 return exchange;
104 }
105
106 public Exchange createOnReplyExchange(int num, String value, String msg) {
107 DefaultExchange exchange = getExchange();
108 exchange.setIn(new IrcMessage("REPLY", num, value, msg));
109 return exchange;
110 }
111
112 public Exchange createOnTopicExchange(String channel, IRCUser user, String topic) {
113 DefaultExchange exchange = getExchange();
114 exchange.setIn(new IrcMessage("TOPIC", channel, user, topic));
115 return exchange;
116 }
117
118 public IrcProducer createProducer() throws Exception {
119 return new IrcProducer(this, component.getIRCConnection(configuration));
120 }
121
122 public IrcConsumer createConsumer(Processor processor) throws Exception {
123 return new IrcConsumer(this, processor, component.getIRCConnection(configuration));
124 }
125
126 public IrcComponent getComponent() {
127 return component;
128 }
129
130 public void setComponent(IrcComponent component) {
131 this.component = component;
132 }
133
134 public IrcBinding getBinding() {
135 if (binding == null) {
136 binding = new IrcBinding();
137 }
138 return binding;
139 }
140
141 public void setBinding(IrcBinding binding) {
142 this.binding = binding;
143 }
144
145 public IrcConfiguration getConfiguration() {
146 return configuration;
147 }
148
149 public void setConfiguration(IrcConfiguration configuration) {
150 this.configuration = configuration;
151 }
152
153
154 public void handleIrcError(int num, String msg) {
155 if (IRCEventAdapter.ERR_NICKNAMEINUSE == num) {
156 handleNickInUse();
157 }
158 }
159
160 private void handleNickInUse() {
161 IRCConnection connection = component.getIRCConnection(configuration);
162 String nick = connection.getNick() + "-";
163
164 // hackish but working approach to prevent an endless loop. Abort after 4 nick attempts.
165 if (nick.endsWith("----")) {
166 LOG.error("Unable to set nick: " + nick + " disconnecting");
167 } else {
168 LOG.warn("Unable to set nick: " + nick + " Retrying with " + nick + "-");
169 connection.doNick(nick);
170 // if the nick failure was doing startup channels weren't joined. So join
171 // the channels now. It's a no-op if the channels are already joined.
172 joinChannels();
173 }
174 }
175
176 private DefaultExchange getExchange() {
177 DefaultExchange exchange = new DefaultExchange(this, getExchangePattern());
178 exchange.setProperty(Exchange.BINDING, getBinding());
179 return exchange;
180 }
181
182
183 public void joinChannels() {
184 for (String channel : configuration.getChannels()) {
185 joinChannel(channel);
186 }
187 }
188
189 public void joinChannel(String channel) {
190
191 List<String> channels = configuration.getChannels();
192
193 IRCConnection connection = component.getIRCConnection(configuration);
194
195 // check for key for channel
196 String key = configuration.getKey(channel);
197
198 if (ObjectHelper.isNotEmpty(key)) {
199 if (LOG.isDebugEnabled()) {
200 LOG.debug("Joining: " + channel + " using " + connection.getClass().getName() + " with key " + key);
201 }
202 connection.doJoin(channel, key);
203 } else {
204 if (LOG.isDebugEnabled()) {
205 LOG.debug("Joining: " + channel + " using " + connection.getClass().getName());
206 }
207 connection.doJoin(channel);
208 }
209 }
210 }
211