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.smpp; 018 019 import java.io.IOException; 020 021 import org.apache.camel.Exchange; 022 import org.apache.camel.Processor; 023 import org.apache.camel.impl.DefaultConsumer; 024 import org.apache.commons.logging.Log; 025 import org.apache.commons.logging.LogFactory; 026 import org.jsmpp.DefaultPDUReader; 027 import org.jsmpp.DefaultPDUSender; 028 import org.jsmpp.SynchronizedPDUSender; 029 import org.jsmpp.bean.AlertNotification; 030 import org.jsmpp.bean.BindType; 031 import org.jsmpp.bean.DataSm; 032 import org.jsmpp.bean.DeliverSm; 033 import org.jsmpp.bean.NumberingPlanIndicator; 034 import org.jsmpp.bean.TypeOfNumber; 035 import org.jsmpp.extra.ProcessRequestException; 036 import org.jsmpp.extra.SessionState; 037 import org.jsmpp.session.BindParameter; 038 import org.jsmpp.session.DataSmResult; 039 import org.jsmpp.session.MessageReceiverListener; 040 import org.jsmpp.session.SMPPSession; 041 import org.jsmpp.session.Session; 042 import org.jsmpp.session.SessionStateListener; 043 import org.jsmpp.util.DefaultComposer; 044 import org.jsmpp.util.MessageIDGenerator; 045 import org.jsmpp.util.MessageId; 046 import org.jsmpp.util.RandomMessageIDGenerator; 047 048 /** 049 * An implementation of @{link Consumer} which use the SMPP protocol 050 * 051 * @version $Revision: 954316 $ 052 * @author muellerc 053 */ 054 public class SmppConsumer extends DefaultConsumer { 055 056 private static final transient Log LOG = LogFactory.getLog(SmppConsumer.class); 057 058 private SmppConfiguration configuration; 059 private SMPPSession session; 060 private MessageReceiverListener messageReceiverListener; 061 private SessionStateListener sessionStateListener; 062 063 /** 064 * The constructor which gets a smpp endpoint, a smpp configuration and a 065 * processor 066 */ 067 public SmppConsumer(SmppEndpoint endpoint, SmppConfiguration config, Processor processor) { 068 super(endpoint, processor); 069 070 this.configuration = config; 071 this.sessionStateListener = new SessionStateListener() { 072 public void onStateChange(SessionState newState, SessionState oldState, Object source) { 073 if (newState.equals(SessionState.CLOSED)) { 074 LOG.warn("Loost connection to: " + getEndpoint().getConnectionString() 075 + " - trying to reconnect..."); 076 closeSession(session); 077 reconnect(configuration.getInitialReconnectDelay()); 078 } 079 } 080 }; 081 this.messageReceiverListener = new MessageReceiverListener() { 082 private final MessageIDGenerator messageIDGenerator = new RandomMessageIDGenerator(); 083 084 public void onAcceptAlertNotification(AlertNotification alertNotification) { 085 if (LOG.isDebugEnabled()) { 086 LOG.debug("Received an alertNotification " + alertNotification); 087 } 088 089 try { 090 Exchange exchange = getEndpoint().createOnAcceptAlertNotificationExchange( 091 alertNotification); 092 093 LOG.trace("Processing the new smpp exchange..."); 094 getProcessor().process(exchange); 095 LOG.trace("Processed the new smpp exchange"); 096 } catch (Exception e) { 097 getExceptionHandler().handleException(e); 098 } 099 } 100 101 public void onAcceptDeliverSm(DeliverSm deliverSm) { 102 if (LOG.isDebugEnabled()) { 103 LOG.debug("Received a deliverSm " + deliverSm); 104 } 105 106 try { 107 Exchange exchange = getEndpoint().createOnAcceptDeliverSmExchange(deliverSm); 108 109 LOG.trace("processing the new smpp exchange..."); 110 getProcessor().process(exchange); 111 LOG.trace("processed the new smpp exchange"); 112 } catch (Exception e) { 113 getExceptionHandler().handleException(e); 114 } 115 } 116 117 public DataSmResult onAcceptDataSm(DataSm dataSm, Session session) 118 throws ProcessRequestException { 119 if (LOG.isDebugEnabled()) { 120 LOG.debug("Received a dataSm " + dataSm); 121 } 122 123 MessageId newMessageId = messageIDGenerator.newMessageId(); 124 125 try { 126 Exchange exchange = getEndpoint().createOnAcceptDataSm(dataSm, 127 newMessageId.getValue()); 128 129 LOG.trace("processing the new smpp exchange..."); 130 getProcessor().process(exchange); 131 LOG.trace("processed the new smpp exchange"); 132 } catch (Exception e) { 133 getExceptionHandler().handleException(e); 134 throw new ProcessRequestException(e.getMessage(), 255, e); 135 } 136 137 return new DataSmResult(newMessageId, dataSm.getOptionalParametes()); 138 } 139 }; 140 } 141 142 @Override 143 protected void doStart() throws Exception { 144 LOG.debug("Connecting to: " + getEndpoint().getConnectionString() + "..."); 145 146 super.doStart(); 147 session = createSession(); 148 149 LOG.info("Connected to: " + getEndpoint().getConnectionString()); 150 } 151 152 private SMPPSession createSession() throws IOException { 153 SMPPSession session = createSMPPSession(); 154 session = createSMPPSession(); 155 session.setEnquireLinkTimer(configuration.getEnquireLinkTimer()); 156 session.setTransactionTimer(configuration.getTransactionTimer()); 157 session.addSessionStateListener(sessionStateListener); 158 session.setMessageReceiverListener(messageReceiverListener); 159 session.connectAndBind(this.configuration.getHost(), this.configuration.getPort(), 160 new BindParameter(BindType.BIND_RX, this.configuration.getSystemId(), 161 this.configuration.getPassword(), this.configuration.getSystemType(), 162 TypeOfNumber.UNKNOWN, NumberingPlanIndicator.UNKNOWN, "")); 163 164 return session; 165 } 166 167 /** 168 * Factory method to easily instantiate a mock SMPPSession 169 * 170 * @return the SMPPSession 171 */ 172 SMPPSession createSMPPSession() { 173 if (configuration.getUsingSSL()) { 174 return new SMPPSession(new SynchronizedPDUSender(new DefaultPDUSender( 175 new DefaultComposer())), new DefaultPDUReader(), SmppSSLConnectionFactory 176 .getInstance()); 177 } else { 178 return new SMPPSession(); 179 } 180 } 181 182 @Override 183 protected void doStop() throws Exception { 184 LOG.debug("Disconnecting from: " + getEndpoint().getConnectionString() + "..."); 185 186 super.doStop(); 187 closeSession(session); 188 189 LOG.info("Disconnected from: " + getEndpoint().getConnectionString()); 190 } 191 192 private void closeSession(SMPPSession session) { 193 if (session != null) { 194 session.removeSessionStateListener(this.sessionStateListener); 195 session.close(); 196 session = null; 197 } 198 } 199 200 private void reconnect(final long initialReconnectDelay) { 201 new Thread() { 202 @Override 203 public void run() { 204 LOG.info("Schedule reconnect after " + initialReconnectDelay + " millis"); 205 try { 206 Thread.sleep(initialReconnectDelay); 207 } catch (InterruptedException e) { 208 } 209 210 int attempt = 0; 211 while (!(isStopping() || isStopped()) && (session == null || session.getSessionState().equals(SessionState.CLOSED))) { 212 try { 213 LOG.info("Trying to reconnect to " + getEndpoint().getConnectionString() + " - attempt #" + (++attempt) + "..."); 214 session = createSession(); 215 } catch (IOException e) { 216 LOG.info("Failed to reconnect to " + getEndpoint().getConnectionString()); 217 closeSession(session); 218 try { 219 Thread.sleep(configuration.getReconnectDelay()); 220 } catch (InterruptedException ee) { 221 } 222 } 223 } 224 LOG.info("Reconnected to " + getEndpoint().getConnectionString()); 225 } 226 }.start(); 227 } 228 229 @Override 230 public String toString() { 231 return "SmppConsumer[" + getEndpoint().getConnectionString() + "]"; 232 } 233 234 @Override 235 public SmppEndpoint getEndpoint() { 236 return (SmppEndpoint) super.getEndpoint(); 237 } 238 239 /** 240 * Returns the smpp configuration 241 * 242 * @return the configuration 243 */ 244 public SmppConfiguration getConfiguration() { 245 return configuration; 246 } 247 }