Skip to content

Commit

Permalink
Merge pull request Azure#19 from WindowsAzure/dev
Browse files Browse the repository at this point in the history
Forward integration from Dev
  • Loading branch information
Albert Cheng committed Oct 4, 2012
2 parents 571c28d + 13737cd commit 3f29fc3
Show file tree
Hide file tree
Showing 25 changed files with 1,268 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
* Copyright 2011 Microsoft Corporation
*
* 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
* 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.
* 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 com.microsoft.windowsazure.services.core;

Expand All @@ -23,10 +23,18 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sun.jersey.api.client.config.ClientConfig;

public class Configuration {

/**
* Property name for socket connection timeout used by services created with this configuration.
*/
public static final String PROPERTY_CONNECT_TIMEOUT = "com.microsoft.windowsazure.services.core.Configuration.connectTimeout";

/**
* Property name for socket read timeout used by services created with this configuration.
*/
public static final String PROPERTY_READ_TIMEOUT = "com.microsoft.windowsazure.services.core.Configuration.readTimeout";

private static Configuration instance;
Map<String, Object> properties;
Builder builder;
Expand All @@ -36,17 +44,11 @@ public class Configuration {
public Configuration() {
this.properties = new HashMap<String, Object>();
this.builder = DefaultBuilder.create();
init();
}

public Configuration(Builder builder) {
this.properties = new HashMap<String, Object>();
this.builder = builder;
init();
}

private void init() {
setProperty("ClientConfig", builder.build("", ClientConfig.class, properties));
}

public static Configuration getInstance() {
Expand Down Expand Up @@ -102,4 +104,7 @@ public void setProperty(String name, Object value) {
properties.put(name, value);
}

public Map<String, Object> getProperties() {
return properties;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Copyright 2012 Microsoft Corporation
*
* 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 com.microsoft.windowsazure.services.core;

/**
* Exception indicating a service operation has timed out.
*/
public class ServiceTimeoutException extends ServiceException {

private static final long serialVersionUID = 6612846403178749361L;

/**
* Construct a ServiceTimeoutException instance with default parameters.
*/
public ServiceTimeoutException() {
}

/**
* Construct a ServiceTimeoutException instance with the specified message.
*
* @param message
* Exception message
*/
public ServiceTimeoutException(String message) {
super(message);
}

/**
* Construct a ServiceTimeoutException instance with specified
* message and cause
*
* @param message
* Exception message
* @param cause
* Exception that caused this exception to occur
*/
public ServiceTimeoutException(String message, Throwable cause) {
super(message, cause);
}

/**
* Construct a ServiceTimeoutException instance with the specified cause.
*
* @param cause
* Exception that caused this exception to occur
*/
public ServiceTimeoutException(Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
* Copyright 2011 Microsoft Corporation
*
* 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
* 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.
* 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 com.microsoft.windowsazure.services.core.utils;

import java.net.SocketTimeoutException;

import com.microsoft.windowsazure.services.core.ServiceException;
import com.microsoft.windowsazure.services.core.ServiceTimeoutException;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.UniformInterfaceException;
Expand All @@ -25,12 +28,16 @@ public static ServiceException process(String serviceName, ServiceException exce
Throwable cause = exception.getCause();

for (Throwable scan = cause; scan != null; scan = scan.getCause()) {
if (ServiceException.class.isAssignableFrom(scan.getClass())) {
Class scanClass = scan.getClass();
if (ServiceException.class.isAssignableFrom(scanClass)) {
return populate(exception, serviceName, (ServiceException) scan);
}
else if (UniformInterfaceException.class.isAssignableFrom(scan.getClass())) {
else if (UniformInterfaceException.class.isAssignableFrom(scanClass)) {
return populate(exception, serviceName, (UniformInterfaceException) scan);
}
else if (SocketTimeoutException.class.isAssignableFrom(scanClass)) {
return populate(exception, serviceName, (SocketTimeoutException) scan);
}
}

exception.setServiceName(serviceName);
Expand Down Expand Up @@ -83,4 +90,9 @@ static ServiceException populate(ServiceException exception, String serviceName,
return exception;
}

static ServiceException populate(ServiceException exception, String serviceName, SocketTimeoutException cause) {
ServiceTimeoutException newException = new ServiceTimeoutException(cause.getMessage(), cause);
newException.setServiceName(serviceName);
return newException;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.microsoft.windowsazure.services.core.Builder;
import com.microsoft.windowsazure.services.core.Builder.Registry;
import com.microsoft.windowsazure.services.core.Configuration;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
Expand All @@ -31,8 +32,37 @@ public void register(Registry registry) {
@Override
public ClientConfig create(String profile, Builder builder, Map<String, Object> properties) {
ClientConfig clientConfig = new DefaultClientConfig();
profile = normalizeProfile(profile);

// Lower levels of the stack assume timeouts are set.
// Set default timeout on clientConfig in case user
// hasn't set it yet in their configuration

clientConfig.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, new Integer(90 * 1000));
clientConfig.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, new Integer(90 * 1000));

for (Entry<String, Object> entry : properties.entrySet()) {
clientConfig.getProperties().put(entry.getKey(), entry.getValue());
Object propertyValue = entry.getValue();
String propertyKey = entry.getKey();

if (propertyKey.equals(profile + Configuration.PROPERTY_CONNECT_TIMEOUT)) {
propertyKey = ClientConfig.PROPERTY_CONNECT_TIMEOUT;
}
if (propertyKey.equals(profile + Configuration.PROPERTY_READ_TIMEOUT)) {
propertyKey = ClientConfig.PROPERTY_READ_TIMEOUT;
}

// ClientConfig requires instance of Integer to properly set
// timeouts, but config file will deliver strings. Special
// case these timeout properties and convert them to Integer
// if necessary.
if (propertyKey.equals(ClientConfig.PROPERTY_CONNECT_TIMEOUT)
|| propertyKey.equals(ClientConfig.PROPERTY_READ_TIMEOUT)) {
if (propertyValue instanceof String) {
propertyValue = Integer.valueOf((String) propertyValue);
}
}
clientConfig.getProperties().put(propertyKey, propertyValue);
}
return clientConfig;
}
Expand All @@ -41,7 +71,7 @@ public ClientConfig create(String profile, Builder builder, Map<String, Object>
registry.add(new Builder.Factory<Client>() {
@Override
public Client create(String profile, Builder builder, Map<String, Object> properties) {
ClientConfig clientConfig = (ClientConfig) properties.get("ClientConfig");
ClientConfig clientConfig = builder.build(profile, ClientConfig.class, properties);
Client client = Client.create(clientConfig);
return client;
}
Expand All @@ -50,11 +80,23 @@ public Client create(String profile, Builder builder, Map<String, Object> proper
registry.add(new Builder.Factory<HttpURLConnectionClient>() {
@Override
public HttpURLConnectionClient create(String profile, Builder builder, Map<String, Object> properties) {
ClientConfig clientConfig = (ClientConfig) properties.get("ClientConfig");
ClientConfig clientConfig = builder.build(profile, ClientConfig.class, properties);
HttpURLConnectionClient client = HttpURLConnectionClient.create(clientConfig);
//client.addFilter(new LoggingFilter());
return client;
}
});
}

private static String normalizeProfile(String profile) {
if (profile == null) {
return "";
}

if (profile.endsWith(".")) {
return profile;
}

return profile + ".";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
* Copyright 2011 Microsoft Corporation
*
* 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
* 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.
* 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 com.microsoft.windowsazure.services.core.utils.pipeline;

Expand All @@ -26,7 +26,7 @@ public HttpURLConnectionClient(HttpURLConnectionClientHandler handler, ClientCon
}

public static HttpURLConnectionClient create(ClientConfig config) {
return new HttpURLConnectionClient(new HttpURLConnectionClientHandler(), config);
return new HttpURLConnectionClient(new HttpURLConnectionClientHandler(config), config);
}

public HttpURLConnectionClientHandler getRootHandler() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
* Copyright 2011 Microsoft Corporation
*
* 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
* 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.
* 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 com.microsoft.windowsazure.services.core.utils.pipeline;

Expand All @@ -37,10 +37,28 @@
import com.sun.jersey.core.header.InBoundHeaders;

public class HttpURLConnectionClientHandler extends TerminatingClientHandler {

private final int connectionTimeoutMillis;
private final int readTimeoutMillis;

public HttpURLConnectionClientHandler(ClientConfig clientConfig) {
connectionTimeoutMillis = readTimeoutFromConfig(clientConfig, ClientConfig.PROPERTY_CONNECT_TIMEOUT);
readTimeoutMillis = readTimeoutFromConfig(clientConfig, ClientConfig.PROPERTY_READ_TIMEOUT);
}

private static int readTimeoutFromConfig(ClientConfig config, String propertyName) {
Integer property = (Integer) config.getProperty(propertyName);
if (property != null) {
return property.intValue();
}
throw new IllegalArgumentException(propertyName);
}

/**
* Empty "no-op" listener if none registered
*/
private static final EntityStreamingListener EMPTY_STREAMING_LISTENER = new EntityStreamingListener() {
@Override
public void onBeforeStreamingEntity(ClientRequest clientRequest) {
}
};
Expand Down Expand Up @@ -164,6 +182,7 @@ public String toString() {
}
}

@Override
public ClientResponse handle(final ClientRequest ro) throws ClientHandlerException {
try {
return doHandle(ro);
Expand All @@ -176,6 +195,9 @@ public ClientResponse handle(final ClientRequest ro) throws ClientHandlerExcepti
private ClientResponse doHandle(final ClientRequest clientRequest) throws IOException, MalformedURLException,
ProtocolException {
final HttpURLConnection urlConnection = (HttpURLConnection) clientRequest.getURI().toURL().openConnection();
urlConnection.setReadTimeout(readTimeoutMillis);
urlConnection.setConnectTimeout(connectionTimeoutMillis);

final EntityStreamingListener entityStreamingListener = getEntityStreamingListener(clientRequest);

urlConnection.setRequestMethod(clientRequest.getMethod());
Expand All @@ -202,6 +224,7 @@ private ClientResponse doHandle(final ClientRequest clientRequest) throws IOExce
writeRequestEntity(clientRequest, new RequestEntityWriterListener() {
private boolean inStreamingMode;

@Override
public void onRequestEntitySize(long size) {
if (size != -1 && size < Integer.MAX_VALUE) {
inStreamingMode = true;
Expand All @@ -222,6 +245,7 @@ public void onRequestEntitySize(long size) {
}
}

@Override
public OutputStream onGetOutputStream() throws IOException {
if (inStreamingMode)
return new StreamingOutputStream(urlConnection, clientRequest);
Expand Down
Loading

0 comments on commit 3f29fc3

Please sign in to comment.