Java tutorial
/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bremersee.sms; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.nio.charset.Charset; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.bremersee.sms.model.GoyyaSmsSendResponseDto; import org.bremersee.sms.model.SmsSendRequestDto; import org.bremersee.sms.model.SmsSendResponseDto; import org.bremersee.utils.WebUtils; //@formatter:off /** * <p> * A SMS service implementation that uses the Goyya SMS Services ( * <a href="https://www.goyya.com/sms-services">https://www.goyya.com/sms-services</a> * ). * </p> * * @author Christian Bremer */ //@formatter:on public class GoyyaSmsService extends AbstractSmsService implements SmsService { /** * The default URL of the Goyya SMS service. */ private static final String DEFAULT_URL = "https://gate1.goyyamobile.com/sms/sendsms.asp"; /** * The default pattern to convert a time. */ public static final String DEFAULT_SEND_TIME_PATTERN = "HHmmddMMyyyy"; /** * The message type for normal text messages. */ public static final String MESSAGE_TYPE_TEXT_VALUE = "t"; /** * The message type for long text messages. */ public static final String MESSAGE_TYPE_LONG_TEXT_VALUE = "c"; /** * The message type for blinking messages. */ public static final String MESSAGE_TYPE_BLINK_VALUE = "b"; /** * The message type for flash messages. */ public static final String MESSAGE_TYPE_FLASH_VALUE = "f"; private static final String GATEWAY_USER_ID_KEY = "id"; private static final String GATEWAY_USER_PASSWORD_KEY = "pw"; private static final String SENDER_KEY = "sender"; private static final String RECEIVER_KEY = "receiver"; private static final String MESSAGE_KEY = "msg"; private static final String MESSAGE_TYPE_KEY = "msgtype"; private static final String TIME_KEY = "time"; private static final String GET_MSG_ID_KEY = "getID"; private static final String GET_MSG_ID_VALUE = "1"; private static final String GET_COUNT_MSG_KEY = "countMsg"; private static final String GET_COUNT_MSG_VALUE = "1"; private static final String GET_LIMIT_KEY = "getLimit"; private static final String GET_LIMIT_VALUE = "1"; private static final String GET_STATUS_KEY = "getStatus"; private static final String GET_STATUS_VALUE = "1"; private String url = DEFAULT_URL; private String username; private String password; private String proxyHost; private Integer proxyPort; private String proxyUsername; private String proxyPassword; private String sendTimePattern = DEFAULT_SEND_TIME_PATTERN; /** * t|f|b|c t=Text-SMS, f=Flash-SMS, b=Blink-SMS*, c=long SMS */ private String defaultMessageType = MESSAGE_TYPE_TEXT_VALUE; /** * Default constructor. */ public GoyyaSmsService() { super(); } /** * Constructs a SMS service the the specified user name and password. * * @param username * the user name * @param password * the password */ public GoyyaSmsService(String username, String password) { this(username, password, null); } /** * Constructs a SMS service the the specified user name, password and URL. * * @param username * the user name * @param password * the password * @param url * the URL to use */ public GoyyaSmsService(String username, String password, String url) { this.username = username; this.password = password; if (StringUtils.isNotBlank(url)) { this.url = url; } } /** * Sets the user name. * * @param username * the user name */ public void setUsername(String username) { this.username = username; } /** * Sets the password. * * @param password * the password */ public void setPassword(String password) { this.password = password; } /** * Returns the URL which is used. * * @return the URL */ public String getUrl() { return url; } /** * Sets the URL to use. * * @param url * the URL to use */ public void setUrl(String url) { this.url = url; } /** * Gets the host name of the proxy. * * @return the host name of the proxy */ public String getProxyHost() { return proxyHost; } /** * Sets the host name of the proxy. * * @param proxyHost * the host name of the proxy */ public void setProxyHost(String proxyHost) { this.proxyHost = proxyHost; } /** * Gets the port of the proxy. * * @return the port of the proxy */ public Integer getProxyPort() { return proxyPort; } /** * Sets the port of the proxy. * * @param proxyPort * the port of the proxy */ public void setProxyPort(Integer proxyPort) { this.proxyPort = proxyPort; } /** * Sets the user name for proxy authentication. * * @param proxyUsername * the user name for proxy authentication */ public void setProxyUsername(String proxyUsername) { this.proxyUsername = proxyUsername; } /** * Sets the password for proxy authentication. * * @param proxyPassword * the password for proxy authentication */ public void setProxyPassword(String proxyPassword) { this.proxyPassword = proxyPassword; } /** * Gets the pattern to convert the time. * * @return the pattern to convert the time */ public String getSendTimePattern() { return sendTimePattern; } /** * Sets the pattern to convert the time. * * @param sendTimePattern * the pattern to convert the time */ public void setSendTimePattern(String sendTimePattern) { this.sendTimePattern = sendTimePattern; } /** * Gets the default message type. * * @return the default message type */ public String getDefaultMessageType() { return defaultMessageType; } /** * Sets the default message type. * * @param defaultMessageType * the default message type */ public void setDefaultMessageType(String defaultMessageType) { this.defaultMessageType = defaultMessageType; } /* * (non-Javadoc) * * @see * org.bremersee.sms.service.AbstractSmsService#doSendSms(org.bremersee.sms. * service.model.SmsSendRequestDto) */ @Override public SmsSendResponseDto doSendSms(final SmsSendRequestDto smsSendRequest) throws SmsException { final String sender = getSender(smsSendRequest); final String receiver = getReceiver(smsSendRequest); final String message = getMessage(smsSendRequest); final String messageType = getMessageType(message); final String time = createSendTime(smsSendRequest.getSendTime()); final Charset charset = createCharset(); String url = new String(this.url); url = WebUtils.addUrlParameter(url, GATEWAY_USER_ID_KEY, username, charset); url = WebUtils.addUrlParameter(url, GATEWAY_USER_PASSWORD_KEY, password, charset); url = WebUtils.addUrlParameter(url, SENDER_KEY, sender, charset); url = WebUtils.addUrlParameter(url, RECEIVER_KEY, receiver, charset); url = WebUtils.addUrlParameter(url, MESSAGE_KEY, message, charset); if (StringUtils.isNotBlank(messageType)) { url = WebUtils.addUrlParameter(url, MESSAGE_TYPE_KEY, messageType, charset); } if (time != null) { url = WebUtils.addUrlParameter(url, TIME_KEY, time, charset); } url = WebUtils.addUrlParameter(url, GET_MSG_ID_KEY, GET_MSG_ID_VALUE, charset); url = WebUtils.addUrlParameter(url, GET_COUNT_MSG_KEY, GET_COUNT_MSG_VALUE, charset); url = WebUtils.addUrlParameter(url, GET_LIMIT_KEY, GET_LIMIT_VALUE, charset); url = WebUtils.addUrlParameter(url, GET_STATUS_KEY, GET_STATUS_VALUE, charset); final StringBuilder sb = new StringBuilder(); HttpURLConnection con = null; InputStreamReader in = null; try { con = createHttpURLConnection(url); con.connect(); in = new InputStreamReader(con.getInputStream(), charset); int len; char[] buf = new char[64]; while ((len = in.read(buf)) > 0) { sb.append(buf, 0, len); } } catch (IOException e) { SmsException se = new SmsException(e); log.error("Sending SMS specified by " + smsSendRequest + " failed.", se); throw se; } finally { IOUtils.closeQuietly(in); if (con != null) { con.disconnect(); } } final GoyyaSmsSendResponseDto goyyaSmsSendResponse = new GoyyaSmsSendResponseDto(sb.toString()); final SmsSendResponseDto smsSendResponse = new SmsSendResponseDto(smsSendRequest, goyyaSmsSendResponse.isOk(), goyyaSmsSendResponse); return smsSendResponse; } /** * Returns the message type. * * @param message * the message * @return the message type */ protected String getMessageType(final String message) { if (StringUtils.isBlank(defaultMessageType) || MESSAGE_TYPE_TEXT_VALUE.equalsIgnoreCase(defaultMessageType) || MESSAGE_TYPE_LONG_TEXT_VALUE.equalsIgnoreCase(defaultMessageType)) { return message.length() > getMaxLengthOfOneSms() ? MESSAGE_TYPE_LONG_TEXT_VALUE : MESSAGE_TYPE_TEXT_VALUE; } return defaultMessageType; } /** * Creates the send time URL parameter value. * * @param sendTime * the send time as {@link Date} * @return the send time URL parameter value */ protected String createSendTime(final Date sendTime) { if (sendTime == null || new Date(System.currentTimeMillis() + 1000L * 60L).after(sendTime)) { return null; } String sendTimePattern = StringUtils.isBlank(this.sendTimePattern) ? DEFAULT_SEND_TIME_PATTERN : this.sendTimePattern; SimpleDateFormat sdf = new SimpleDateFormat(sendTimePattern, Locale.GERMANY); sdf.setTimeZone(TimeZone.getTimeZone("Europe/Berlin")); return sdf.format(sendTime); } /** * Creates the URL connection. * * @param url * the URL * @return the URL connection * @throws IOException * if creation of the URL connection fails */ protected HttpURLConnection createHttpURLConnection(final String url) throws IOException { URL sendUrl = new URL(url); HttpURLConnection con = null; if (StringUtils.isNotBlank(proxyHost) && proxyPort != null) { Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); con = (HttpURLConnection) sendUrl.openConnection(proxy); if (StringUtils.isNotBlank(proxyUsername)) { String passwd = proxyPassword != null ? proxyPassword : ""; String authValue = proxyUsername + ":" + passwd; String headerValue = Base64.encodeBase64String(authValue.getBytes("utf-8")); con.setRequestProperty("Proxy-Authorization", "Basic " + headerValue); } } else { con = (HttpURLConnection) sendUrl.openConnection(); } try { if (url.toString().toLowerCase().startsWith("https")) { HttpsURLConnection secCon = (HttpsURLConnection) con; secCon.setHostnameVerifier(createAllHostnamesVerifier()); SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, createTrustAllManagers(), new SecureRandom()); secCon.setSSLSocketFactory(sc.getSocketFactory()); } } catch (NoSuchAlgorithmException e) { IOException ise = new IOException(e); // log.error("Creating HttpURLConnection failed.", ise); throw ise; } catch (KeyManagementException e) { IOException ise = new IOException(e); // log.error("Creating HttpURLConnection failed.", ise); throw ise; } return con; } /** * Creates a host name verifier that does not verify the host name. */ protected HostnameVerifier createAllHostnamesVerifier() { return new HostnameVerifier() { /* * (non-Javadoc) * * @see javax.net.ssl.HostnameVerifier#verify(java.lang.String, * javax.net.ssl.SSLSession) */ @Override public boolean verify(String hostname, SSLSession session) { return true; } }; } /** * Creates an array of trust managers which trusts all X509 certificates. */ protected TrustManager[] createTrustAllManagers() { return new TrustManager[] { new X509TrustManager() { /* * (non-Javadoc) * * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() */ @Override public X509Certificate[] getAcceptedIssuers() { return null; } /* * (non-Javadoc) * * @see * javax.net.ssl.X509TrustManager#checkClientTrusted(java. * security.cert.X509Certificate[], java.lang.String) */ @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { } /* * (non-Javadoc) * * @see * javax.net.ssl.X509TrustManager#checkServerTrusted(java. * security.cert.X509Certificate[], java.lang.String) */ @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; } }