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