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: {} using {} with key {}", new Object[]{channel, connection.getClass().getName(), key});
199 }
200 connection.doJoin(channel, key);
201 } else {
202 if (LOG.isDebugEnabled()) {
203 LOG.debug("Joining: {} using {}", channel, connection.getClass().getName());
204 }
205 connection.doJoin(channel);
206 }
207 }
208 }
209