diff --git a/ChangeLog.txt b/ChangeLog.txt index 17345e70ce1af..ec57d7e0d2140 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,8 @@ +2012.10.16 Version 0.3.2 + * Implemented a more graceful timeout Exception + * Implemented a better Exception for an empty header returned by the Azure Storage Service + * Added Fluent setters for Blob Models + 2012.09.11 Version 0.3.1 * Added Javadocs to 1.7 Storage Support from 0.3.0 release * Fixed bug where getqueue for an invalid queue returns 200 and the exception is not wrapped in a ServiceException diff --git a/microsoft-azure-api/pom.xml b/microsoft-azure-api/pom.xml index a728300dac54a..b8ed0c41ecb6f 100644 --- a/microsoft-azure-api/pom.xml +++ b/microsoft-azure-api/pom.xml @@ -17,7 +17,7 @@ 4.0.0 com.microsoft.windowsazure microsoft-windowsazure-api - 0.3.1 + 0.3.2 jar Microsoft Windows Azure Client API diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobRestProxy.java index 1366704cf2d81..1a8d830c20dfc 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobRestProxy.java @@ -976,8 +976,19 @@ else if (options.isUncommittedList()) { ListBlobBlocksResult result = response.getEntity(ListBlobBlocksResult.class); result.setEtag(response.getHeaders().getFirst("ETag")); result.setContentType(response.getHeaders().getFirst("Content-Type")); - result.setContentLength(Long.parseLong(response.getHeaders().getFirst("x-ms-blob-content-length"))); - result.setLastModified(dateMapper.parse(response.getHeaders().getFirst("Last-Modified"))); + + String blobContentLength = response.getHeaders().getFirst("x-ms-blob-content-length"); + if (blobContentLength != null) { + result.setContentLength(Long.parseLong(blobContentLength)); + } + else { + result.setContentLength(0); + } + + String lastModified = response.getHeaders().getFirst("Last-Modified"); + if (lastModified != null) { + result.setLastModified(dateMapper.parse(lastModified)); + } return result; } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ContainerACL.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ContainerACL.java index d5f6005b41ea2..4fb40c1285537 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ContainerACL.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ContainerACL.java @@ -1,11 +1,11 @@ /** * 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 - * + * * 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. @@ -46,7 +46,7 @@ public class ContainerACL { * Gets the Etag value associated with this {@link ContainerACL} instance. This is the value * returned for a container by a Blob service REST API Get Container ACL operation, or the value to set on a * container with a Set Container ACL operation. - * + * * @return * A {@link String} containing the Etag value associated with this {@link ContainerACL} * instance. @@ -61,20 +61,24 @@ public String getEtag() { * This value is only set on a container when this {@link ContainerACL} instance is passed as a parameter to a call * to an implementation of {@link BlobContract#setContainerACL(String, ContainerACL)} or * {@link BlobContract#setContainerACL(String, ContainerACL, BlobServiceOptions)}. - * + * * @param etag * A {@link String} containing the Etag value to associate with this * {@link ContainerACL} instance. + * + * @return + * A reference to this {@link ContainerACL} instance. */ - public void setEtag(String etag) { + public ContainerACL setEtag(String etag) { this.etag = etag; + return this; } /** * Gets the last modified time associated with this {@link ContainerACL} instance. This is the value * returned for a container by a Blob service REST API Get Container ACL operation, or the value to set on a * container with a Set Container ACL operation. - * + * * @return * A {@link Date} containing the last modified time associated with this {@link ContainerACL} instance. */ @@ -88,19 +92,22 @@ public Date getLastModified() { * This value is only set on a container when this {@link ContainerACL} instance is passed as a parameter to a call * to an implementation of {@link BlobContract#setContainerACL(String, ContainerACL)} or * {@link BlobContract#setContainerACL(String, ContainerACL, BlobServiceOptions)}. - * + * * @param lastModified - * A {@link Date} containing the last modified time to associate with this {@link ContainerACL} instance. + * A {@link java.util.Date} containing the last modified time to associate with this {@link ContainerACL} instance. + * @return + * A reference to this {@link ContainerACL} instance. */ - public void setLastModified(Date lastModified) { + public ContainerACL setLastModified(Date lastModified) { this.lastModified = lastModified; + return this; } /** * Gets the public access level associated with this {@link ContainerACL} instance. This is the value * returned for a container by a Blob service REST API Get Container ACL operation, or the value to set on a * container with a Set Container ACL operation. - * + * * @return * A {@link PublicAccessType} value representing the public access level associated with this * {@link ContainerACL} instance. @@ -115,20 +122,23 @@ public PublicAccessType getPublicAccess() { * This value is only set on a container when this {@link ContainerACL} instance is passed as a parameter to a call * to an implementation of {@link BlobContract#setContainerACL(String, ContainerACL)} or * {@link BlobContract#setContainerACL(String, ContainerACL, BlobServiceOptions)}. - * + * * @param publicAccess * A {@link PublicAccessType} value representing the public access level to associate with this * {@link ContainerACL} instance. + * @return + * A reference to this {@link ContainerACL} instance. */ - public void setPublicAccess(PublicAccessType publicAccess) { + public ContainerACL setPublicAccess(PublicAccessType publicAccess) { this.publicAccess = publicAccess; + return this; } /** * Gets the list of container-level access policies associated with this {@link ContainerACL} instance. This is the * value returned for a container by a Blob service REST API Get Container ACL operation, or the value to set on a * container with a Set Container ACL operation. - * + * * @return * A {@link List} of {@link SignedIdentifier} instances containing up to five container-level access * policies associated with this {@link ContainerACL} instance. @@ -143,13 +153,16 @@ public List getSignedIdentifiers() { * This value is only set on a container when this {@link ContainerACL} instance is passed as a parameter to a call * to an implementation of {@link BlobContract#setContainerACL(String, ContainerACL)} or * {@link BlobContract#setContainerACL(String, ContainerACL, BlobServiceOptions)}. - * + * * @param signedIdentifiers * A {@link List} of {@link SignedIdentifier} instances containing up to five container-level access * policies to associate with this {@link ContainerACL} instance. + * @return + * A reference to this {@link ContainerACL} instance. */ - public void setSignedIdentifiers(List signedIdentifiers) { + public ContainerACL setSignedIdentifiers(List signedIdentifiers) { this.signedIdentifiers = signedIdentifiers; + return this; } /** @@ -176,7 +189,7 @@ public void setSignedIdentifiers(List signedIdentifiers) { * This value is only set on a container when this {@link ContainerACL} instance is passed as a parameter to a call * to an implementation of {@link BlobContract#setContainerACL(String, ContainerACL)} or * {@link BlobContract#setContainerACL(String, ContainerACL, BlobServiceOptions)}. - * + * * @param id * A {@link String} containing the name for the access policy. * @param start @@ -213,7 +226,7 @@ public static class SignedIdentifiers { /** * Gets the list of container-level access policies associated with this {@link SignedIdentifiers} instance. - * + * * @return * A {@link List} of {@link SignedIdentifier} instances containing container-level access policies. */ @@ -224,7 +237,7 @@ public List getSignedIdentifiers() { /** * Sets the list of container-level access policies associated with this {@link SignedIdentifiers} instance. - * + * * @param signedIdentifiers * A {@link List} of {@link SignedIdentifier} instances containing container-level access policies. */ @@ -243,7 +256,7 @@ public static class SignedIdentifier { /** * Gets the name of the container-level access policy. The name may be up to 64 characters in * length and must be unique within the container. - * + * * @return * A {@link String} containing the name for the access policy. */ @@ -255,18 +268,21 @@ public String getId() { /** * Sets the name of the container-level access policy. The name may be up to 64 characters in * length and must be unique within the container. - * + * * @param id * A {@link String} containing the name for the access policy. + * @return + * A reference to this {@link SignedIdentifier} instance. */ - public void setId(String id) { + public SignedIdentifier setId(String id) { this.id = id; + return this; } /** * Gets an {@link AccessPolicy} reference containing the start time, expiration time, and permissions associated * with the container-level access policy. - * + * * @return * An {@link AccessPolicy} reference containing the start time, expiration time, and permissions * associated with the access policy. @@ -279,13 +295,16 @@ public AccessPolicy getAccessPolicy() { /** * Sets an {@link AccessPolicy} reference containing the start time, expiration time, and permissions to * associate with the container-level access policy. - * + * * @param accessPolicy * An {@link AccessPolicy} reference containing the start time, expiration time, and permissions * to associate with the access policy. + * @return + * A reference to this {@link SignedIdentifier} instance. */ - public void setAccessPolicy(AccessPolicy accessPolicy) { + public SignedIdentifier setAccessPolicy(AccessPolicy accessPolicy) { this.accessPolicy = accessPolicy; + return this; } } @@ -301,7 +320,7 @@ public static class AccessPolicy { * Gets the start time for valid access to a resource using the access policy. If this value is * null, the start time for any resource request using the access policy is assumed to be the time * when the Blob service receives the request. - * + * * @return * A {@link Date} representing the start time for the access policy, or null if none is * specified. @@ -316,20 +335,23 @@ public Date getStart() { * Sets the start time for valid access to a resource using the access policy. If this value is * null, the start time for any resource request using the access policy is assumed to be the time * when the Blob service receives the request. - * + * * @param start * A {@link Date} representing the start time for the access policy, or null to leave * the time unspecified. + * @return + * A reference to this {@link AccessPolicy} instance. */ - public void setStart(Date start) { + public AccessPolicy setStart(Date start) { this.start = start; + return this; } /** * Gets the expiration time for valid access to a resource using the access policy. If this value is * null, any Shared Access Signature that refers to this access policy must specify the expiry * value. - * + * * @return * A {@link Date} representing the expiration time for the access policy, or null if none * is specified. @@ -344,13 +366,16 @@ public Date getExpiry() { * Sets the expiration time for valid access to a resource using the access policy. If this value is * null, any Shared Access Signature that refers to this access policy must specify the expiry * value. - * + * * @param expiry * A {@link Date} representing the expiration time for the access policy, or null to * leave the time unspecified. + * @return + * A reference to this {@link AccessPolicy} instance. */ - public void setExpiry(Date expiry) { + public AccessPolicy setExpiry(Date expiry) { this.expiry = expiry; + return this; } /** @@ -359,7 +384,7 @@ public void setExpiry(Date expiry) { * operations to be performed with the access policy. For example, if all permissions to a resource are granted, * the method returns "rwdl" as the result. If only read/write permissions are granted, the method returns "rw" * as the result. - * + * * @return * A {@link String} containing the permissions specified for the access policy. */ @@ -373,12 +398,15 @@ public String getPermission() { * include read (r), write (w), delete (d), and list (l). Permissions may be grouped so as to allow multiple * operations to be performed with the access policy. For example, to grant all permissions to a resource, * specify "rwdl" for the parameter. To grant only read/write permissions, specify "rw" for the parameter. - * + * * @param permission * A {@link String} containing the permissions specified for the access policy. + * @return + * A reference to this {@link AccessPolicy} instance. */ - public void setPermission(String permission) { + public AccessPolicy setPermission(String permission) { this.permission = permission; + return this; } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ServiceProperties.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ServiceProperties.java index cdca5eee0e01b..24f92c559b2f6 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ServiceProperties.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/ServiceProperties.java @@ -1,11 +1,11 @@ /** * 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 - * + * * 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. @@ -34,7 +34,7 @@ public class ServiceProperties { /** * Gets the value of the logging options on the storage account. - * + * * @return * A {@link Logging} instance containing the logging options. */ @@ -45,17 +45,20 @@ public Logging getLogging() { /** * Sets the value of the logging options on the storage account. - * + * * @param logging * A {@link Logging} instance containing the logging options. + * @return + * A reference to this {@link ServiceProperties} instance. */ - public void setLogging(Logging logging) { + public ServiceProperties setLogging(Logging logging) { this.logging = logging; + return this; } /** * Gets the value of the metrics options on the storage account. - * + * * @return * A {@link Metrics} instance containing the metrics options. */ @@ -66,17 +69,20 @@ public Metrics getMetrics() { /** * Sets the value of the metrics options on the storage account. - * + * * @param metrics * A {@link Metrics} instance containing the metrics options. + * @return + * A reference to this {@link ServiceProperties} instance. */ - public void setMetrics(Metrics metrics) { + public ServiceProperties setMetrics(Metrics metrics) { this.metrics = metrics; + return this; } /** * Gets the default service version string used for operations on the storage account. - * + * * @return * A {@link String} containing the default service version string used for operations on the storage * account. @@ -92,13 +98,16 @@ public String getDefaultServiceVersion() { *

* See Storage Services Versioning * on MSDN for more information on applicable versions. - * + * * @param defaultServiceVersion * A {@link String} containing the default service version string used for operations on the storage * account. + * @return + * A reference to this {@link ServiceProperties} instance. */ - public void setDefaultServiceVersion(String defaultServiceVersion) { + public ServiceProperties setDefaultServiceVersion(String defaultServiceVersion) { this.defaultServiceVersion = defaultServiceVersion; + return this; } /** @@ -113,7 +122,7 @@ public static class Logging { /** * Gets the retention policy for logging data set on the storage account. - * + * * @return * The {@link RetentionPolicy} set on the storage account. */ @@ -124,17 +133,20 @@ public RetentionPolicy getRetentionPolicy() { /** * Sets the retention policy to use for logging data on the storage account. - * + * * @param retentionPolicy * The {@link RetentionPolicy} to set on the storage account. + * @return + * A reference to this {@link Logging} instance. */ - public void setRetentionPolicy(RetentionPolicy retentionPolicy) { + public Logging setRetentionPolicy(RetentionPolicy retentionPolicy) { this.retentionPolicy = retentionPolicy; + return this; } /** * Gets a flag indicating whether all write requests are logged. - * + * * @return * A flag value of true if all write operations are logged; otherwise, false. */ @@ -145,17 +157,20 @@ public boolean isWrite() { /** * Sets a flag indicating whether all write requests should be logged. - * + * * @param write * Set a flag value of true to log all write operations; otherwise, false. + * @return + * A reference to this {@link Logging} instance. */ - public void setWrite(boolean write) { + public Logging setWrite(boolean write) { this.write = write; + return this; } /** * Gets a flag indicating whether all read requests are logged. - * + * * @return * A flag value of true if all read operations are logged; otherwise, false. */ @@ -166,17 +181,20 @@ public boolean isRead() { /** * Sets a flag indicating whether all read requests should be logged. - * + * * @param read * Set a flag value of true to log all read operations; otherwise, false. + * @return + * A reference to this {@link Logging} instance. */ - public void setRead(boolean read) { + public Logging setRead(boolean read) { this.read = read; + return this; } /** * Gets a flag indicating whether all delete requests are logged. - * + * * @return * A flag value of true if all delete operations are logged; otherwise, false. */ @@ -187,17 +205,20 @@ public boolean isDelete() { /** * Sets a flag indicating whether all delete requests should be logged. - * + * * @param delete * Set a flag value of true to log all delete operations; otherwise, false. + * @return + * A reference to this {@link Logging} instance. */ - public void setDelete(boolean delete) { + public Logging setDelete(boolean delete) { this.delete = delete; + return this; } /** * Gets the version of logging configured on the storage account. - * + * * @return * A {@link String} containing the version of logging configured on the storage account. */ @@ -208,12 +229,15 @@ public String getVersion() { /** * Sets the version of logging configured on the storage account. - * + * * @param version * A {@link String} containing the version of logging configured on the storage account. + * @return + * A reference to this {@link Logging} instance. */ - public void setVersion(String version) { + public Logging setVersion(String version) { this.version = version; + return this; } } @@ -228,7 +252,7 @@ public static class Metrics { /** * Gets the retention policy for metrics data set on the storage account. - * + * * @return * The {@link RetentionPolicy} set on the storage account. */ @@ -239,17 +263,20 @@ public RetentionPolicy getRetentionPolicy() { /** * Sets the retention policy to use for metrics data on the storage account. - * + * * @param retentionPolicy * The {@link RetentionPolicy} to set on the storage account. + * @return + * A reference to this {@link Metrics} instance. */ - public void setRetentionPolicy(RetentionPolicy retentionPolicy) { + public Metrics setRetentionPolicy(RetentionPolicy retentionPolicy) { this.retentionPolicy = retentionPolicy; + return this; } /** * Gets a flag indicating whether metrics generates summary statistics for called API operations. - * + * * @return * A flag value of true if metrics generates summary statistics for called API operations; * otherwise, false. @@ -262,18 +289,21 @@ public Boolean isIncludeAPIs() { /** * Sets a flag indicating whether metrics should generate summary statistics for called API operations. This * flag is optional if metrics is not enabled. - * + * * @param includeAPIs * Set a flag value of true to generate summary statistics for called API operations; * otherwise, false. + * @return + * A reference to this {@link Metrics} instance. */ - public void setIncludeAPIs(Boolean includeAPIs) { + public Metrics setIncludeAPIs(Boolean includeAPIs) { this.includeAPIs = includeAPIs; + return this; } /** * Gets a flag indicating whether metrics is enabled for the storage account. - * + * * @return * A flag value of true if metrics is enabled for the storage account; otherwise, * false. @@ -285,18 +315,21 @@ public boolean isEnabled() { /** * Sets a flag indicating whether to enable metrics for the storage account. - * + * * @param enabled * Set a flag value of true to enable metrics for the storage account; otherwise, * false. + * @return + * A reference to this {@link Metrics} instance. */ - public void setEnabled(boolean enabled) { + public Metrics setEnabled(boolean enabled) { this.enabled = enabled; + return this; } /** * Gets the version of Storage Analytics configured on the storage account. - * + * * @return * A {@link String} containing the version of Storage Analytics configured on the storage account. */ @@ -307,12 +340,15 @@ public String getVersion() { /** * Sets the version of Storage Analytics configured on the storage account. - * + * * @param version * A {@link String} containing the version of Storage Analytics configured on the storage account. + * @return + * A reference to this {@link Metrics} instance. */ - public void setVersion(String version) { + public Metrics setVersion(String version) { this.version = version; + return this; } } @@ -325,7 +361,7 @@ public static class RetentionPolicy { /** * Gets the number of days that metrics or logging data should be retained, if logging is enabled. - * + * * @return * The number of days to retain logging or metrics data if logging is enabled, or null. */ @@ -338,17 +374,20 @@ public Integer getDays() { * Sets the number of days that metrics or logging data should be retained. The minimum value you can specify is * 1; the largest value is 365 (one year). This value must be specified even if the enabled flag is set * to false. - * + * * @param days * The number of days to retain logging or metrics data. + * @return + * A reference to this {@link RetentionPolicy} instance. */ - public void setDays(Integer days) { + public RetentionPolicy setDays(Integer days) { this.days = days; + return this; } /** * Gets a flag indicating whether a retention policy is enabled. - * + * * @return * A flag value of true if a retention policy is enabled; otherwise, false. */ @@ -359,12 +398,15 @@ public boolean isEnabled() { /** * Sets a flag indicating whether to enable a retention policy. - * + * * @param enabled * Set a flag value of true to enable a retention policy; otherwise, false. + * @return + * A reference to this {@link RetentionPolicy} instance. */ - public void setEnabled(boolean enabled) { + public RetentionPolicy setEnabled(boolean enabled) { this.enabled = enabled; + return this; } } -} +} \ No newline at end of file diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/Configuration.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/Configuration.java index 1664dec987818..e5afff9047a29 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/Configuration.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/Configuration.java @@ -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; @@ -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 properties; Builder builder; @@ -36,17 +44,11 @@ public class Configuration { public Configuration() { this.properties = new HashMap(); this.builder = DefaultBuilder.create(); - init(); } public Configuration(Builder builder) { this.properties = new HashMap(); this.builder = builder; - init(); - } - - private void init() { - setProperty("ClientConfig", builder.build("", ClientConfig.class, properties)); } public static Configuration getInstance() { @@ -102,4 +104,7 @@ public void setProperty(String name, Object value) { properties.put(name, value); } + public Map getProperties() { + return properties; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/ServiceTimeoutException.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/ServiceTimeoutException.java new file mode 100644 index 0000000000000..9c3c5f7fcd134 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/ServiceTimeoutException.java @@ -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); + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ServiceExceptionFactory.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ServiceExceptionFactory.java index 90210ac0e6254..d11feceb6d20b 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ServiceExceptionFactory.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ServiceExceptionFactory.java @@ -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; @@ -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); @@ -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; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/Exports.java index 234581b023fb8..d5b9ddc05ce9f 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/Exports.java @@ -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; @@ -31,8 +32,37 @@ public void register(Registry registry) { @Override public ClientConfig create(String profile, Builder builder, Map 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 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; } @@ -41,7 +71,7 @@ public ClientConfig create(String profile, Builder builder, Map registry.add(new Builder.Factory() { @Override public Client create(String profile, Builder builder, Map properties) { - ClientConfig clientConfig = (ClientConfig) properties.get("ClientConfig"); + ClientConfig clientConfig = builder.build(profile, ClientConfig.class, properties); Client client = Client.create(clientConfig); return client; } @@ -50,11 +80,23 @@ public Client create(String profile, Builder builder, Map proper registry.add(new Builder.Factory() { @Override public HttpURLConnectionClient create(String profile, Builder builder, Map 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 + "."; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClient.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClient.java index 9b7ca1dd32482..f996e5edc6421 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClient.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClient.java @@ -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; @@ -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() { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClientHandler.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClientHandler.java index 20d9046c5358c..83e0822264e45 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClientHandler.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/HttpURLConnectionClientHandler.java @@ -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; @@ -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) { } }; @@ -164,6 +182,7 @@ public String toString() { } } + @Override public ClientResponse handle(final ClientRequest ro) throws ClientHandlerException { try { return doHandle(ro); @@ -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()); @@ -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; @@ -222,6 +245,7 @@ public void onRequestEntitySize(long size) { } } + @Override public OutputStream onGetOutputStream() throws IOException { if (inStreamingMode) return new StreamingOutputStream(urlConnection, clientRequest); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/models/ServiceProperties.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/models/ServiceProperties.java index 9f2715a7fe0d6..a914ac2279975 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/models/ServiceProperties.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/models/ServiceProperties.java @@ -1,11 +1,11 @@ /** * 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 - * + * * 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. @@ -45,7 +45,7 @@ public class ServiceProperties { *

* Note that changes to this value are not reflected in the Queue service properties until they have been set on the * storage account with a call to {@link QueueContract}.setServiceProperties. - * + * * @return * A reference to the {@link Logging} instance in this {@link ServiceProperties} instance. */ @@ -59,12 +59,15 @@ public Logging getLogging() { *

* Note that changes to this value are not reflected in the Queue service properties until they have been set on the * storage account with a call to {@link QueueContract}.setServiceProperties. - * + * * @param logging * The {@link Logging} instance to set in this {@link ServiceProperties} instance. + * @return + * A reference to this {@link ServiceProperties} instance. */ - public void setLogging(Logging logging) { + public ServiceProperties setLogging(Logging logging) { this.logging = logging; + return this; } /** @@ -75,7 +78,7 @@ public void setLogging(Logging logging) { *

* Note that changes to this value are not reflected in the Queue service properties until they have been set on the * storage account with a call to {@link QueueContract}.setServiceProperties. - * + * * @return * A reference to the {@link Metrics} instance in this {@link ServiceProperties} instance. */ @@ -89,12 +92,15 @@ public Metrics getMetrics() { *

* Note that changes to this value are not reflected in the Queue service properties until they have been set on the * storage account with a call to {@link QueueContract}.setServiceProperties. - * + * * @param metrics * The {@link Metrics} instance to set in this {@link ServiceProperties} instance. + * @return + * A reference to this {@link ServiceProperties} instance. */ - public void setMetrics(Metrics metrics) { + public ServiceProperties setMetrics(Metrics metrics) { this.metrics = metrics; + return this; } /** @@ -111,7 +117,7 @@ public static class Logging { /** * Gets a reference to the {@link RetentionPolicy} instance in this {@link Logging} instance. - * + * * @return * A reference to the {@link RetentionPolicy} instance in this {@link Logging} instance. */ @@ -122,19 +128,22 @@ public RetentionPolicy getRetentionPolicy() { /** * Sets the {@link RetentionPolicy} instance in this {@link Logging} instance. - * + * * @param retentionPolicy * The {@link RetentionPolicy} instance to set in this {@link Logging} instance. + * @return + * A reference to this {@link Logging} instance. */ - public void setRetentionPolicy(RetentionPolicy retentionPolicy) { + public Logging setRetentionPolicy(RetentionPolicy retentionPolicy) { this.retentionPolicy = retentionPolicy; + return this; } /** * Gets a flag indicating whether queue write operations are logged. If this value is true then all * requests that write to the Queue service will be logged. These requests include adding a message, updating a * message, setting queue metadata, and creating a queue. - * + * * @return * true if queue write operations are logged, otherwise false. */ @@ -147,19 +156,22 @@ public boolean isWrite() { * Sets a flag indicating whether queue write operations are logged. If this value is true then all * requests that write to the Queue service will be logged. These requests include adding a message, updating a * message, setting queue metadata, and creating a queue. - * + * * @param write * true to enable logging of queue write operations, otherwise false. + * @return + * A reference to this {@link Logging} instance. */ - public void setWrite(boolean write) { + public Logging setWrite(boolean write) { this.write = write; + return this; } /** * Gets a flag indicating whether queue read operations are logged. If this value is true then all * requests that read from the Queue service will be logged. These requests include listing queues, getting * queue metadata, listing messages, and peeking messages. - * + * * @return * true if queue read operations are logged, otherwise false. */ @@ -172,19 +184,22 @@ public boolean isRead() { * Sets a flag indicating whether queue read operations are logged. If this value is true then all * requests that read from the Queue service will be logged. These requests include listing queues, getting * queue metadata, listing messages, and peeking messages. - * + * * @param read * true to enable logging of queue read operations, otherwise false. + * @return + * A reference to this {@link Logging} instance. */ - public void setRead(boolean read) { + public Logging setRead(boolean read) { this.read = read; + return this; } /** * Gets a flag indicating whether queue delete operations are logged. If this value is true then * all requests that delete from the Queue service will be logged. These requests include deleting queues, * deleting messages, and clearing messages. - * + * * @return * true if queue delete operations are logged, otherwise false. */ @@ -197,17 +212,20 @@ public boolean isDelete() { * Sets a flag indicating whether queue delete operations are logged. If this value is true then * all requests that delete from the Queue service will be logged. These requests include deleting queues, * deleting messages, and clearing messages. - * + * * @param delete * true to enable logging of queue delete operations, otherwise false. + * @return + * A reference to this {@link Logging} instance. */ - public void setDelete(boolean delete) { + public Logging setDelete(boolean delete) { this.delete = delete; + return this; } /** * Gets the Storage Analytics version number associated with this {@link Logging} instance. - * + * * @return * A {@link String} containing the Storage Analytics version number. */ @@ -223,12 +241,15 @@ public String getVersion() { *

* See the Storage Analytics * Overview documentation on MSDN for more information. - * + * * @param version * A {@link String} containing the Storage Analytics version number to set. + * @return + * A reference to this {@link Logging} instance. */ - public void setVersion(String version) { + public Logging setVersion(String version) { this.version = version; + return this; } } @@ -245,7 +266,7 @@ public static class Metrics { /** * Gets a reference to the {@link RetentionPolicy} instance in this {@link Metrics} instance. - * + * * @return * A reference to the {@link RetentionPolicy} instance in this {@link Metrics} instance. */ @@ -256,18 +277,21 @@ public RetentionPolicy getRetentionPolicy() { /** * Sets the {@link RetentionPolicy} instance in this {@link Metrics} instance. - * + * * @param retentionPolicy * The {@link RetentionPolicy} instance to set in this {@link Metrics} instance. + * @return + * A reference to this {@link Metrics} instance. */ - public void setRetentionPolicy(RetentionPolicy retentionPolicy) { + public Metrics setRetentionPolicy(RetentionPolicy retentionPolicy) { this.retentionPolicy = retentionPolicy; + return this; } /** * Gets a flag indicating whether metrics should generate summary statistics for called API operations. If this * value is true then all Queue service REST API operations will be included in the metrics. - * + * * @return * true if Queue service REST API operations are included in metrics, otherwise * false. @@ -280,18 +304,21 @@ public Boolean isIncludeAPIs() { /** * Sets a flag indicating whether metrics should generate summary statistics for called API operations. If this * value is true then all Queue service REST API operations will be included in the metrics. - * + * * @param includeAPIs * true to include Queue service REST API operations in metrics, otherwise * false. + * @return + * A reference to this {@link Metrics} instance. */ - public void setIncludeAPIs(Boolean includeAPIs) { + public Metrics setIncludeAPIs(Boolean includeAPIs) { this.includeAPIs = includeAPIs; + return this; } /** * Gets a flag indicating whether metrics is enabled for the Queue storage service. - * + * * @return * A flag indicating whether metrics is enabled for the Queue storage service. */ @@ -302,17 +329,20 @@ public boolean isEnabled() { /** * Sets a flag indicating whether to enable metrics for the Queue storage service. - * + * * @param enabled * true to enable metrics for the Queue storage service, otherwise false. + * @return + * A reference to this {@link Metrics} instance. */ - public void setEnabled(boolean enabled) { + public Metrics setEnabled(boolean enabled) { this.enabled = enabled; + return this; } /** * Gets the Storage Analytics version number associated with this {@link Metrics} instance. - * + * * @return * A {@link String} containing the Storage Analytics version number. */ @@ -327,12 +357,15 @@ public String getVersion() { *

* See the Storage Analytics * Overview documentation on MSDN for more information. - * + * * @param version * A {@link String} containing the Storage Analytics version number to set. + * @return + * A reference to this {@link Metrics} instance. */ - public void setVersion(String version) { + public Metrics setVersion(String version) { this.version = version; + return this; } } @@ -348,7 +381,7 @@ public static class RetentionPolicy { /** * Gets the number of days that metrics or logging data should be retained. All data older than this value will * be deleted. The value may be null if a retention policy is not enabled. - * + * * @return * The number of days that metrics or logging data should be retained. */ @@ -361,17 +394,20 @@ public Integer getDays() { * Sets the number of days that metrics or logging data should be retained. All data older than this value will * be deleted. The value must be in the range from 1 to 365. This value must be set if a retention policy is * enabled, but is not required if a retention policy is not enabled. - * + * * @param days * The number of days that metrics or logging data should be retained. + * @return + * A reference to this {@link RetentionPolicy} instance. */ - public void setDays(Integer days) { + public RetentionPolicy setDays(Integer days) { this.days = days; + return this; } /** * Gets a flag indicating whether a retention policy is enabled for the storage service. - * + * * @return * true if data retention is enabled, otherwise false. */ @@ -382,12 +418,15 @@ public boolean isEnabled() { /** * Sets a flag indicating whether a retention policy is enabled for the storage service. - * + * * @param enabled * Set true to enable data retention. + * @return + * A reference to this {@link RetentionPolicy} instance. */ - public void setEnabled(boolean enabled) { + public RetentionPolicy setEnabled(boolean enabled) { this.enabled = enabled; + return this; } } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/RuleInfo.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/RuleInfo.java index 35e30ae716508..7889fdc900a35 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/RuleInfo.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/RuleInfo.java @@ -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.serviceBus.models; @@ -149,12 +149,14 @@ public RuleInfo withSqlExpressionFilter(String sqlExpression) { public RuleInfo withTrueFilter() { TrueFilter filter = new TrueFilter(); filter.setCompatibilityLevel(20); + filter.setSqlExpression("1=1"); return setFilter(filter); } public RuleInfo withFalseFilter() { FalseFilter filter = new FalseFilter(); filter.setCompatibilityLevel(20); + filter.setSqlExpression("1=0"); return setFilter(filter); } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/BlobServiceIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/BlobServiceIntegrationTest.java index 28e5d990ec7ce..d1fbb29871d6b 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/BlobServiceIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/BlobServiceIntegrationTest.java @@ -91,6 +91,7 @@ public class BlobServiceIntegrationTest extends IntegrationTestBase { private static String TEST_CONTAINER_FOR_LISTING; private static String[] creatableContainers; private static String[] testContainers; + private static boolean createdRoot; @BeforeClass public static void setup() throws Exception { @@ -120,6 +121,14 @@ public static void setup() throws Exception { BlobContract service = BlobService.create(config); createContainers(service, testContainersPrefix, testContainers); + + try { + service.createContainer("$root"); + createdRoot = true; + } + catch (ServiceException e) { + e.printStackTrace(); + } } @AfterClass @@ -129,6 +138,17 @@ public static void cleanup() throws Exception { deleteContainers(service, testContainersPrefix, testContainers); deleteContainers(service, createableContainersPrefix, creatableContainers); + + // If container was created, delete it + if (createdRoot) { + try { + service.deleteContainer("$root"); + createdRoot = false; + } + catch (ServiceException e) { + e.printStackTrace(); + } + } } private static void createContainers(BlobContract service, String prefix, String[] list) throws Exception { @@ -464,20 +484,6 @@ public void workingWithRootContainersWorks() throws Exception { Configuration config = createConfiguration(); BlobContract service = BlobService.create(config); - // - // Ensure root container exists - // - ServiceException error = null; - try { - service.createContainer("$root"); - } - catch (ServiceException e) { - error = e; - } - - // Assert - assertTrue(error == null || error.getHttpStatusCode() == 409); - // // Work with root container explicitly ("$root") // @@ -518,11 +524,6 @@ public void workingWithRootContainersWorks() throws Exception { // Act service.deleteBlob("", BLOB_FOR_ROOT_CONTAINER); } - - // If container was created, delete it - if (error == null) { - service.deleteContainer("$root"); - } } @Test @@ -650,6 +651,31 @@ public void listBlobsWithDelimiterWorks() throws Exception { assertEquals(0, results6.getBlobPrefixes().size()); } + @Test + public void listBlockBlobWithNoCommittedBlocksWorks() throws Exception { + Configuration config = createConfiguration(); + BlobContract service = BlobService.create(config); + + String container = TEST_CONTAINER_FOR_BLOBS; + String blob = "listBlockBlobWithNoCommittedBlocksWorks"; + + service.createBlockBlob(container, blob, null); + service.createBlobBlock(container, blob, "01", new ByteArrayInputStream(new byte[] { 0x00 })); + service.deleteBlob(container, blob); + + try { + // Note: This next two lines should give a 404, because the blob no longer + // exists. However, the service sometimes allow this improper access, so + // the SDK has to handle the situation gracefully. + service.createBlobBlock(container, blob, "01", new ByteArrayInputStream(new byte[] { 0x00 })); + ListBlobBlocksResult result = service.listBlobBlocks(container, blob); + assertEquals(0, result.getCommittedBlocks().size()); + } + catch (ServiceException ex) { + assertEquals(404, ex.getHttpStatusCode()); + } + } + @Test public void createPageBlobWorks() throws Exception { // Arrange @@ -1321,14 +1347,14 @@ public void getBlobPropertiesIfNotModified() throws Exception { // Arrange Configuration config = createConfiguration(); BlobContract service = BlobService.create(config); - Date currentLastModifiedDate = new Date(); // Act String container = TEST_CONTAINER_FOR_BLOBS; String blob = "test"; - service.createPageBlob(container, blob, 4096); - GetBlobPropertiesResult result = service.getBlobProperties(container, blob, new GetBlobPropertiesOptions() - .setAccessCondition(AccessCondition.ifModifiedSince(currentLastModifiedDate))); + CreateBlobResult result = service.createPageBlob(container, blob, 4096); + Date tenSecondsFromNow = new Date(result.getLastModified().getTime() + 10000); + service.getBlobProperties(container, blob, + new GetBlobPropertiesOptions().setAccessCondition(AccessCondition.ifModifiedSince(tenSecondsFromNow))); // Assert assertTrue(false); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/BlobTestBase.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/BlobTestBase.java index bd0671e3ece19..938db64c06d4a 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/BlobTestBase.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/BlobTestBase.java @@ -51,7 +51,11 @@ public static void setup() throws URISyntaxException, StorageException, InvalidK httpAcc = CloudStorageAccount.getDevelopmentStorageAccount(); } else { - httpAcc = CloudStorageAccount.parse(CLOUD_ACCOUNT_HTTP); + String cloudAccount = CLOUD_ACCOUNT_HTTP; + cloudAccount = cloudAccount.replace("[ACCOUNT NAME]", System.getenv("blob.accountName")); + cloudAccount = cloudAccount.replace("[ACCOUNT KEY]", System.getenv("blob.accountKey")); + + httpAcc = CloudStorageAccount.parse(cloudAccount); } bClient = httpAcc.createCloudBlobClient(); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/QueueTestBase.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/QueueTestBase.java index feb5b1ceb4a10..8144378d8577b 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/QueueTestBase.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/QueueTestBase.java @@ -52,7 +52,11 @@ public static void setup() throws URISyntaxException, StorageException, InvalidK httpAcc = CloudStorageAccount.getDevelopmentStorageAccount(); } else { - httpAcc = CloudStorageAccount.parse(CLOUD_ACCOUNT_HTTP); + String cloudAccount = CLOUD_ACCOUNT_HTTP; + cloudAccount = cloudAccount.replace("[ACCOUNT NAME]", System.getenv("queue.accountName")); + cloudAccount = cloudAccount.replace("[ACCOUNT KEY]", System.getenv("queue.accountKey")); + + httpAcc = CloudStorageAccount.parse(cloudAccount); } qClient = httpAcc.createCloudQueueClient(); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/TableServiceIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/TableServiceIntegrationTest.java index 4651f71acf0d6..74fdd4d911499 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/TableServiceIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/TableServiceIntegrationTest.java @@ -29,6 +29,7 @@ import com.microsoft.windowsazure.services.core.ExponentialRetryPolicy; import com.microsoft.windowsazure.services.core.RetryPolicyFilter; import com.microsoft.windowsazure.services.core.ServiceException; +import com.microsoft.windowsazure.services.core.ServiceTimeoutException; import com.microsoft.windowsazure.services.table.models.BatchOperations; import com.microsoft.windowsazure.services.table.models.BatchResult; import com.microsoft.windowsazure.services.table.models.BatchResult.DeleteEntity; @@ -1139,4 +1140,84 @@ public void batchNegativeWorks() throws Exception { assertEquals("Second result status code", 412, error.getError().getHttpStatusCode()); assertNull("Third result should be null", result.getEntries().get(2)); } + + @Test + public void settingTimeoutWorks() throws Exception { + Configuration config = createConfiguration(); + + // Set timeout to very short to force failure + config.setProperty(Configuration.PROPERTY_CONNECT_TIMEOUT, new Integer(1)); + config.setProperty(Configuration.PROPERTY_READ_TIMEOUT, new Integer(1)); + + TableContract service = TableService.create(config); + + try { + service.queryTables(); + fail("Exception should have been thrown"); + } + catch (ServiceTimeoutException ex) { + // No need to assert, test is if correct assertion type is thrown. + } + catch (Exception ex) { + fail("unexpected exception was thrown"); + } + finally { + // Clean up timeouts, they interfere with other tests otherwise + config.getProperties().remove(Configuration.PROPERTY_CONNECT_TIMEOUT); + config.getProperties().remove(Configuration.PROPERTY_READ_TIMEOUT); + } + } + + @Test + public void settingTimeoutFromStringWorks() throws Exception { + Configuration config = createConfiguration(); + + // Set timeout to very short to force failure + config.setProperty(Configuration.PROPERTY_CONNECT_TIMEOUT, "1"); + config.setProperty(Configuration.PROPERTY_READ_TIMEOUT, "1"); + + TableContract service = TableService.create(config); + + try { + service.queryTables(); + fail("Exception should have been thrown"); + } + catch (ServiceTimeoutException ex) { + // No need to assert, test is if correct assertion type is thrown. + } + catch (Exception ex) { + fail("unexpected exception was thrown"); + } + finally { + // Clean up timeouts, they interfere with other tests otherwise + config.getProperties().remove(Configuration.PROPERTY_CONNECT_TIMEOUT); + config.getProperties().remove(Configuration.PROPERTY_READ_TIMEOUT); + } + } + + @Test + public void settingTimeoutPrefixedFromConfigWorks() throws Exception { + Configuration config = createConfiguration(); + + TableContract service = TableService.create("testprefix", config); + + try { + service.queryTables(); + fail("Exception should have been thrown"); + } + catch (ServiceTimeoutException ex) { + // No need to assert, test is if correct assertion type is thrown. + } + catch (Exception ex) { + fail("unexpected exception was thrown"); + } + } + + @Test + public void prefixedTimeoutsGetLoaded() throws Exception { + Configuration config = createConfiguration(); + + assertEquals("3", config.getProperty("testprefix." + Configuration.PROPERTY_CONNECT_TIMEOUT)); + assertEquals("7", config.getProperty("testprefix." + Configuration.PROPERTY_READ_TIMEOUT)); + } } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableTestBase.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableTestBase.java index d235ed326cc69..7ba57b75322c8 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableTestBase.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableTestBase.java @@ -577,7 +577,11 @@ public static void setup() throws URISyntaxException, StorageException, InvalidK httpAcc = CloudStorageAccount.getDevelopmentStorageAccount(); } else { - httpAcc = CloudStorageAccount.parse(CLOUD_ACCOUNT_HTTP); + String cloudAccount = CLOUD_ACCOUNT_HTTP; + cloudAccount = cloudAccount.replace("[ACCOUNT NAME]", System.getenv("table.accountName")); + cloudAccount = cloudAccount.replace("[ACCOUNT KEY]", System.getenv("table.accountKey")); + + httpAcc = CloudStorageAccount.parse(cloudAccount); } bClient = httpAcc.createCloudBlobClient(); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/utils/ServiceExceptionFactoryTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/utils/ServiceExceptionFactoryTest.java index 3cc8639eb849c..54c5b84aab75a 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/utils/ServiceExceptionFactoryTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/utils/ServiceExceptionFactoryTest.java @@ -2,25 +2,27 @@ * 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.utils; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; +import java.net.SocketTimeoutException; import org.junit.Test; import com.microsoft.windowsazure.services.core.ServiceException; +import com.microsoft.windowsazure.services.core.ServiceTimeoutException; import com.microsoft.windowsazure.services.core.utils.ServiceExceptionFactory; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientResponse; @@ -31,11 +33,11 @@ public class ServiceExceptionFactoryTest { public void serviceNameAndMessageAndCauseAppearInException() { // Arrange ClientResponse response = new ClientResponse(404, null, new ByteArrayInputStream(new byte[0]), null); - UniformInterfaceException cause = new UniformInterfaceException( - response); + UniformInterfaceException cause = new UniformInterfaceException(response); // Act - ServiceException exception = ServiceExceptionFactory.process("testing", new ServiceException("this is a test", cause)); + ServiceException exception = ServiceExceptionFactory.process("testing", new ServiceException("this is a test", + cause)); // Assert assertNotNull(exception); @@ -48,11 +50,11 @@ public void serviceNameAndMessageAndCauseAppearInException() { public void httpStatusCodeAndReasonPhraseAppearInException() { // Arrange ClientResponse response = new ClientResponse(404, null, new ByteArrayInputStream(new byte[0]), null); - UniformInterfaceException cause = new UniformInterfaceException( - response); + UniformInterfaceException cause = new UniformInterfaceException(response); // Act - ServiceException exception = ServiceExceptionFactory.process("testing", new ServiceException("this is a test", cause)); + ServiceException exception = ServiceExceptionFactory.process("testing", new ServiceException("this is a test", + cause)); // Assert assertNotNull(exception); @@ -65,7 +67,8 @@ public void informationWillPassUpIfServiceExceptionIsRootCauseOfClientHandlerExc // Arrange ClientResponse response = new ClientResponse(503, null, new ByteArrayInputStream(new byte[0]), null); UniformInterfaceException rootCause = new UniformInterfaceException(response); - ServiceException originalDescription = ServiceExceptionFactory.process("underlying", new ServiceException(rootCause)); + ServiceException originalDescription = ServiceExceptionFactory.process("underlying", new ServiceException( + rootCause)); ClientHandlerException wrappingException = new ClientHandlerException(originalDescription); // Act @@ -76,4 +79,17 @@ public void informationWillPassUpIfServiceExceptionIsRootCauseOfClientHandlerExc assertEquals("underlying", exception.getServiceName()); } + @Test + public void socketTimeoutWillPassUpIfInsideClientHandlerException() { + String expectedMessage = "connect timeout"; + SocketTimeoutException rootCause = new SocketTimeoutException(expectedMessage); + ClientHandlerException wrappingException = new ClientHandlerException(rootCause); + + ServiceException exception = ServiceExceptionFactory + .process("testing", new ServiceException(wrappingException)); + + assertSame(ServiceTimeoutException.class, exception.getClass()); + assertEquals(expectedMessage, exception.getMessage()); + assertEquals("testing", exception.getServiceName()); + } } diff --git a/microsoft-azure-api/src/test/resources/META-INF/com.microsoft.windowsazure.properties b/microsoft-azure-api/src/test/resources/META-INF/com.microsoft.windowsazure.properties index 7739acd3e7333..5685b680eab64 100644 --- a/microsoft-azure-api/src/test/resources/META-INF/com.microsoft.windowsazure.properties +++ b/microsoft-azure-api/src/test/resources/META-INF/com.microsoft.windowsazure.properties @@ -10,4 +10,6 @@ queue.accountKey=%QUEUE_ACCOUNTKEY% queue.uri=http://%QUEUE_ACCOUNTNAME%.queue.core.windows.net table.accountName=%TABLE_ACCOUNTNAME% table.accountKey=%TABLE_ACCOUNTKEY% -table.uri=http://%TABLE_ACCOUNTNAME%.table.core.windows.net \ No newline at end of file +table.uri=http://%TABLE_ACCOUNTNAME%.table.core.windows.net +testprefix.com.microsoft.windowsazure.services.core.Configuration.connectTimeout=3 +testprefix.com.microsoft.windowsazure.services.core.Configuration.readTimeout=7