1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.marre.sms.transport.pswincom;
36
37 import java.io.BufferedReader;
38 import java.io.ByteArrayOutputStream;
39 import java.io.FileOutputStream;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.InputStreamReader;
43 import java.io.OutputStream;
44 import java.io.StringWriter;
45 import java.net.Socket;
46 import java.util.Properties;
47
48 import javax.xml.parsers.SAXParser;
49 import javax.xml.parsers.SAXParserFactory;
50
51 import org.marre.sms.SmsAddress;
52 import org.marre.sms.SmsConstants;
53 import org.marre.sms.SmsDcs;
54 import org.marre.sms.SmsException;
55 import org.marre.sms.SmsMessage;
56 import org.marre.sms.SmsPdu;
57 import org.marre.sms.SmsPduUtil;
58 import org.marre.sms.SmsTextMessage;
59 import org.marre.sms.SmsUserData;
60 import org.marre.sms.transport.SmsTransport;
61 import org.marre.sms.transport.clickatell.ClickatellTransport;
62 import org.marre.util.IOUtil;
63 import org.marre.util.StringUtil;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66 import org.xml.sax.InputSource;
67
68 /***
69 * Simple transport for the pswin xml protocol.
70 *
71 * See http://www.pswin.com/ for more information.
72 *
73 * <pre>
74 * Available properties:
75 * smsj.pswincom.username
76 * smsj.pswincom.password
77 * smsj.pswincom.server - server address (default is "sms.pswin.com")
78 * smsj.pswincom.port - port (default is "1111")
79 * </pre>
80 *
81 * @author Markus
82 * @version $Id: PsWinXmlTransport.java,v 1.10 2005/11/26 16:24:23 c95men Exp $
83 */
84 public class PsWinXmlTransport implements SmsTransport
85 {
86 private static Logger log_ = LoggerFactory.getLogger(PsWinXmlTransport.class);
87
88 private String username_;
89 private String password_;
90
91 private String server_;
92 private int port_;
93
94 /***
95 * Initializes the pswin transport.
96 *
97 * @see org.marre.sms.transport.SmsTransport#init(java.util.Properties)
98 */
99 public void init(Properties props) throws SmsException
100 {
101 username_ = props.getProperty("smsj.pswincom.username");
102 password_ = props.getProperty("smsj.pswincom.password");
103 server_ = props.getProperty("smsj.pswincom.server", "sms.pswin.com");
104 port_ = Integer.parseInt(props.getProperty("smsj.pswincom.port", "1111"));
105
106 log_.debug("init() : username = " + username_);
107 log_.debug("init() : password = " + password_);
108 log_.debug("init() : server = " + server_);
109 log_.debug("init() : port = " + port_);
110
111 if ((username_ == null) || (password_ == null))
112 {
113 throw new SmsException("Incomplete login information for pswincom");
114 }
115 }
116
117 private void addMsg(StringWriter xmlStringWriter, SmsPdu smsPdu, SmsAddress dest, SmsAddress sender)
118 throws SmsException
119 {
120 SmsUserData userData = smsPdu.getUserData();
121
122
123 xmlStringWriter.write("<MSG>\r\n");
124
125 xmlStringWriter.write("<RCPREQ>Y</RCPREQ>\r\n");
126
127 switch (smsPdu.getDcs().getAlphabet())
128 {
129 case SmsDcs.ALPHABET_UCS2:
130
131 xmlStringWriter.write("<OP>9</OP>\r\n");
132
133 xmlStringWriter.write("<TEXT>");
134 xmlStringWriter.write(StringUtil.bytesToHexString(userData.getData()));
135 xmlStringWriter.write("</TEXT>\r\n");
136 break;
137
138 case SmsDcs.ALPHABET_GSM:
139
140 xmlStringWriter.write("<TEXT>");
141 xmlStringWriter.write(SmsPduUtil.readSeptets(userData.getData(), userData.getLength()));
142 xmlStringWriter.write("</TEXT>\r\n");
143 break;
144
145 case SmsDcs.ALPHABET_8BIT:
146
147 xmlStringWriter.write("<OP>8</OP>\r\n");
148
149 xmlStringWriter.write("<TEXT>");
150 xmlStringWriter.write(StringUtil.bytesToHexString(smsPdu.getUserDataHeaders())
151 + StringUtil.bytesToHexString(userData.getData()));
152 xmlStringWriter.write("</TEXT>\r\n");
153 break;
154
155 default:
156 throw new SmsException("Unsupported alphabet");
157 }
158
159
160 xmlStringWriter.write("<RCV>");
161 xmlStringWriter.write(dest.getAddress());
162 xmlStringWriter.write("</RCV>\r\n");
163
164 if (sender != null)
165 {
166
167 xmlStringWriter.write("<SND>");
168 xmlStringWriter.write(sender.getAddress());
169 xmlStringWriter.write("</SND>\r\n");
170 }
171
172 if (smsPdu.getDcs().getMessageClass() == SmsDcs.MSG_CLASS_0)
173 {
174
175 xmlStringWriter.write("<CLASS>");
176 xmlStringWriter.write("0");
177 xmlStringWriter.write("</CLASS>\r\n");
178 }
179
180
181 xmlStringWriter.write("</MSG>\r\n");
182 }
183
184 private void addTextMsg(StringWriter xmlStringWriter, SmsTextMessage msg, SmsAddress dest, SmsAddress sender)
185 throws SmsException
186 {
187 SmsUserData userData = msg.getUserData();
188
189
190 xmlStringWriter.write("<MSG>\r\n");
191
192 switch (userData.getDcs().getAlphabet())
193 {
194 case SmsDcs.ALPHABET_UCS2:
195
196 xmlStringWriter.write("<OP>9</OP>\r\n");
197
198 xmlStringWriter.write("<TEXT>");
199 xmlStringWriter.write(StringUtil.bytesToHexString(userData.getData()));
200 xmlStringWriter.write("</TEXT>\r\n");
201 break;
202
203 case SmsDcs.ALPHABET_GSM:
204
205 xmlStringWriter.write("<TEXT>");
206 xmlStringWriter.write(msg.getText());
207 xmlStringWriter.write("</TEXT>\r\n");
208 break;
209
210 default:
211 throw new SmsException("Unsupported alphabet");
212 }
213
214
215 xmlStringWriter.write("<RCV>");
216 xmlStringWriter.write(dest.getAddress());
217 xmlStringWriter.write("</RCV>\r\n");
218
219 if (sender != null)
220 {
221
222 xmlStringWriter.write("<SND>");
223 xmlStringWriter.write(sender.getAddress());
224 xmlStringWriter.write("</SND>\r\n");
225 }
226
227 if (userData.getDcs().getMessageClass() == SmsDcs.MSG_CLASS_0)
228 {
229
230 xmlStringWriter.write("<CLASS>");
231 xmlStringWriter.write("0");
232 xmlStringWriter.write("</CLASS>\r\n");
233 }
234
235
236 xmlStringWriter.write("</MSG>\r\n");
237 }
238
239 /***
240 * Creates a pswin xml document and writes it to the given outputstream.
241 *
242 * @param os
243 * @param msg
244 * @param dest
245 * @param sender
246 * @throws IOException
247 * @throws SmsException
248 */
249 private void writeXmlTo(OutputStream os, SmsMessage msg,
250 SmsAddress dest, SmsAddress sender)
251 throws IOException, SmsException
252 {
253 StringWriter xmlWriter = new StringWriter(1024);
254
255
256
257
258
259
260 xmlWriter.write("<?xml version=\"1.0\"?>\r\n");
261 xmlWriter.write("<SESSION>\r\n");
262 xmlWriter.write("<CLIENT>" + username_ + "</CLIENT>\r\n");
263 xmlWriter.write("<PW>" + password_ + "</PW>\r\n");
264 xmlWriter.write("<MSGLST>\r\n");
265
266
267 if (msg instanceof SmsTextMessage)
268 {
269 addTextMsg(xmlWriter, (SmsTextMessage) msg, dest, sender);
270 }
271 else
272 {
273 SmsPdu[] msgPdu = msg.getPdus();
274 for (int i = 0; i < msgPdu.length; i++)
275 {
276 addMsg(xmlWriter, msgPdu[i], dest, sender);
277 }
278 }
279
280
281
282 xmlWriter.write("</MSGLST>\r\n");
283 xmlWriter.write("</SESSION>\r\n");
284
285
286 String xmlDoc = xmlWriter.toString();
287 os.write(xmlDoc.getBytes());
288 }
289
290 /***
291 * Sends the given xml request to pswin for processing.
292 *
293 * @param xmlReq
294 * @throws IOException
295 * @throws SmsException
296 */
297 private void sendReqToPsWinCom(byte[] xmlReq) throws IOException, SmsException
298 {
299 Socket xmlSocket = new Socket(server_, port_);
300
301
302 OutputStream os = xmlSocket.getOutputStream();
303 os.write(xmlReq);
304
305
306 InputStream is = xmlSocket.getInputStream();
307
308
309 PsWinXmlResponseParser responseParser = new PsWinXmlResponseParser(is);
310 responseParser.parse();
311
312
313 if (! responseParser.getLogon().equals("OK"))
314 {
315 throw new SmsException("Failed to send message: " + responseParser.getReason());
316 }
317 }
318
319 /***
320 * Send.
321 *
322 * @param msg
323 * @param dest
324 * @param sender
325 * @return Internal message id.
326 * @throws SmsException
327 * @throws IOException
328 *
329 * @see org.marre.sms.transport.SmsTransport#send()
330 */
331 public String send(SmsMessage msg, SmsAddress dest, SmsAddress sender) throws SmsException, IOException
332 {
333 byte[] xmlReq;
334
335 if (dest.getTypeOfNumber() == SmsConstants.TON_ALPHANUMERIC)
336 {
337 throw new SmsException("Cannot sent SMS to ALPHANUMERIC address");
338 }
339
340 try
341 {
342 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
343
344
345 writeXmlTo(baos, msg, dest, sender);
346 baos.close();
347
348 xmlReq = baos.toByteArray();
349 }
350 catch (IOException ex)
351 {
352 throw new SmsException("Failed to build xml request", ex);
353 }
354
355
356 sendReqToPsWinCom(xmlReq);
357
358
359 return null;
360 }
361
362 /***
363 * Connect.
364 *
365 * @see org.marre.sms.transport.SmsTransport#connect()
366 */
367 public void connect()
368 {
369
370 }
371
372 /***
373 * Disconnect.
374 *
375 * @see org.marre.sms.transport.SmsTransport#disconnect()
376 */
377 public void disconnect()
378 {
379
380 }
381
382 /***
383 * Ping.
384 *
385 * @see org.marre.sms.transport.SmsTransport#ping()
386 */
387 public void ping()
388 {
389
390 }
391 }