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.xmpp;
018
019 import java.util.Iterator;
020
021 import org.apache.camel.Consumer;
022 import org.apache.camel.Exchange;
023 import org.apache.camel.ExchangePattern;
024 import org.apache.camel.Processor;
025 import org.apache.camel.Producer;
026 import org.apache.camel.impl.DefaultEndpoint;
027 import org.apache.camel.impl.DefaultHeaderFilterStrategy;
028 import org.apache.camel.spi.HeaderFilterStrategy;
029 import org.apache.camel.spi.HeaderFilterStrategyAware;
030 import org.apache.camel.util.ObjectHelper;
031 import org.apache.commons.logging.Log;
032 import org.apache.commons.logging.LogFactory;
033 import org.jivesoftware.smack.AccountManager;
034 import org.jivesoftware.smack.ConnectionConfiguration;
035 import org.jivesoftware.smack.XMPPConnection;
036 import org.jivesoftware.smack.XMPPException;
037 import org.jivesoftware.smack.packet.Message;
038 import org.jivesoftware.smackx.muc.MultiUserChat;
039
040 /**
041 * A XMPP Endpoint
042 *
043 * @version $Revision:520964 $
044 */
045 public class XmppEndpoint extends DefaultEndpoint implements HeaderFilterStrategyAware {
046 private static final transient Log LOG = LogFactory.getLog(XmppEndpoint.class);
047 private HeaderFilterStrategy headerFilterStrategy = new DefaultHeaderFilterStrategy();
048 private XmppBinding binding;
049 private String host;
050 private int port;
051 private String user;
052 private String password;
053 private String resource = "Camel";
054 private boolean login = true;
055 private boolean createAccount;
056 private String room;
057 private String participant;
058 private String nickname;
059 private String serviceName;
060
061 public XmppEndpoint() {
062 }
063
064 public XmppEndpoint(String uri, XmppComponent component) {
065 super(uri, component);
066 }
067
068 public XmppEndpoint(String endpointUri) {
069 super(endpointUri);
070 }
071
072 public Producer createProducer() throws Exception {
073 if (room != null) {
074 return createGroupChatProducer();
075 } else {
076 if (getParticipant() == null) {
077 throw new IllegalArgumentException("No room or participant configured on this endpoint: " + this);
078 }
079 return createPrivateChatProducer(getParticipant());
080 }
081 }
082
083 public Producer createGroupChatProducer() throws Exception {
084 return new XmppGroupChatProducer(this);
085 }
086
087 public Producer createPrivateChatProducer(String participant) throws Exception {
088 return new XmppPrivateChatProducer(this, participant);
089 }
090
091 public Consumer createConsumer(Processor processor) throws Exception {
092 return new XmppConsumer(this, processor);
093 }
094
095 @Override
096 public Exchange createExchange(ExchangePattern pattern) {
097 return new XmppExchange(this, pattern, getBinding());
098 }
099
100 public XmppExchange createExchange(Message message) {
101 return new XmppExchange(this, getExchangePattern(), getBinding(), message);
102 }
103
104 @Override
105 protected String createEndpointUri() {
106 return "xmpp://" + host + ":" + port + "/" + getParticipant() + "?serviceName=" + serviceName;
107 }
108
109 public boolean isSingleton() {
110 return true;
111 }
112
113 public XMPPConnection createConnection() throws XMPPException {
114 XMPPConnection connection;
115
116 if (port > 0) {
117 if (getServiceName() == null) {
118 connection = new XMPPConnection(new ConnectionConfiguration(host, port));
119 } else {
120 connection = new XMPPConnection(new ConnectionConfiguration(host, port, getServiceName()));
121 }
122 } else {
123 connection = new XMPPConnection(host);
124 }
125
126 connection.connect();
127
128 if (login && !connection.isAuthenticated()) {
129 if (user != null) {
130 if (LOG.isDebugEnabled()) {
131 LOG.debug("Logging in to XMPP as user: " + user + " on connection: " + getConnectionMessage(connection));
132 }
133 if (password == null) {
134 LOG.warn("No password configured for user: " + user + " on connection: " + getConnectionMessage(connection));
135 }
136
137 if (createAccount) {
138 AccountManager accountManager = new AccountManager(connection);
139 accountManager.createAccount(user, password);
140 }
141 if (resource != null) {
142 connection.login(user, password, resource);
143 } else {
144 connection.login(user, password);
145 }
146 } else {
147 if (LOG.isDebugEnabled()) {
148 LOG.debug("Logging in anonymously to XMPP on connection: " + getConnectionMessage(connection));
149 }
150 connection.loginAnonymously();
151 }
152
153 // presence is not needed to be sent after login
154 }
155
156 return connection;
157 }
158
159 /*
160 * If there is no "@" symbol in the room, find the chat service JID and
161 * return fully qualified JID for the room as room@conference.server.domain
162 */
163 public String resolveRoom(XMPPConnection connection) throws XMPPException {
164 ObjectHelper.notEmpty(room, "room");
165
166 if (room.indexOf('@', 0) != -1) {
167 return room;
168 }
169
170 Iterator<String> iterator = MultiUserChat.getServiceNames(connection).iterator();
171 if (!iterator.hasNext()) {
172 throw new XMPPException("Cannot find Multi User Chat service on connection: " + getConnectionMessage(connection));
173 }
174
175 String chatServer = iterator.next();
176 if (LOG.isDebugEnabled()) {
177 LOG.debug("Detected chat server: " + chatServer);
178 }
179
180 return room + "@" + chatServer;
181 }
182
183 public static String getConnectionMessage(XMPPConnection connetion) {
184 return connetion.getHost() + ":" + connetion.getPort() + "/" + connetion.getServiceName();
185 }
186
187 // Properties
188 // -------------------------------------------------------------------------
189 public XmppBinding getBinding() {
190 if (binding == null) {
191 binding = new XmppBinding(headerFilterStrategy);
192 }
193 return binding;
194 }
195
196 /**
197 * Sets the binding used to convert from a Camel message to and from an XMPP
198 * message
199 */
200 public void setBinding(XmppBinding binding) {
201 this.binding = binding;
202 }
203
204 public String getHost() {
205 return host;
206 }
207
208 public void setHost(String host) {
209 this.host = host;
210 }
211
212 public int getPort() {
213 return port;
214 }
215
216 public void setPort(int port) {
217 this.port = port;
218 }
219
220 public String getUser() {
221 return user;
222 }
223
224 public void setUser(String user) {
225 this.user = user;
226 }
227
228 public String getPassword() {
229 return password;
230 }
231
232 public void setPassword(String password) {
233 this.password = password;
234 }
235
236 public String getResource() {
237 return resource;
238 }
239
240 public void setResource(String resource) {
241 this.resource = resource;
242 }
243
244 public boolean isLogin() {
245 return login;
246 }
247
248 public void setLogin(boolean login) {
249 this.login = login;
250 }
251
252 public boolean isCreateAccount() {
253 return createAccount;
254 }
255
256 public void setCreateAccount(boolean createAccount) {
257 this.createAccount = createAccount;
258 }
259
260 public String getRoom() {
261 return room;
262 }
263
264 public void setRoom(String room) {
265 this.room = room;
266 }
267
268 public String getParticipant() {
269 // participant is optional so use user if not provided
270 return participant != null ? participant : user;
271 }
272
273 public void setParticipant(String participant) {
274 this.participant = participant;
275 }
276
277 public String getNickname() {
278 return nickname != null ? nickname : getUser();
279 }
280
281 public void setNickname(String nickname) {
282 this.nickname = nickname;
283 }
284
285 public void setServiceName(String serviceName) {
286 this.serviceName = serviceName;
287 }
288
289 public String getServiceName() {
290 return serviceName;
291 }
292
293 public HeaderFilterStrategy getHeaderFilterStrategy() {
294 return headerFilterStrategy;
295 }
296
297 public void setHeaderFilterStrategy(HeaderFilterStrategy headerFilterStrategy) {
298 this.headerFilterStrategy = headerFilterStrategy;
299 }
300
301 // Implementation methods
302 // -------------------------------------------------------------------------
303
304 }