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.impl.DefaultProducer;
023    import org.apache.commons.logging.Log;
024    import org.apache.commons.logging.LogFactory;
025    import org.jsmpp.InvalidResponseException;
026    import org.jsmpp.PDUException;
027    import org.jsmpp.bean.Alphabet;
028    import org.jsmpp.bean.BindType;
029    import org.jsmpp.bean.ESMClass;
030    import org.jsmpp.bean.GeneralDataCoding;
031    import org.jsmpp.bean.MessageClass;
032    import org.jsmpp.bean.NumberingPlanIndicator;
033    import org.jsmpp.bean.RegisteredDelivery;
034    import org.jsmpp.bean.SubmitSm;
035    import org.jsmpp.bean.TypeOfNumber;
036    import org.jsmpp.extra.NegativeResponseException;
037    import org.jsmpp.extra.ResponseTimeoutException;
038    import org.jsmpp.session.BindParameter;
039    import org.jsmpp.session.SMPPSession;
040    
041    /**
042     * An implementation of @{link Producer} which use the SMPP protocol
043     * 
044     * @version $Revision: 888296 $
045     * @author muellerc
046     */
047    public class SmppProducer extends DefaultProducer {
048    
049        private static final transient Log LOG = LogFactory.getLog(SmppProducer.class);
050    
051        private SmppConfiguration configuration;
052        private SMPPSession session;
053    
054        public SmppProducer(SmppEndpoint endpoint, SmppConfiguration configuration) {
055            super(endpoint);
056            this.configuration = configuration;
057        }
058    
059        @Override
060        protected void doStart() throws Exception {
061            if (LOG.isDebugEnabled()) {
062                LOG.debug("Connecting to: " + getEndpoint().getConnectionString() + "...");
063            }
064    
065            super.doStart();
066    
067            session = createSMPPSession();
068            session.setEnquireLinkTimer(this.configuration.getEnquireLinkTimer());
069            session.setTransactionTimer(this.configuration.getTransactionTimer());
070            session.connectAndBind(
071                    this.configuration.getHost(),
072                    this.configuration.getPort(),
073                    new BindParameter(
074                            BindType.BIND_TX,
075                            this.configuration.getSystemId(),
076                            this.configuration.getPassword(), 
077                            this.configuration.getSystemType(),
078                            TypeOfNumber.valueOf(configuration.getTypeOfNumber()),
079                            NumberingPlanIndicator.valueOf(configuration.getNumberingPlanIndicator()),
080                            ""));
081    
082            LOG.info("Connected to: " + getEndpoint().getConnectionString());
083        }
084        
085        /**
086         * Factory method to easily instantiate a mock SMPPSession
087         * 
088         * @return the SMPPSession
089         */
090        SMPPSession createSMPPSession() {
091            return new SMPPSession();
092        }
093    
094        public void process(Exchange exchange) throws Exception {
095            if (LOG.isDebugEnabled()) {
096                LOG.debug("Sending a short message for exchange id '"
097                        + exchange.getExchangeId() + "'...");
098            }
099    
100            SubmitSm submitSm = getEndpoint().getBinding().createSubmitSm(exchange);
101            String messageId;
102            try {
103                messageId = doProcess(submitSm);
104            } catch (Exception e) {
105                // TODO: Add some DEBUG logging that we retry one more time
106                doStop();
107                doStart();
108                
109                messageId = doProcess(submitSm);
110            }
111    
112            LOG.info("Sent a short message for exchange id '"
113                    + exchange.getExchangeId() + "' and received message id '"
114                    + messageId + "'");
115    
116            if (exchange.getPattern().isOutCapable()) {
117                exchange.getOut().setHeader(SmppBinding.ID, messageId);
118            } else {
119                exchange.getIn().setHeader(SmppBinding.ID, messageId);
120            }
121        }
122    
123        private String doProcess(SubmitSm submitSm) throws PDUException,
124                ResponseTimeoutException, InvalidResponseException,
125                NegativeResponseException, IOException {
126    
127            String messageId = session.submitShortMessage(
128                    submitSm.getServiceType(), 
129                    TypeOfNumber.valueOf(submitSm.getSourceAddrTon()),
130                    NumberingPlanIndicator.valueOf(submitSm.getSourceAddrNpi()),
131                    submitSm.getSourceAddr(),
132                    TypeOfNumber.valueOf(submitSm.getDestAddrTon()),
133                    NumberingPlanIndicator.valueOf(submitSm.getDestAddrNpi()),
134                    submitSm.getDestAddress(),
135                    new ESMClass(),
136                    submitSm.getProtocolId(),
137                    submitSm.getPriorityFlag(),
138                    submitSm.getScheduleDeliveryTime(),
139                    submitSm.getValidityPeriod(),
140                    new RegisteredDelivery(submitSm.getRegisteredDelivery()),
141                    submitSm.getReplaceIfPresent(),
142                    new GeneralDataCoding(
143                            false,
144                            false,
145                            MessageClass.CLASS1,
146                            Alphabet.ALPHA_DEFAULT),
147                    (byte) 0,
148                    submitSm.getShortMessage());
149    
150            return messageId;
151        }
152    
153        @Override
154        protected void doStop() throws Exception {
155            if (LOG.isDebugEnabled()) {
156                LOG.debug("Disconnecting from: " + getEndpoint().getConnectionString() + "...");
157            }
158    
159            super.doStop();
160    
161            if (session != null) {
162                session.close();
163                session = null;
164            }
165    
166            LOG.info("Disconnected from: " + getEndpoint().getConnectionString());
167        }
168    
169        @Override
170        public SmppEndpoint getEndpoint() {
171            return (SmppEndpoint) super.getEndpoint();
172        }
173    
174        /**
175         * Returns the smppConfiguration for this producer
176         * 
177         * @return the configuration
178         */
179        public SmppConfiguration getConfiguration() {
180            return configuration;
181        }
182    
183        @Override
184        public String toString() {
185            return "SmppProducer[" + getEndpoint().getConnectionString() + "]";
186        }
187    
188    }