diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/BlobContract.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/BlobContract.java index b3dbc962f0f5a..367d3b311d935 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/BlobContract.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/BlobContract.java @@ -24,10 +24,12 @@ import com.microsoft.windowsazure.services.blob.models.CommitBlobBlocksOptions; import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.CopyBlobOptions; +import com.microsoft.windowsazure.services.blob.models.CopyBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobBlockOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesResult; +import com.microsoft.windowsazure.services.blob.models.CreateBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotResult; import com.microsoft.windowsazure.services.blob.models.CreateContainerOptions; @@ -429,7 +431,7 @@ void setContainerMetadata(String container, HashMap<String, String> metadata, Se * @throws ServiceException * if an error occurs accessing the storage service. */ - void createPageBlob(String container, String blob, long length) throws ServiceException; + CreateBlobResult createPageBlob(String container, String blob, long length) throws ServiceException; /** * Creates a page blob of the specified maximum length, using the specified options. @@ -457,7 +459,8 @@ void setContainerMetadata(String container, HashMap<String, String> metadata, Se * @throws ServiceException * if an error occurs accessing the storage service. */ - void createPageBlob(String container, String blob, long length, CreateBlobOptions options) throws ServiceException; + CreateBlobResult createPageBlob(String container, String blob, long length, CreateBlobOptions options) + throws ServiceException; /** * Creates a block blob from a content stream. @@ -473,7 +476,7 @@ void setContainerMetadata(String container, HashMap<String, String> metadata, Se * @throws ServiceException * if an error occurs accessing the storage service. */ - void createBlockBlob(String container, String blob, InputStream contentStream) throws ServiceException; + CreateBlobResult createBlockBlob(String container, String blob, InputStream contentStream) throws ServiceException; /** * Creates a block blob from a content stream, using the specified options. @@ -495,7 +498,7 @@ void setContainerMetadata(String container, HashMap<String, String> metadata, Se * @throws ServiceException * if an error occurs accessing the storage service. */ - void createBlockBlob(String container, String blob, InputStream contentStream, CreateBlobOptions options) + CreateBlobResult createBlockBlob(String container, String blob, InputStream contentStream, CreateBlobOptions options) throws ServiceException; /** @@ -1214,8 +1217,8 @@ CreateBlobSnapshotResult createBlobSnapshot(String container, String blob, Creat * @throws ServiceException * if an error occurs accessing the storage service. */ - void copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, String sourceBlob) - throws ServiceException; + CopyBlobResult copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, + String sourceBlob) throws ServiceException; /** * Copies a source blob to a destination within the storage account, using the specified options. @@ -1293,8 +1296,8 @@ void copyBlob(String destinationContainer, String destinationBlob, String source * @throws ServiceException * if an error occurs accessing the storage service. */ - void copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, String sourceBlob, - CopyBlobOptions options) throws ServiceException; + CopyBlobResult copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, + String sourceBlob, CopyBlobOptions options) throws ServiceException; /** * Gets a new lease on a blob. diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobExceptionProcessor.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobExceptionProcessor.java index fea8798af1097..157dbd9737cb8 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobExceptionProcessor.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobExceptionProcessor.java @@ -30,10 +30,12 @@ import com.microsoft.windowsazure.services.blob.models.CommitBlobBlocksOptions; import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.CopyBlobOptions; +import com.microsoft.windowsazure.services.blob.models.CopyBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobBlockOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesResult; +import com.microsoft.windowsazure.services.blob.models.CreateBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotResult; import com.microsoft.windowsazure.services.blob.models.CreateContainerOptions; @@ -383,9 +385,9 @@ public ListBlobsResult listBlobs(String container, ListBlobsOptions options) thr } @Override - public void createPageBlob(String container, String blob, long length) throws ServiceException { + public CreateBlobResult createPageBlob(String container, String blob, long length) throws ServiceException { try { - service.createPageBlob(container, blob, length); + return service.createPageBlob(container, blob, length); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); @@ -396,10 +398,10 @@ public void createPageBlob(String container, String blob, long length) throws Se } @Override - public void createPageBlob(String container, String blob, long length, CreateBlobOptions options) + public CreateBlobResult createPageBlob(String container, String blob, long length, CreateBlobOptions options) throws ServiceException { try { - service.createPageBlob(container, blob, length, options); + return service.createPageBlob(container, blob, length, options); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); @@ -410,9 +412,10 @@ public void createPageBlob(String container, String blob, long length, CreateBlo } @Override - public void createBlockBlob(String container, String blob, InputStream contentStream) throws ServiceException { + public CreateBlobResult createBlockBlob(String container, String blob, InputStream contentStream) + throws ServiceException { try { - service.createBlockBlob(container, blob, contentStream); + return service.createBlockBlob(container, blob, contentStream); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); @@ -423,10 +426,10 @@ public void createBlockBlob(String container, String blob, InputStream contentSt } @Override - public void createBlockBlob(String container, String blob, InputStream contentStream, CreateBlobOptions options) - throws ServiceException { + public CreateBlobResult createBlockBlob(String container, String blob, InputStream contentStream, + CreateBlobOptions options) throws ServiceException { try { - service.createBlockBlob(container, blob, contentStream, options); + return service.createBlockBlob(container, blob, contentStream, options); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); @@ -776,10 +779,10 @@ public CreateBlobSnapshotResult createBlobSnapshot(String container, String blob } @Override - public void copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, String sourceBlob) - throws ServiceException { + public CopyBlobResult copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, + String sourceBlob) throws ServiceException { try { - service.copyBlob(destinationContainer, destinationBlob, sourceContainer, sourceBlob); + return service.copyBlob(destinationContainer, destinationBlob, sourceContainer, sourceBlob); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); @@ -790,10 +793,10 @@ public void copyBlob(String destinationContainer, String destinationBlob, String } @Override - public void copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, + public CopyBlobResult copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, String sourceBlob, CopyBlobOptions options) throws ServiceException { try { - service.copyBlob(destinationContainer, destinationBlob, sourceContainer, sourceBlob, options); + return service.copyBlob(destinationContainer, destinationBlob, sourceContainer, sourceBlob, options); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); 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 00aea0a3efbd5..1366704cf2d81 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 @@ -34,10 +34,12 @@ import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.ContainerACL.PublicAccessType; import com.microsoft.windowsazure.services.blob.models.CopyBlobOptions; +import com.microsoft.windowsazure.services.blob.models.CopyBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobBlockOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesResult; +import com.microsoft.windowsazure.services.blob.models.CreateBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotResult; import com.microsoft.windowsazure.services.blob.models.CreateContainerOptions; @@ -146,12 +148,12 @@ private Builder addOptionalRangeHeader(Builder builder, Long rangeStart, Long ra return PipelineHelpers.addOptionalRangeHeader(builder, rangeStart, rangeEnd); } - private Builder addOptionalAccessContitionHeader(Builder builder, AccessCondition accessCondition) { - return PipelineHelpers.addOptionalAccessContitionHeader(builder, accessCondition); + private Builder addOptionalAccessConditionHeader(Builder builder, AccessCondition accessCondition) { + return PipelineHelpers.addOptionalAccessConditionHeader(builder, accessCondition); } - private Builder addOptionalSourceAccessContitionHeader(Builder builder, AccessCondition accessCondition) { - return PipelineHelpers.addOptionalSourceAccessContitionHeader(builder, accessCondition); + private Builder addOptionalSourceAccessConditionHeader(Builder builder, AccessCondition accessCondition) { + return PipelineHelpers.addOptionalSourceAccessConditionHeader(builder, accessCondition); } private HashMap<String, String> getMetadataFromHeaders(ClientResponse response) { @@ -191,7 +193,7 @@ private Builder addPutBlobHeaders(CreateBlobOptions options, Builder builder) { builder = addOptionalHeader(builder, "x-ms-blob-cache-control", options.getBlobCacheControl()); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); builder = addOptionalMetadataHeader(builder, options.getMetadata()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); return builder; } @@ -322,7 +324,7 @@ public void deleteContainer(String container, DeleteContainerOptions options) th WebResource webResource = getResource(options).path(container).queryParam("resType", "container"); WebResource.Builder builder = webResource.header("x-ms-version", API_VERSION); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); builder.delete(); } @@ -443,7 +445,7 @@ public void setContainerMetadata(String container, HashMap<String, String> metad WebResource.Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalMetadataHeader(builder, metadata); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); builder.put(); } @@ -488,12 +490,12 @@ public ListBlobsResult listBlobs(String container, ListBlobsOptions options) thr } @Override - public void createPageBlob(String container, String blob, long length) throws ServiceException { - createPageBlob(container, blob, length, new CreateBlobOptions()); + public CreateBlobResult createPageBlob(String container, String blob, long length) throws ServiceException { + return createPageBlob(container, blob, length, new CreateBlobOptions()); } @Override - public void createPageBlob(String container, String blob, long length, CreateBlobOptions options) + public CreateBlobResult createPageBlob(String container, String blob, long length, CreateBlobOptions options) throws ServiceException { String path = createPathFromContainer(container); WebResource webResource = getResource(options).path(path).path(blob); @@ -505,17 +507,25 @@ public void createPageBlob(String container, String blob, long length, CreateBlo builder = addOptionalHeader(builder, "x-ms-blob-sequence-number", options.getSequenceNumber()); builder = addPutBlobHeaders(options, builder); - builder.put(); + ClientResponse clientResponse = builder.put(ClientResponse.class); + ThrowIfError(clientResponse); + + CreateBlobResult createBlobResult = new CreateBlobResult(); + createBlobResult.setEtag(clientResponse.getHeaders().getFirst("ETag")); + createBlobResult.setLastModified(dateMapper.parse(clientResponse.getHeaders().getFirst("Last-Modified"))); + + return createBlobResult; } @Override - public void createBlockBlob(String container, String blob, InputStream contentStream) throws ServiceException { - createBlockBlob(container, blob, contentStream, new CreateBlobOptions()); + public CreateBlobResult createBlockBlob(String container, String blob, InputStream contentStream) + throws ServiceException { + return createBlockBlob(container, blob, contentStream, new CreateBlobOptions()); } @Override - public void createBlockBlob(String container, String blob, InputStream contentStream, CreateBlobOptions options) - throws ServiceException { + public CreateBlobResult createBlockBlob(String container, String blob, InputStream contentStream, + CreateBlobOptions options) throws ServiceException { String path = createPathFromContainer(container); System.out.println(path); WebResource webResource = getResource(options).path(path).path(blob); @@ -526,7 +536,14 @@ public void createBlockBlob(String container, String blob, InputStream contentSt builder = addPutBlobHeaders(options, builder); Object contentObject = (contentStream == null ? new byte[0] : contentStream); - builder.put(contentObject); + ClientResponse clientResponse = builder.put(ClientResponse.class, contentObject); + ThrowIfError(clientResponse); + + CreateBlobResult createBlobResult = new CreateBlobResult(); + createBlobResult.setEtag(clientResponse.getHeaders().getFirst("ETag")); + createBlobResult.setLastModified(dateMapper.parse(clientResponse.getHeaders().getFirst("Last-Modified"))); + + return createBlobResult; } @Override @@ -543,10 +560,10 @@ public GetBlobPropertiesResult getBlobProperties(String container, String blob, Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.method("HEAD", ClientResponse.class); - ThrowIfError(response); + ThrowIfNotSuccess(response); return getBlobPropertiesResultFromResponse(response); } @@ -565,7 +582,7 @@ public GetBlobMetadataResult getBlobMetadata(String container, String blob, GetB Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.get(ClientResponse.class); ThrowIfError(response); @@ -594,7 +611,7 @@ public SetBlobPropertiesResult setBlobProperties(String container, String blob, builder = addOptionalHeader(builder, "x-ms-sequence-number-action", options.getSequenceNumberAction()); builder = addOptionalHeader(builder, "x-ms-blob-sequence-number", options.getSequenceNumber()); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.put(ClientResponse.class); ThrowIfError(response); @@ -625,7 +642,7 @@ public SetBlobMetadataResult setBlobMetadata(String container, String blob, Hash WebResource.Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); builder = addOptionalMetadataHeader(builder, metadata); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.put(ClientResponse.class); ThrowIfError(response); @@ -650,7 +667,10 @@ public GetBlobResult getBlob(String container, String blob, GetBlobOptions optio Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); builder = addOptionalRangeHeader(builder, options.getRangeStart(), options.getRangeEnd()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); + if (options.isComputeRangeMD5()) { + builder = addOptionalHeader(builder, "x-ms-range-get-content-md5", "true"); + } ClientResponse response = builder.get(ClientResponse.class); ThrowIfNotSuccess(response); @@ -680,7 +700,7 @@ public void deleteBlob(String container, String blob, DeleteBlobOptions options) builder = addOptionalHeader(builder, "x-ms-delete-snapshots", options.getDeleteSnaphotsOnly() ? "only" : "include"); } - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); builder.delete(); } @@ -699,7 +719,7 @@ public CreateBlobSnapshotResult createBlobSnapshot(String container, String blob Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); builder = addOptionalMetadataHeader(builder, options.getMetadata()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.put(ClientResponse.class); ThrowIfError(response); @@ -713,13 +733,13 @@ public CreateBlobSnapshotResult createBlobSnapshot(String container, String blob } @Override - public void copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, String sourceBlob) - throws ServiceException { - copyBlob(destinationContainer, destinationBlob, sourceContainer, sourceBlob, new CopyBlobOptions()); + public CopyBlobResult copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, + String sourceBlob) throws ServiceException { + return copyBlob(destinationContainer, destinationBlob, sourceContainer, sourceBlob, new CopyBlobOptions()); } @Override - public void copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, + public CopyBlobResult copyBlob(String destinationContainer, String destinationBlob, String sourceContainer, String sourceBlob, CopyBlobOptions options) { String path = createPathFromContainer(destinationContainer); WebResource webResource = getResource(options).path(path).path(destinationBlob); @@ -730,10 +750,17 @@ public void copyBlob(String destinationContainer, String destinationBlob, String builder = addOptionalHeader(builder, "x-ms-copy-source", getCopyBlobSourceName(sourceContainer, sourceBlob, options)); builder = addOptionalMetadataHeader(builder, options.getMetadata()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); - builder = addOptionalSourceAccessContitionHeader(builder, options.getSourceAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); + builder = addOptionalSourceAccessConditionHeader(builder, options.getSourceAccessCondition()); - builder.put(); + ClientResponse clientResponse = builder.put(ClientResponse.class); + ThrowIfError(clientResponse); + + CopyBlobResult copyBlobResult = new CopyBlobResult(); + copyBlobResult.setEtag(clientResponse.getHeaders().getFirst("ETag")); + copyBlobResult.setLastModified(dateMapper.parse(clientResponse.getHeaders().getFirst("Last-Modified"))); + + return copyBlobResult; } @Override @@ -788,7 +815,7 @@ private AcquireLeaseResult putLeaseImpl(String leaseAction, String container, St Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalHeader(builder, "x-ms-lease-id", leaseId); builder = addOptionalHeader(builder, "x-ms-lease-action", leaseAction); - builder = addOptionalAccessContitionHeader(builder, accessCondition); + builder = addOptionalAccessConditionHeader(builder, accessCondition); // Note: Add content type here to enable proper HMAC signing ClientResponse response = builder.put(ClientResponse.class); @@ -834,7 +861,7 @@ private CreateBlobPagesResult updatePageBlobPagesImpl(String action, String cont builder = addOptionalHeader(builder, "Content-MD5", options.getContentMD5()); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); builder = addOptionalHeader(builder, "x-ms-page-write", action); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.put(ClientResponse.class, contentStream); ThrowIfError(response); @@ -862,7 +889,7 @@ public ListBlobRegionsResult listBlobRegions(String container, String blob, List Builder builder = webResource.header("x-ms-version", API_VERSION); builder = addOptionalRangeHeader(builder, options.getRangeStart(), options.getRangeEnd()); builder = addOptionalHeader(builder, "x-ms-lease-id", options.getLeaseId()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); ClientResponse response = builder.get(ClientResponse.class); ThrowIfError(response); @@ -914,7 +941,7 @@ public void commitBlobBlocks(String container, String blob, BlockList blockList, builder = addOptionalHeader(builder, "x-ms-blob-content-language", options.getBlobContentLanguage()); builder = addOptionalHeader(builder, "x-ms-blob-content-md5", options.getBlobContentMD5()); builder = addOptionalMetadataHeader(builder, options.getMetadata()); - builder = addOptionalAccessContitionHeader(builder, options.getAccessCondition()); + builder = addOptionalAccessConditionHeader(builder, options.getAccessCondition()); builder.put(blockList); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CopyBlobResult.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CopyBlobResult.java new file mode 100644 index 0000000000000..d8dd1b665847d --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CopyBlobResult.java @@ -0,0 +1,80 @@ +/** + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.windowsazure.services.blob.models; + +import java.util.Date; + +import com.microsoft.windowsazure.services.blob.BlobContract; + +/** + * A wrapper class for the response returned from a Blob Service REST API Copy Blob operation. This is returned by calls + * to implementations of {@link BlobContract#copyBlob(String, String, String, String, CopyBlobOptions)}. + * <p> + * See the <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd894037.aspx">Copy Blob</a> documentation on + * MSDN for details of the underlying Blob Service REST API operation. + */ +public class CopyBlobResult { + private String etag; + private Date lastModified; + + /** + * Gets the ETag of the blob. + * + * @return + * A {@link String} containing the server-assigned ETag value for the copy blob. + */ + public String getEtag() { + return etag; + } + + /** + * Sets the ETag of the blob from the <code>ETag</code> header returned in the + * response. + * <p> + * This method is invoked by the API to set the value from the Blob Service REST API operation response returned by + * the server. + * + * @param etag + * A {@link String} containing the server-assigned ETag value for the blob. + */ + public void setEtag(String etag) { + this.etag = etag; + } + + /** + * Gets the last modified time of the blob. + * <p> + * + * @return + * A {@link java.util.Date} containing the last modified time of the blob. + */ + public Date getLastModified() { + return lastModified; + } + + /** + * Sets the last modified time of the blob from the <code>Last-Modified</code> header + * returned in the response. + * <p> + * This method is invoked by the API to set the value from the Blob Service REST API operation response returned by + * the server. + * + * @param lastModified + * A {@link java.util.Date} containing the last modified time of the blob. + */ + public void setLastModified(Date lastModified) { + this.lastModified = lastModified; + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobResult.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobResult.java new file mode 100644 index 0000000000000..4ab963e269006 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobResult.java @@ -0,0 +1,80 @@ +/** + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.windowsazure.services.blob.models; + +import java.util.Date; + +import com.microsoft.windowsazure.services.blob.BlobContract; + +/** + * A wrapper class for the response returned from a Blob Service REST API Create Blob operation. This is returned by + * calls to implementations of {@link BlobContract#createPageBlob(String, String, long, CreateBlobOptions)} and + * {@link BlobContract#createBlockBlob(String, String, long, CreateBlobOptions)}. + * <p> + * See the <a href="http://msdn.microsoft.com/en-us/library/windowsazure/dd179451.aspx">Put Blob</a> documentation on + * MSDN for details of the underlying Blob Service REST API operation. + */ +public class CreateBlobResult { + private String etag; + private Date lastModified; + + /** + * Gets the ETag of the blob. + * + * @return + * A {@link String} containing the server-assigned ETag value for the snapshot. + */ + public String getEtag() { + return etag; + } + + /** + * Sets the ETag of the snapshot from the <code>ETag</code> header returned in the + * response. + * <p> + * This method is invoked by the API to set the value from the Blob Service REST API operation response returned by + * the server. + * + * @param etag + * A {@link String} containing the server-assigned ETag value for the blob. + */ + public void setEtag(String etag) { + this.etag = etag; + } + + /** + * Gets the last modified time of the snapshot. + * + * @return + * A {@link java.util.Date} containing the last modified time of the blob. + */ + public Date getLastModified() { + return lastModified; + } + + /** + * Reserved for internal use. Sets the last modified time of the snapshot from the <code>Last-Modified</code> header + * returned in the response. + * <p> + * This method is invoked by the API to set the value from the Blob Service REST API operation response returned by + * the server. + * + * @param lastModified + * A {@link java.util.Date} containing the last modified time of the snapshot. + */ + public void setLastModified(Date lastModified) { + this.lastModified = lastModified; + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpers.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpers.java index 21b95538f6e11..7f117707aafcc 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpers.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpers.java @@ -80,7 +80,7 @@ public static Builder addOptionalRangeHeader(Builder builder, Long rangeStart, L return builder; } - public static Builder addOptionalAccessContitionHeader(Builder builder, AccessCondition accessCondition) { + public static Builder addOptionalAccessConditionHeader(Builder builder, AccessCondition accessCondition) { if (accessCondition != null) { if (accessCondition.getHeader() != AccessConditionHeaderType.NONE) { builder = addOptionalHeader(builder, accessCondition.getHeader().toString(), accessCondition.getValue()); @@ -89,19 +89,23 @@ public static Builder addOptionalAccessContitionHeader(Builder builder, AccessCo return builder; } - public static Builder addOptionalSourceAccessContitionHeader(Builder builder, AccessCondition accessCondition) { + public static Builder addOptionalSourceAccessConditionHeader(Builder builder, AccessCondition accessCondition) { if (accessCondition != null) { if (accessCondition.getHeader() != AccessConditionHeaderType.NONE) { String headerName; switch (accessCondition.getHeader()) { case IF_MATCH: headerName = "x-ms-source-if-match"; + break; case IF_UNMODIFIED_SINCE: headerName = "x-ms-source-if-unmodified-since"; + break; case IF_MODIFIED_SINCE: headerName = "x-ms-source-if-modified-since"; + break; case IF_NONE_MATCH: headerName = "x-ms-source-if-none-match"; + break; default: headerName = ""; } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfiguration.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfiguration.java index 64c58d8d2a13c..24592204de197 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfiguration.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfiguration.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; @@ -63,8 +63,10 @@ public class ServiceBusConfiguration { * <code>ServiceBusService</code> class. * */ - public static Configuration configureWithWrapAuthentication(String namespace, String authenticationName, String authenticationPassword) { - return configureWithWrapAuthentication(null, Configuration.getInstance(), namespace, authenticationName, authenticationPassword); + public static Configuration configureWithWrapAuthentication(String namespace, String authenticationName, + String authenticationPassword, String serviceBusRootUri, String wrapRootUri) { + return configureWithWrapAuthentication(null, Configuration.getInstance(), namespace, authenticationName, + authenticationPassword, serviceBusRootUri, wrapRootUri); } /** @@ -87,9 +89,10 @@ public static Configuration configureWithWrapAuthentication(String namespace, St * <code>ServiceBusService</code> class. * */ - public static Configuration configureWithWrapAuthentication(Configuration configuration, String namespace, String authenticationName, - String authenticationPassword) { - return configureWithWrapAuthentication(null, configuration, namespace, authenticationName, authenticationPassword); + public static Configuration configureWithWrapAuthentication(Configuration configuration, String namespace, + String authenticationName, String authenticationPassword, String serviceBusRootUri, String wrapRootUri) { + return configureWithWrapAuthentication(null, configuration, namespace, authenticationName, + authenticationPassword, serviceBusRootUri, wrapRootUri); } /** @@ -115,8 +118,9 @@ public static Configuration configureWithWrapAuthentication(Configuration config * <code>ServiceBusService</code> class. * */ - public static Configuration configureWithWrapAuthentication(String profile, Configuration configuration, String namespace, - String authenticationName, String authenticationPassword) { + public static Configuration configureWithWrapAuthentication(String profile, Configuration configuration, + String namespace, String authenticationName, String authenticationPassword, String serviceBusRootUri, + String wrapRootUri) { if (profile == null) { profile = ""; @@ -125,10 +129,9 @@ else if (profile.length() != 0 && !profile.endsWith(".")) { profile = profile + "."; } - configuration.setProperty(profile + URI, "https://" + namespace + ".servicebus.windows.net/"); + configuration.setProperty(profile + URI, "https://" + namespace + serviceBusRootUri); - configuration - .setProperty(profile + WRAP_URI, "https://" + namespace + "-sb.accesscontrol.windows.net/WRAPv0.9"); + configuration.setProperty(profile + WRAP_URI, "https://" + namespace + wrapRootUri); configuration.setProperty(profile + WRAP_NAME, authenticationName); configuration.setProperty(profile + WRAP_PASSWORD, authenticationPassword); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusRestProxy.java index c654e49c6faef..7fc710b76d00a 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusRestProxy.java @@ -22,7 +22,6 @@ import javax.inject.Inject; import javax.inject.Named; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import org.apache.commons.logging.Log; diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/AtomReaderWriter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/AtomReaderWriter.java index ddff3f9aa8895..4691215478308 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/AtomReaderWriter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/AtomReaderWriter.java @@ -77,6 +77,11 @@ public void write(XMLStreamWriter writer) throws XMLStreamException { } String value = edmValueConverter.serialize(edmType, entry.getValue().getValue()); + + if ((edmType != null) && (edmType == "Edm.String")) { + value = encodeNumericCharacterReference(value); + } + if (value != null) { writer.writeCharacters(value); } @@ -327,4 +332,21 @@ private void expect(XMLStreamReader xmlr, int eventType, String localName) throw xmlr.require(eventType, null, localName); nextSignificant(xmlr); } + + private String encodeNumericCharacterReference(String value) { + if (value == null) { + return null; + } + else { + char[] charArray = value.toCharArray(); + StringBuffer stringBuffer = new StringBuffer(); + for (int index = 0; index < charArray.length; index++) { + if (charArray[index] < 0x20 || charArray[index] > 0x7f) + stringBuffer.append("&#x").append(Integer.toHexString(charArray[index])).append(";"); + else + stringBuffer.append(charArray[index]); + } + return stringBuffer.toString(); + } + } } 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 76146812ed985..28e5d990ec7ce 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 @@ -44,8 +44,10 @@ import com.microsoft.windowsazure.services.blob.models.BlockList; import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.ContainerACL.PublicAccessType; +import com.microsoft.windowsazure.services.blob.models.CopyBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobPagesResult; +import com.microsoft.windowsazure.services.blob.models.CreateBlobResult; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotOptions; import com.microsoft.windowsazure.services.blob.models.CreateBlobSnapshotResult; import com.microsoft.windowsazure.services.blob.models.CreateContainerOptions; @@ -660,6 +662,20 @@ public void createPageBlobWorks() throws Exception { // Assert } + @Test + public void createPageBlobWithETagSuccess() throws Exception { + // Arrange + Configuration config = createConfiguration(); + BlobContract service = BlobService.create(config); + + // Act + CreateBlobResult createBlobResult = service.createPageBlob(TEST_CONTAINER_FOR_BLOBS, "test", 512); + + // Assert + assertNotNull(createBlobResult); + assertNotNull(createBlobResult.getEtag()); + } + @Test public void createPageBlobWithOptionsWorks() throws Exception { // Arrange @@ -971,6 +987,21 @@ public void createBlockBlobWorks() throws Exception { // Assert } + @Test + public void createBlockBlobWithValidEtag() throws Exception { + // Arrange + Configuration config = createConfiguration(); + BlobContract service = BlobService.create(config); + + // Act + CreateBlobResult createBlobResult = service.createBlockBlob(TEST_CONTAINER_FOR_BLOBS, "test2", + new ByteArrayInputStream("some content".getBytes())); + + // Assert + assertNotNull(createBlobResult); + assertNotNull(createBlobResult.getEtag()); + } + @Test public void createBlockBlobWithOptionsWorks() throws Exception { // Arrange @@ -1226,6 +1257,32 @@ public void getBlobWithIfNotModifiedSinceAccessConditionWorks() throws Exception // Assert } + @Test + public void getBlobWithMD5Range() throws Exception { + // Arrange + Configuration config = createConfiguration(); + BlobContract service = BlobService.create(config); + String expectedMd5 = "+zxkkqBt6HehE3r5suhS1w=="; + + // Act + String container = TEST_CONTAINER_FOR_BLOBS; + String blob = "test"; + service.createPageBlob(container, blob, 4096); + + GetBlobOptions options = new GetBlobOptions(); + options = options.setRangeStart(50L); + options = options.setRangeEnd(200L); + options = options.setComputeRangeMD5(true); + GetBlobResult getBlobResult = service.getBlob(container, blob, options); + + // Assert + assertNotNull(getBlobResult); + BlobProperties blobProperties = getBlobResult.getProperties(); + String actualMd5 = blobProperties.getContentMD5(); + assertEquals(expectedMd5, actualMd5); + + } + @Test public void getBlobPropertiesWorks() throws Exception { // Arrange @@ -1259,6 +1316,24 @@ public void getBlobPropertiesWorks() throws Exception { assertEquals(0, props.getSequenceNumber()); } + @Test(expected = ServiceException.class) + 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))); + + // Assert + assertTrue(false); + } + @Test public void getBlobMetadataWorks() throws Exception { // Arrange @@ -1427,6 +1502,29 @@ public void copyBlobWorks() throws Exception { assertEquals(content, inputStreamToString(result.getContentStream(), "UTF-8")); } + @Test + public void copyBlobGetEtagSuccess() throws Exception { + // Arrange + Configuration config = createConfiguration(); + BlobContract service = BlobService.create(config); + String sourceBlobName = "copyblobgetetagsuccesssource"; + String targetBlobName = "copyblobgetetagsuccesstarget"; + + //Act + String content = "some content2"; + service.createBlockBlob(TEST_CONTAINER_FOR_BLOBS, sourceBlobName, + new ByteArrayInputStream(content.getBytes("UTF-8"))); + CopyBlobResult copyBlobResult = service.copyBlob(TEST_CONTAINER_FOR_BLOBS_2, targetBlobName, + TEST_CONTAINER_FOR_BLOBS, sourceBlobName); + + GetBlobResult result = service.getBlob(TEST_CONTAINER_FOR_BLOBS_2, targetBlobName); + + // Assert + assertNotNull(result); + assertEquals(copyBlobResult.getEtag(), result.getProperties().getEtag()); + + } + @Test public void acquireLeaseWorks() throws Exception { // Arrange diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpersTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpersTest.java new file mode 100644 index 0000000000000..670b3e7ae0a23 --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/core/utils/pipeline/PipelineHelpersTest.java @@ -0,0 +1,42 @@ +/** + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.microsoft.windowsazure.services.core.utils.pipeline; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.microsoft.windowsazure.services.blob.models.AccessCondition; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.WebResource.Builder; + +public class PipelineHelpersTest { + @Test + public void addOptionalSourceAccessConditionHeaderSuccess() throws Exception { + // Arrange + Client client = Client.create(); + WebResource webResource = client.resource("http://www.microsoft.com"); + Builder builder = webResource.header("ms-version", "1.0"); + AccessCondition accessCondition = AccessCondition.ifMatch("thisIsAETag"); + + // Act + Builder resultBuilder = PipelineHelpers.addOptionalSourceAccessConditionHeader(builder, accessCondition); + + // Assert + assertNotNull(resultBuilder); + + } +} diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfigurationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfigurationTest.java index f9262cd868747..70c3f97963a02 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfigurationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusConfigurationTest.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; @@ -27,7 +27,8 @@ public void ConfigureSetsExpectedProperties() { Configuration config = new Configuration(); // Act - ServiceBusConfiguration.configureWithWrapAuthentication(config, "alpha", "beta", "gamma"); + ServiceBusConfiguration.configureWithWrapAuthentication(config, "alpha", "beta", "gamma", + ".servicebus.windows.net/", "-sb.accesscontrol.windows.net/WRAPv0.9"); // Assert assertEquals("https://alpha.servicebus.windows.net/", config.getProperty("serviceBus.uri")); @@ -42,7 +43,8 @@ public void UsingProfileAddsPrefix() { Configuration config = new Configuration(); // Act - ServiceBusConfiguration.configureWithWrapAuthentication("backup", config, "alpha", "beta", "gamma"); + ServiceBusConfiguration.configureWithWrapAuthentication("backup", config, "alpha", "beta", "gamma", + ".servicebus.windows.net/", "-sb.accesscontrol.windows.net/WRAPv0.9"); // Assert assertEquals("https://alpha.servicebus.windows.net/", config.getProperty("backup.serviceBus.uri")); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusCreationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusCreationTest.java index aba5eace5bf60..ca6c0ebed64e6 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusCreationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusCreationTest.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; @@ -24,7 +24,8 @@ public class ServiceBusCreationTest { @Test public void theServiceClassMayBeCreatedDirectlyViaSingletonConfig() throws Exception { - ServiceBusConfiguration.configureWithWrapAuthentication("my-namespace", "my-identity", "my-shared-secret"); + ServiceBusConfiguration.configureWithWrapAuthentication("my-namespace", "my-identity", "my-shared-secret", + ".servicebus.windows.net", "-sb.accesscontrol.windows.net/WRAPv0.9"); ServiceBusContract service = ServiceBusService.create(); assertNotNull(service); @@ -33,7 +34,8 @@ public void theServiceClassMayBeCreatedDirectlyViaSingletonConfig() throws Excep public Configuration newConfiguration() { Configuration config = new Configuration(); - ServiceBusConfiguration.configureWithWrapAuthentication(config, "my-namespace", "my-identity", "my-shared-secret"); + ServiceBusConfiguration.configureWithWrapAuthentication(config, "my-namespace", "my-identity", + "my-shared-secret", ".servicebus.windows.net", "-sb.accesscontrol.windows.net/WRAPv0.9"); return config; } 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 07b25300bc20b..4651f71acf0d6 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 @@ -348,6 +348,60 @@ public void insertEntityWorks() throws Exception { assertEquals(uuid.toString(), result.getEntity().getProperty("test7").getValue().toString()); } + @Test + public void insertEntityEscapeCharactersWorks() throws Exception { + // Arrange + Configuration config = createConfiguration(); + TableContract service = TableService.create(config); + + Entity entity = new Entity().setPartitionKey("001").setRowKey("insertEntityEscapeCharactersWorks") + .setProperty("test", EdmType.STRING, "\u0005").setProperty("test2", EdmType.STRING, "\u0011") + .setProperty("test3", EdmType.STRING, "\u0025").setProperty("test4", EdmType.STRING, "\uaaaa") + .setProperty("test5", EdmType.STRING, "\ub2e2").setProperty("test6", EdmType.STRING, " \ub2e2") + .setProperty("test7", EdmType.STRING, "ok \ub2e2"); + + // Act + InsertEntityResult result = service.insertEntity(TEST_TABLE_2, entity); + + // Assert + assertNotNull(result); + assertNotNull(result.getEntity()); + + assertEquals("001", result.getEntity().getPartitionKey()); + assertEquals("insertEntityEscapeCharactersWorks", result.getEntity().getRowKey()); + assertNotNull(result.getEntity().getTimestamp()); + assertNotNull(result.getEntity().getEtag()); + + assertNotNull(result.getEntity().getProperty("test")); + String actualTest1 = (String) result.getEntity().getProperty("test").getValue(); + assertEquals("", actualTest1); + + assertNotNull(result.getEntity().getProperty("test2")); + String actualTest2 = (String) result.getEntity().getProperty("test2").getValue(); + assertEquals("", actualTest2); + + assertNotNull(result.getEntity().getProperty("test3")); + String actualTest3 = (String) result.getEntity().getProperty("test3").getValue(); + assertEquals("%", actualTest3); + + assertNotNull(result.getEntity().getProperty("test4")); + String actualTest4 = (String) result.getEntity().getProperty("test4").getValue(); + assertEquals("ꪪ", actualTest4); + + assertNotNull(result.getEntity().getProperty("test5")); + String actualTest5 = (String) result.getEntity().getProperty("test5").getValue(); + assertEquals("닢", actualTest5); + + assertNotNull(result.getEntity().getProperty("test6")); + String actualTest6 = (String) result.getEntity().getProperty("test6").getValue(); + assertEquals(" 닢", actualTest6); + + assertNotNull(result.getEntity().getProperty("test7")); + String actualTest7 = (String) result.getEntity().getProperty("test7").getValue(); + assertEquals("ok 닢", actualTest7); + + } + @Test public void updateEntityWorks() throws Exception { System.out.println("updateEntityWorks()");