Author: hadrian Date: Wed Feb 29 02:34:08 2012 New Revision: 1294946 URL: http://svn.apache.org/viewvc?rev=1294946&view=rev Log: CAMEL-5030. Support for smpp tunnelling through http proxy
Added: camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConnectionFactory.java camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConnectionFactoryTest.java Removed: camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppSSLConnectionFactory.java camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppSSLConnectionFactoryTest.java Modified: camel/branches/camel-2.9.x/components/camel-smpp/pom.xml camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConfiguration.java camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConsumer.java camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppProducer.java camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConfigurationTest.java Modified: camel/branches/camel-2.9.x/components/camel-smpp/pom.xml URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/pom.xml?rev=1294946&r1=1294945&r2=1294946&view=diff ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/pom.xml (original) +++ camel/branches/camel-2.9.x/components/camel-smpp/pom.xml Wed Feb 29 02:34:08 2012 @@ -44,6 +44,11 @@ <artifactId>org.apache.servicemix.bundles.jsmpp</artifactId> <version>${jsmpp-version}</version> </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>${commons-codec-version}</version> + </dependency> <!-- testing --> <dependency> @@ -77,7 +82,6 @@ <artifactId>slf4j-log4j12</artifactId> <scope>test</scope> </dependency> - </dependencies> </project> Modified: camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConfiguration.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConfiguration.java?rev=1294946&r1=1294945&r2=1294946&view=diff ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConfiguration.java (original) +++ camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConfiguration.java Wed Feb 29 02:34:08 2012 @@ -59,6 +59,10 @@ public class SmppConfiguration implement private long initialReconnectDelay = 5000; private long reconnectDelay = 5000; private boolean lazySessionCreation; + private String httpProxyHost; + private Integer httpProxyPort = Integer.valueOf(3128); + private String httpProxyUsername; + private String httpProxyPassword; /** * A POJO which contains all necessary configuration parameters for the SMPP connection @@ -289,6 +293,38 @@ public class SmppConfiguration implement public void setLazySessionCreation(boolean lazySessionCreation) { this.lazySessionCreation = lazySessionCreation; } + + public String getHttpProxyHost() { + return httpProxyHost; + } + + public void setHttpProxyHost(String httpProxyHost) { + this.httpProxyHost = httpProxyHost; + } + + public Integer getHttpProxyPort() { + return httpProxyPort; + } + + public void setHttpProxyPort(Integer httpProxyPort) { + this.httpProxyPort = httpProxyPort; + } + + public String getHttpProxyUsername() { + return httpProxyUsername; + } + + public void setHttpProxyUsername(String httpProxyUsername) { + this.httpProxyUsername = httpProxyUsername; + } + + public String getHttpProxyPassword() { + return httpProxyPassword; + } + + public void setHttpProxyPassword(String httpProxyPassword) { + this.httpProxyPassword = httpProxyPassword; + } @Override public String toString() { @@ -318,6 +354,10 @@ public class SmppConfiguration implement + ", initialReconnectDelay=" + initialReconnectDelay + ", reconnectDelay=" + reconnectDelay + ", lazySessionCreation=" + lazySessionCreation + + ", httpProxyHost=" + httpProxyHost + + ", httpProxyPort=" + httpProxyPort + + ", httpProxyUsername=" + httpProxyUsername + + ", httpProxyPassword=" + httpProxyPassword + "]"; } } Added: camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConnectionFactory.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConnectionFactory.java?rev=1294946&view=auto ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConnectionFactory.java (added) +++ camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConnectionFactory.java Wed Feb 29 02:34:08 2012 @@ -0,0 +1,169 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/** + * The connectProxy() method implementation is inspired from + * com.jcraft.jsch.ProxyHTTP available under a BSD style license (below). + * + * Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved. + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the distribution. + + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, + * INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package org.apache.camel.component.smpp; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.Socket; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; + +import org.apache.camel.RuntimeCamelException; +import org.apache.commons.codec.binary.Base64; +import org.jsmpp.session.connection.Connection; +import org.jsmpp.session.connection.ConnectionFactory; +import org.jsmpp.session.connection.socket.SocketConnection; + +/** + * A Jsmpp ConnectionFactory that creates SSL Sockets. + * + * @version + */ +public final class SmppConnectionFactory implements ConnectionFactory { + private SmppConfiguration config; + + private SmppConnectionFactory(SmppConfiguration config) { + this.config = config; + } + + public static SmppConnectionFactory getInstance(SmppConfiguration config) { + return new SmppConnectionFactory(config); + } + + public Connection createConnection(String host, int port) throws IOException { + try { + Socket socket; + SocketFactory socketFactory; + socketFactory = config.getUsingSSL() ? SSLSocketFactory.getDefault() : SocketFactory.getDefault(); + if (config.getHttpProxyHost() != null) { + socket = socketFactory.createSocket(config.getHttpProxyHost(), config.getHttpProxyPort()); + connectProxy(host, port, socket); + } else { + socket = socketFactory.createSocket(host, port); + } + return new SocketConnection(socket); + + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + } + + private void connectProxy(String host, int port, Socket socket) throws IOException { + try { + OutputStream out = socket.getOutputStream(); + InputStream in = socket.getInputStream(); + + String connectString = "CONNECT " + host + ":" + port + " HTTP/1.0\r\n"; + out.write(connectString.getBytes()); + + String username = config.getHttpProxyUsername(); + String password = config.getHttpProxyPassword(); + + if (username != null && password != null) { + String usernamePassword = username + ":" + password; + byte[] code = Base64.encodeBase64(usernamePassword.getBytes()); + out.write("Proxy-Authorization: Basic ".getBytes()); + out.write(code); + out.write("\r\n".getBytes()); + } + + out.write("\r\n".getBytes()); + out.flush(); + + int ch = 0; + + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + String response = reader.readLine(); + if (response == null) { + throw new RuntimeCamelException("Empty response to CONNECT request to host " + host + ":" + port); + } + String reason = "Unknown reason"; + int code = -1; + try { + ch = response.indexOf(' '); + int bar = response.indexOf(' ', ch + 1); + code = Integer.parseInt(response.substring(ch + 1, bar)); + reason = response.substring(bar + 1); + } catch (NumberFormatException e) { + throw new RuntimeCamelException("Invalid response to CONNECT request to host " + host + ":" + port + + " - cannot parse code from response string: " + response); + } + if (code != 200) { + throw new RuntimeCamelException("Proxy error: " + reason); + } + + // read until empty line + for (; response.length() > 0;) { + response = reader.readLine(); + if (response == null) { + throw new RuntimeCamelException("Proxy error: reached end of stream"); + } + } + } catch (RuntimeException re) { + closeSocket(socket); + throw re; + } catch (Exception e) { + closeSocket(socket); + throw new RuntimeException("SmppConnectionFactory: " + e.getMessage()); + } + } + + private static void closeSocket(Socket s) { + if (s != null) { + try { + s.close(); + } catch (IOException e) { + // ignore + } + } + } +} \ No newline at end of file Modified: camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConsumer.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConsumer.java?rev=1294946&r1=1294945&r2=1294946&view=diff ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConsumer.java (original) +++ camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppConsumer.java Wed Feb 29 02:34:08 2012 @@ -102,13 +102,9 @@ public class SmppConsumer extends Defaul * @return the SMPPSession */ SMPPSession createSMPPSession() { - if (configuration.getUsingSSL()) { - return new SMPPSession(new SynchronizedPDUSender(new DefaultPDUSender( - new DefaultComposer())), new DefaultPDUReader(), SmppSSLConnectionFactory - .getInstance()); - } else { - return new SMPPSession(); - } + return new SMPPSession(new SynchronizedPDUSender(new DefaultPDUSender( + new DefaultComposer())), new DefaultPDUReader(), SmppConnectionFactory + .getInstance(configuration)); } @Override Modified: camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppProducer.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppProducer.java?rev=1294946&r1=1294945&r2=1294946&view=diff ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppProducer.java (original) +++ camel/branches/camel-2.9.x/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppProducer.java Wed Feb 29 02:34:08 2012 @@ -106,12 +106,9 @@ public class SmppProducer extends Defaul * @return the SMPPSession */ SMPPSession createSMPPSession() { - if (configuration.getUsingSSL()) { - return new SMPPSession(new SynchronizedPDUSender(new DefaultPDUSender(new DefaultComposer())), - new DefaultPDUReader(), SmppSSLConnectionFactory.getInstance()); - } else { - return new SMPPSession(); - } + return new SMPPSession(new SynchronizedPDUSender(new DefaultPDUSender( + new DefaultComposer())), new DefaultPDUReader(), SmppConnectionFactory + .getInstance(configuration)); } public void process(Exchange exchange) throws Exception { Modified: camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConfigurationTest.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConfigurationTest.java?rev=1294946&r1=1294945&r2=1294946&view=diff ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConfigurationTest.java (original) +++ camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConfigurationTest.java Wed Feb 29 02:34:08 2012 @@ -67,6 +67,10 @@ public class SmppConfigurationTest { assertEquals(false, configuration.getUsingSSL()); assertEquals(5000, configuration.getInitialReconnectDelay()); assertEquals(5000, configuration.getReconnectDelay()); + assertEquals(null, configuration.getHttpProxyHost()); + assertEquals(new Integer(3128), configuration.getHttpProxyPort()); + assertEquals(null, configuration.getHttpProxyUsername()); + assertEquals(null, configuration.getHttpProxyPassword()); } @Test @@ -97,6 +101,10 @@ public class SmppConfigurationTest { assertEquals(true, configuration.getUsingSSL()); assertEquals(5001, configuration.getInitialReconnectDelay()); assertEquals(5002, configuration.getReconnectDelay()); + assertEquals("127.0.0.1", configuration.getHttpProxyHost()); + assertEquals(new Integer(3129), configuration.getHttpProxyPort()); + assertEquals("user", configuration.getHttpProxyUsername()); + assertEquals("secret", configuration.getHttpProxyPassword()); } @Test @@ -137,6 +145,10 @@ public class SmppConfigurationTest { assertEquals(config.getUsingSSL(), configuration.getUsingSSL()); assertEquals(config.getInitialReconnectDelay(), configuration.getInitialReconnectDelay()); assertEquals(config.getReconnectDelay(), configuration.getReconnectDelay()); + assertEquals(config.getHttpProxyHost(), configuration.getHttpProxyHost()); + assertEquals(config.getHttpProxyPort(), configuration.getHttpProxyPort()); + assertEquals(config.getHttpProxyUsername(), configuration.getHttpProxyUsername()); + assertEquals(config.getHttpProxyPassword(), configuration.getHttpProxyPassword()); } @@ -168,7 +180,11 @@ public class SmppConfigurationTest { + "numberingPlanIndicator=0, " + "initialReconnectDelay=5000, " + "reconnectDelay=5000, " - + "lazySessionCreation=false]"; + + "lazySessionCreation=false, " + + "httpProxyHost=null, " + + "httpProxyPort=3128, " + + "httpProxyUsername=null, " + + "httpProxyPassword=null]"; assertEquals(expected, configuration.toString()); } @@ -197,5 +213,9 @@ public class SmppConfigurationTest { config.setUsingSSL(true); config.setInitialReconnectDelay(5001); config.setReconnectDelay(5002); + config.setHttpProxyHost("127.0.0.1"); + config.setHttpProxyPort(new Integer(3129)); + config.setHttpProxyUsername("user"); + config.setHttpProxyPassword("secret"); } } \ No newline at end of file Added: camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConnectionFactoryTest.java URL: http://svn.apache.org/viewvc/camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConnectionFactoryTest.java?rev=1294946&view=auto ============================================================================== --- camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConnectionFactoryTest.java (added) +++ camel/branches/camel-2.9.x/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppConnectionFactoryTest.java Wed Feb 29 02:34:08 2012 @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.camel.component.smpp; + +import java.io.IOException; + +import org.jsmpp.session.connection.Connection; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * JUnit test class for <code>org.apache.camel.component.smpp.SmppConnectionFactory</code> + * + * @version + */ +public class SmppConnectionFactoryTest { + + @Test + @Ignore("Must be manually tested") + public void createConnection() throws IOException { + SmppConfiguration configuration = new SmppConfiguration(); + SmppConnectionFactory factory = SmppConnectionFactory.getInstance(configuration); + Connection connection = factory.createConnection("localhost", 2775); + + try { + Assert.assertNotNull(connection); + Assert.assertTrue(connection.isOpen()); + } finally { + if (connection != null) { + connection.close(); + } + } + } + + @Test + @Ignore("Must be manually tested") + public void createConnectionWithProxyHost() throws IOException { + SmppConfiguration configuration = new SmppConfiguration(); + configuration.setHttpProxyHost("localhost"); + configuration.setHttpProxyPort(new Integer(3128)); + SmppConnectionFactory factory = SmppConnectionFactory.getInstance(configuration); + Connection connection = factory.createConnection("localhost", 2775); + + try { + Assert.assertNotNull(connection); + Assert.assertTrue(connection.isOpen()); + } finally { + if (connection != null) { + connection.close(); + } + } + } + + @Test + @Ignore("Must be manually tested") + public void createConnectionWithProxyUsername() throws IOException { + SmppConfiguration configuration = new SmppConfiguration(); + configuration.setHttpProxyHost("localhost"); + configuration.setHttpProxyPort(new Integer(3128)); + configuration.setHttpProxyUsername("user"); + configuration.setHttpProxyPassword("secret"); + SmppConnectionFactory factory = SmppConnectionFactory.getInstance(configuration); + Connection connection = factory.createConnection("localhost", 2775); + + try { + Assert.assertNotNull(connection); + Assert.assertTrue(connection.isOpen()); + } finally { + if (connection != null) { + connection.close(); + } + } + } +} \ No newline at end of file