[ARIES-1756] Support osgi.basic.timeout
Project: http://git-wip-us.apache.org/repos/asf/aries-rsa/repo Commit: http://git-wip-us.apache.org/repos/asf/aries-rsa/commit/0ea1c0c3 Tree: http://git-wip-us.apache.org/repos/asf/aries-rsa/tree/0ea1c0c3 Diff: http://git-wip-us.apache.org/repos/asf/aries-rsa/diff/0ea1c0c3 Branch: refs/heads/master Commit: 0ea1c0c37d44e192478edc8a1e6c91383bb91381 Parents: 3cfb2dc Author: Christian Schneider <[email protected]> Authored: Fri Nov 17 11:35:02 2017 +0100 Committer: Christian Schneider <[email protected]> Committed: Fri Nov 17 11:35:02 2017 +0100 ---------------------------------------------------------------------- .../provider/tcp/EndpointPropertiesParser.java | 70 ++++++++++++++++ .../aries/rsa/provider/tcp/TCPProvider.java | 5 +- .../aries/rsa/provider/tcp/TcpEndpoint.java | 20 +---- .../rsa/provider/tcp/TcpInvocationHandler.java | 12 +-- .../rsa/provider/tcp/EndpointParserTest.java | 86 ++++++++++++++++++++ .../aries/rsa/provider/tcp/TcpEndpointTest.java | 44 ++++------ .../aries/rsa/provider/tcp/TcpProviderTest.java | 15 +++- .../rsa/provider/tcp/myservice/MyService.java | 1 + .../provider/tcp/myservice/MyServiceImpl.java | 8 +- 9 files changed, 210 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/EndpointPropertiesParser.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/EndpointPropertiesParser.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/EndpointPropertiesParser.java new file mode 100644 index 0000000..692c1d8 --- /dev/null +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/EndpointPropertiesParser.java @@ -0,0 +1,70 @@ +/** + * 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.aries.rsa.provider.tcp; + +import java.util.Map; + +import org.osgi.service.remoteserviceadmin.EndpointDescription; + +public class EndpointPropertiesParser { + static final String PORT_KEY = "aries.rsa.port"; + static final String DYNAMIC_PORT = "0"; + static final String HOSTNAME_KEY = "aries.rsa.hostname"; + static final String TIMEOUT_KEY = "osgi.basic.timeout"; + static final String DEFAULT_TIMEOUT_MILLIS = "300000"; + + private Map<String, Object> ep; + + public EndpointPropertiesParser(EndpointDescription ep) { + this.ep = ep.getProperties(); + } + + public EndpointPropertiesParser(Map<String, Object> ep) { + this.ep = ep; + } + + public int getTimeoutMillis() { + return getInt(TIMEOUT_KEY, DEFAULT_TIMEOUT_MILLIS); + } + + int getInt(String key, String defaultValue) { + return Integer.parseInt(getString(key, defaultValue)); + } + + String getString(String key, String defaultValue) { + Object value = ep.get(key); + return value != null ? value.toString() : defaultValue; + } + + public int getPort() { + return getInt(PORT_KEY, DYNAMIC_PORT); + } + + public String getHostname() { + String hostName = getString(HOSTNAME_KEY, System.getProperty(HOSTNAME_KEY)); + if (hostName == null) { + hostName = LocalHostUtil.getLocalIp(); + } + return hostName; + } + + public int getNumThreads() { + return getInt("aries.rsa.numThreads", "10"); + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java index c103abb..4ae654f 100644 --- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java @@ -32,7 +32,6 @@ import org.osgi.service.remoteserviceadmin.RemoteConstants; @SuppressWarnings("rawtypes") public class TCPProvider implements DistributionProvider { - private static final String TCP_CONFIG_TYPE = "aries.tcp"; @Override @@ -57,11 +56,13 @@ public class TCPProvider implements DistributionProvider { throws IntentUnsatisfiedException { try { URI address = new URI(endpoint.getId()); - InvocationHandler handler = new TcpInvocationHandler(cl, address.getHost(), address.getPort()); + Integer timeout = new EndpointPropertiesParser(endpoint).getTimeoutMillis(); + InvocationHandler handler = new TcpInvocationHandler(cl, address.getHost(), address.getPort(), timeout); return Proxy.newProxyInstance(cl, interfaces, handler); } catch (Exception e) { throw new RuntimeException(e); } } + } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java index 41ae16e..25f6d62 100644 --- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java @@ -33,28 +33,16 @@ public class TcpEndpoint implements Endpoint { if (service == null) { throw new NullPointerException("Service must not be null"); } - Integer port = getInt(effectiveProperties, "aries.rsa.port", "0"); - String hostName = getString(effectiveProperties, "aries.rsa.hostname", System.getProperty("aries.rsa.hostname")); - if (hostName == null) { - hostName = LocalHostUtil.getLocalIp(); - } - int numThreads = getInt(effectiveProperties, "aries.rsa.numThreads", "10"); + EndpointPropertiesParser parser = new EndpointPropertiesParser(effectiveProperties); + Integer port = parser.getPort(); + String hostName = parser.getHostname(); + int numThreads = parser.getNumThreads(); tcpServer = new TCPServer(service, hostName, port, numThreads); String endpointId = String.format("tcp://%s:%s",hostName, tcpServer.getPort()); effectiveProperties.put(RemoteConstants.ENDPOINT_ID, endpointId); effectiveProperties.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, ""); this.epd = new EndpointDescription(effectiveProperties); } - - - private Integer getInt(Map<String, Object> effectiveProperties, String key, String defaultValue) { - return Integer.parseInt(getString(effectiveProperties, key, defaultValue)); - } - - private String getString(Map<String, Object> effectiveProperties, String key, String defaultValue) { - Object value = effectiveProperties.get(key); - return value != null ? value.toString() : defaultValue; - } @Override public EndpointDescription description() { http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpInvocationHandler.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpInvocationHandler.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpInvocationHandler.java index cdbf8ec..3206339 100644 --- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpInvocationHandler.java +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpInvocationHandler.java @@ -30,26 +30,28 @@ public class TcpInvocationHandler implements InvocationHandler { private String host; private int port; private ClassLoader cl; + private int timeoutMillis; - public TcpInvocationHandler(ClassLoader cl, String host, int port) + public TcpInvocationHandler(ClassLoader cl, String host, int port, int timeoutMillis) throws UnknownHostException, IOException { this.cl = cl; this.host = host; this.port = port; - + this.timeoutMillis = timeoutMillis; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try ( - Socket socket = new Socket(this.host, this.port); - ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()) + Socket socket = new Socket(this.host, this.port); + ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()) ) { + socket.setSoTimeout(timeoutMillis); out.writeObject(method.getName()); out.writeObject(args); out.flush(); return parseResult(socket); - } catch (Exception e) { + } catch (Exception e) { throw new RuntimeException("Error calling " + host + ":" + port + " method: " + method.getName(), e); } } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/EndpointParserTest.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/EndpointParserTest.java b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/EndpointParserTest.java new file mode 100644 index 0000000..27a2399 --- /dev/null +++ b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/EndpointParserTest.java @@ -0,0 +1,86 @@ +/** + * 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.aries.rsa.provider.tcp; + +import java.util.Date; +import java.util.Hashtable; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.RemoteConstants; + + +public class EndpointParserTest { + + private Map<String, Object> props; + + @Before + public void defaultProps() { + props = new Hashtable<String, Object>(); + props.put("objectClass", new String[]{Runnable.class.getName()}); + props.put(RemoteConstants.ENDPOINT_ID, "myid"); + props.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, "any"); + } + + @Test + public void testDefaults() { + Assert.assertEquals(300000, getParser().getTimeoutMillis()); + Assert.assertEquals(0, getParser().getPort()); + Assert.assertEquals(LocalHostUtil.getLocalIp(), getParser().getHostname()); + } + + @Test + public void testTimeoutString() { + props.put(EndpointPropertiesParser.TIMEOUT_KEY, "100"); + Assert.assertEquals(100, getParser().getTimeoutMillis()); + } + + @Test + public void testTimeoutInt() { + props.put(EndpointPropertiesParser.TIMEOUT_KEY, 100); + Assert.assertEquals(100, getParser().getTimeoutMillis()); + } + + + @Test + public void testPortString() { + props.put(EndpointPropertiesParser.PORT_KEY, "11111"); + Assert.assertEquals(11111, getParser().getPort()); + } + + @Test + public void testPortInt() { + props.put(EndpointPropertiesParser.PORT_KEY, 11111); + Assert.assertEquals(11111, getParser().getPort()); + } + + @Test(expected=IllegalArgumentException.class) + public void testTimeoutInvalid() { + props.put(EndpointPropertiesParser.TIMEOUT_KEY, new Date()); + getParser().getTimeoutMillis(); + } + + private EndpointPropertiesParser getParser() { + return new EndpointPropertiesParser(new EndpointDescription(props)); + } + +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpEndpointTest.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpEndpointTest.java b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpEndpointTest.java index d516822..2610aa9 100644 --- a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpEndpointTest.java +++ b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpEndpointTest.java @@ -7,52 +7,44 @@ import java.util.Map; import org.apache.aries.rsa.provider.tcp.myservice.MyService; import org.apache.aries.rsa.provider.tcp.myservice.MyServiceImpl; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.osgi.framework.Constants; import org.osgi.service.remoteserviceadmin.EndpointDescription; import org.osgi.service.remoteserviceadmin.RemoteConstants; public class TcpEndpointTest { - - static final String PORT = "45346"; - - @Test - public void testEndpointProperties() throws IOException { - Object service = new MyServiceImpl(); - Map<String, Object> props = new HashMap<>(); + private static final String HOSTNAME = "myhost"; + private static final String PORT = "45346"; + + private Map<String, Object> props; + private Object service; + + @Before + public void defaultProps() { + props = new HashMap<>(); props.put(Constants.OBJECTCLASS, new String[]{MyService.class.getName()}); props.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, ""); - props.put("aries.rsa.port", PORT); - props.put("aries.rsa.hostname", "myhost"); - TcpEndpoint tcpEndpoint = new TcpEndpoint(service, props); - EndpointDescription epd = tcpEndpoint.description(); - Assert.assertEquals("tcp://myhost:" + PORT, epd.getId()); - tcpEndpoint.close(); + service = new MyServiceImpl(); } - + @Test - public void testIntPort() throws IOException { - Object service = new MyServiceImpl(); - Map<String, Object> props = new HashMap<>(); - props.put(Constants.OBJECTCLASS, new String[]{MyService.class.getName()}); - props.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, ""); - props.put("aries.rsa.port", Integer.parseInt(PORT)); - props.put("aries.rsa.hostname", "myhost"); + public void testEndpointProperties() throws IOException { + props.put("aries.rsa.port", PORT); + props.put("aries.rsa.hostname", HOSTNAME); TcpEndpoint tcpEndpoint = new TcpEndpoint(service, props); EndpointDescription epd = tcpEndpoint.description(); - Assert.assertEquals("tcp://myhost:" + PORT, epd.getId()); + Assert.assertEquals("tcp://" + HOSTNAME + ":" + PORT, epd.getId()); tcpEndpoint.close(); } @Test public void testEndpointPropertiesDefault() throws IOException { - Object service = new MyServiceImpl(); - Map<String, Object> props = new HashMap<>(); - props.put(Constants.OBJECTCLASS, new String[]{MyService.class.getName()}); - props.put(RemoteConstants.SERVICE_IMPORTED_CONFIGS, ""); TcpEndpoint tcpEndpoint = new TcpEndpoint(service, props); EndpointDescription epd = tcpEndpoint.description(); Assert.assertNotNull(epd.getId()); tcpEndpoint.close(); } + + } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java index ad36f65..c9d69d2 100644 --- a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java +++ b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java @@ -21,6 +21,7 @@ package org.apache.aries.rsa.provider.tcp; import static org.hamcrest.core.StringStartsWith.startsWith; import java.io.IOException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -54,6 +55,7 @@ public class TcpProviderTest { EndpointHelper.addObjectClass(props, exportedInterfaces); props.put("aries.rsa.hostname", "localhost"); props.put("aries.rsa.numThreads", "10"); + props.put("osgi.basic.timeout", 100); MyService myService = new MyServiceImpl(); BundleContext bc = EasyMock.mock(BundleContext.class); ep = provider.exportService(myService, bc, props, exportedInterfaces); @@ -64,6 +66,16 @@ public class TcpProviderTest { exportedInterfaces, ep.description()); } + + @Test + public void testCallTimeout() throws IOException { + try { + myServiceProxy.call("slow"); + Assert.fail("Expecting timeout"); + } catch (RuntimeException e) { + Assert.assertEquals(SocketTimeoutException.class, e.getCause().getClass()); + } + } @Test public void testPerf() throws IOException, InterruptedException { @@ -96,7 +108,7 @@ public class TcpProviderTest { List<String> msgList = new ArrayList<String>(); myServiceProxy.callWithList(msgList); } - + @AfterClass public static void close() throws IOException { ep.close(); @@ -126,4 +138,5 @@ public class TcpProviderTest { long tps = NUM_CALLS * 1000 / (System.currentTimeMillis() - start); System.out.println(tps + " tps"); } + } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyService.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyService.java b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyService.java index 04cbe86..6a791c9 100644 --- a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyService.java +++ b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyService.java @@ -32,4 +32,5 @@ public interface MyService { void callOneWay(String msg); void callWithList(List<String> msg); + } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/0ea1c0c3/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyServiceImpl.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyServiceImpl.java b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyServiceImpl.java index de27304..93d61a3 100644 --- a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyServiceImpl.java +++ b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/myservice/MyServiceImpl.java @@ -32,6 +32,12 @@ public class MyServiceImpl implements MyService { if ("throw exception".equals(msg)) { throw new IllegalArgumentException("Throwing expected exception"); } + if ("slow".equals(msg)) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + } + } } @Override @@ -40,7 +46,7 @@ public class MyServiceImpl implements MyService { @Override public void callWithList(List<String> msg) { - + } }
