diff --git a/.gitignore b/.gitignore index 11a721777fdd7..1760b790d8515 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .project target node_modules +.idea +*.iml diff --git a/ChangeLog.txt b/ChangeLog.txt index 8fe478e4a635c..2c15b781280a6 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,8 +1,22 @@ -2013.1.18 Version 0.4.0 +2013.03.12 Version 0.4.1 + * Added "Azure-SDK-For-Java/" To User-Agent HTTP header + * Added connection string support for Service Bus + * Added new methods to break lease for Storage Blob which doesn't require a lease id and returns the result as an object. Deprecated the old breakLease() methods. + * Added a new method to get the historical events for Media Services + * Fixed Storage Table encoding issue for special characters + * BlobOutputStream now commits block list using LATEST instead of UNCOMMITTED + * Added RequestResult to StorageEvents + * Fixed issue when accessing OperationContext RequestResults + * Fixed the return value of BlobInputStream.read + * Fixed CloudPageBlob.downloadPageRanges to retrieve the blob length + * Fixed MD5 validation in BlobInputStream + * Return ETag in TableResult not only for Insert but also for other operations + +2013.01.18 Version 0.4.0 * Added support for Windows Azure Media Services * Updated dependencies to non-beta stable versions - * Add a Sending Request Event to OperationContext in Storage Client code - * Fix a bug in the STorage client in blob download resume for blobs greater than 2GB + * Added a Sending Request Event to OperationContext in Storage Client code + * Fixed a bug in the Storage client in blob download resume for blobs greater than 2GB 2012.10.29 Version 0.3.3 * In the blob client, fixed a bug which allows users to call write APIs on a blob snapshot reference diff --git a/README.md b/README.md index 87ce6e7e7bbae..22ab0a06a9ece 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ For documentation please see the [Windows Azure Java Developer Center](http://ww To get the source code of the SDK via git just type: git clone git://github.com/WindowsAzure/azure-sdk-for-java.git - cd ./azure-sdk-for-java + cd ./azure-sdk-for-java/microsoft-azure-api/ mvn compile ###Option 2: Via Maven @@ -45,7 +45,7 @@ within your project you can also have them installed by the Java package manager com.microsoft.windowsazure microsoft-windowsazure-api - 0.4.0 + 0.4.1 ##Minimum Requirements diff --git a/microsoft-azure-api/pom.xml b/microsoft-azure-api/pom.xml index 45fbc390a65ef..1900ba335e498 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.4.0 + 0.4.1 jar Microsoft Windows Azure Client API @@ -171,7 +171,7 @@ *.implementation.*;*.utils.*;com.microsoft.schemas._2003._10.serialization /** -
* Copyright 2011 Microsoft Corporation +
* Copyright Microsoft Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. diff --git a/microsoft-azure-api/src/config/checkstyle.xml b/microsoft-azure-api/src/config/checkstyle.xml index 287b61490dd39..58a40f4ac43a8 100644 --- a/microsoft-azure-api/src/config/checkstyle.xml +++ b/microsoft-azure-api/src/config/checkstyle.xml @@ -195,7 +195,11 @@ - + + + + + diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/serviceruntime/RoleEnvironment.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/serviceruntime/RoleEnvironment.java index 5d8f04727b042..e5e3e865f67c2 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/serviceruntime/RoleEnvironment.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/serviceruntime/RoleEnvironment.java @@ -2,15 +2,15 @@ * Copyright 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.serviceruntime; @@ -50,7 +50,6 @@ public final class RoleEnvironment { JAXBContext.newInstance(RoleEnvironment.class.getPackage().getName()); } catch (JAXBException e) { - // TODO Auto-generated catch block e.printStackTrace(); } clientId = UUID.randomUUID().toString(); @@ -93,6 +92,7 @@ private static synchronized void initialize() { lastState = new AtomicReference(); runtimeClient.addGoalStateChangedListener(new GoalStateChangedListener() { + @Override public void goalStateChanged(GoalState newGoalState) { switch (newGoalState.getExpectedState()) { case STARTED: 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 2cac537f9456f..ac52417127140 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 @@ -21,6 +21,7 @@ import com.microsoft.windowsazure.services.blob.models.AcquireLeaseResult; import com.microsoft.windowsazure.services.blob.models.BlobServiceOptions; import com.microsoft.windowsazure.services.blob.models.BlockList; +import com.microsoft.windowsazure.services.blob.models.BreakLeaseResult; import com.microsoft.windowsazure.services.blob.models.CommitBlobBlocksOptions; import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.CopyBlobOptions; @@ -1440,16 +1441,23 @@ void releaseLease(String container, String blob, String leaseId, BlobServiceOpti *

* A lease that has been broken but has not yet expired can also be released, in which case another client may * immediately acquire a new lease on the blob. - * + * + * @deprecated Server ignores the leaseId parameter, replaced by {@link #breakLease(String, String)} without + * the useless parameter. + * * @param container * A {@link String} containing the name of the blob's container. * @param blob * A {@link String} containing the name of the blob to break a lease on. - * @param leaseId - * A {@link String} containing an optional lease ID. + * + * @param leaseId lease id to break. Ignored. + * * @throws ServiceException * if an error occurs accessing the storage service. + * + * @return result containing time remaining before a new lease can be acquired */ + @Deprecated() void breakLease(String container, String blob, String leaseId) throws ServiceException; /** @@ -1465,17 +1473,78 @@ void releaseLease(String container, String blob, String leaseId, BlobServiceOpti *

* A lease that has been broken but has not yet expired can also be released, in which case another client may * immediately acquire a new lease on the blob. - * + * + * @deprecated Server ignores the leaseId parameter, replaced by + * {@link #breakLease(String, String, com.microsoft.windowsazure.services.blob.models.BlobServiceOptions)} + * without the useless parameter. + * + * * @param container * A {@link String} containing the name of the blob's container. * @param blob * A {@link String} containing the name of the blob to break a lease on. - * @param leaseId - * A {@link String} containing an optional lease ID. * @param options - * A {@link BlobServiceOptions} instance containing options for the request. + * A {@link com.microsoft.windowsazure.services.blob.models.BlobServiceOptions} instance containing options for the request. + * @param leaseId lease id to break. Ignored. + * * @throws ServiceException * if an error occurs accessing the storage service. + * @return result containing time remaining before a new lease can be acquired */ + @Deprecated() void breakLease(String container, String blob, String leaseId, BlobServiceOptions options) throws ServiceException; + + /** + * Breaks an active lease on a blob. + *

+ * This method breaks the lease on the blob specified by the blob and container parameters. The + * leaseId parameter is not used by the server. + *

+ * Once a lease is broken, it cannot be renewed. Any authorized request can break the lease; the request is not + * required to specify a matching lease ID. When a lease is broken, the remaining time on the lease is allowed to + * elapse, during which time no lease operation may be performed on the blob. + *

+ * A lease that has been broken but has not yet expired can also be released, in which case another client may + * immediately acquire a new lease on the blob. + * + * + * + * @param container + * A {@link String} containing the name of the blob's container. + * @param blob + * A {@link String} containing the name of the blob to break a lease on. + * @throws ServiceException + * if an error occurs accessing the storage service. + * + * @return result containing time remaining before a new lease can be acquired + */ + BreakLeaseResult breakLease(String container, String blob) throws ServiceException; + + /** + * Breaks an active lease on a blob, using the specified options. + *

+ * This method breaks the lease on the blob specified by the blob and container parameters. The + * leaseId parameter is not used by the server. Use the {@link BlobServiceOptions options} parameter to + * specify the server timeout for the operation. + *

+ * Once a lease is broken, it cannot be renewed. Any authorized request can break the lease; the request is not + * required to specify a matching lease ID. When a lease is broken, the remaining time on the lease is allowed to + * elapse, during which time no lease operation may be performed on the blob. + *

+ * A lease that has been broken but has not yet expired can also be released, in which case another client may + * immediately acquire a new lease on the blob. + * + * + * + * @param container + * A {@link String} containing the name of the blob's container. + * @param blob + * A {@link String} containing the name of the blob to break a lease on. + * @param options + * A {@link com.microsoft.windowsazure.services.blob.models.BlobServiceOptions} instance containing options for the request. + * @throws ServiceException + * if an error occurs accessing the storage service. + * @return result containing time remaining before a new lease can be acquired + */ + BreakLeaseResult breakLease(String container, String blob, BlobServiceOptions options) throws ServiceException; } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/Exports.java index 57a7cd87cc5f9..7dfef8f100dbd 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/Exports.java @@ -20,6 +20,7 @@ import com.microsoft.windowsazure.services.blob.implementation.SharedKeyFilter; import com.microsoft.windowsazure.services.blob.implementation.SharedKeyLiteFilter; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.core.UserAgentFilter; public class Exports implements Builder.Exports { @Override @@ -30,5 +31,6 @@ public void register(Builder.Registry registry) { registry.add(SharedKeyLiteFilter.class); registry.add(SharedKeyFilter.class); registry.add(ISO8601DateConverter.class); + registry.add(UserAgentFilter.class); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobContainerProperties.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobContainerProperties.java index 2b781912d584b..516183818f699 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobContainerProperties.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobContainerProperties.java @@ -131,7 +131,7 @@ public void setLeaseStatus(final LeaseStatus leaseStatus) { /** * Sets the lease status on the container. Reserved for internal use. * - * @param LeaseState + * @param leaseState * The lease state to set, as a LeaseState object. */ public void setLeaseState(final LeaseState leaseState) { @@ -141,7 +141,7 @@ public void setLeaseState(final LeaseState leaseState) { /** * Sets the lease duration on the container. Reserved for internal use. * - * @param LeaseDuration + * @param leaseDuration * The lease duration to set, as a LeaseDuration object. */ public void setLeaseDuration(final LeaseDuration leaseDuration) { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobInputStream.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobInputStream.java index a31526a40e008..ac68dc7e15e96 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobInputStream.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobInputStream.java @@ -82,6 +82,11 @@ public final class BlobInputStream extends InputStream { */ private boolean validateBlobMd5; + /** + * Holds the Blob MD5. + */ + private final String retrievedContentMD5Value; + /** * Holds the reference to the current buffered data. */ @@ -161,11 +166,11 @@ protected BlobInputStream(final CloudBlob parentBlob, final AccessCondition acce final HttpURLConnection attributesRequest = this.opContext.getCurrentRequestObject(); - final String retrievedContentMD5Value = attributesRequest.getHeaderField(Constants.HeaderConstants.CONTENT_MD5); + this.retrievedContentMD5Value = attributesRequest.getHeaderField(Constants.HeaderConstants.CONTENT_MD5); // Will validate it if it was returned this.validateBlobMd5 = !options.getDisableContentMD5Validation() - && !Utility.isNullOrEmpty(retrievedContentMD5Value); + && !Utility.isNullOrEmpty(this.retrievedContentMD5Value); // Validates the first option, and sets future requests to use if match // request option. @@ -395,8 +400,17 @@ public boolean markSupported() { @DoesServiceRequest public int read() throws IOException { final byte[] tBuff = new byte[1]; - this.read(tBuff, 0, 1); - return tBuff[0]; + final int numberOfBytesRead = this.read(tBuff, 0, 1); + + if (numberOfBytesRead > 0) { + return tBuff[0] & 0xFF; + } + else if (numberOfBytesRead == 0) { + throw new IOException("Unexpected error. Stream returned unexpected number of bytes."); + } + else { + return -1; + } } /** @@ -519,13 +533,13 @@ private synchronized int readInternal(final byte[] b, final int off, int len) th if (this.currentAbsoluteReadPosition == this.streamLength) { // Reached end of stream, validate md5. final String calculatedMd5 = Base64.encode(this.md5Digest.digest()); - if (!calculatedMd5.equals(this.parentBlobRef.getProperties().getContentMD5())) { + if (!calculatedMd5.equals(this.retrievedContentMD5Value)) { this.lastError = Utility .initIOException(new StorageException( StorageErrorCodeStrings.INVALID_MD5, String.format( "Blob data corrupted (integrity check failed), Expected value is %s, retrieved %s", - this.parentBlobRef.getProperties().getContentMD5(), calculatedMd5), + this.retrievedContentMD5Value, calculatedMd5), Constants.HeaderConstants.HTTP_UNUSED_306, null, null)); this.streamFaulted = true; throw this.lastError; diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobOutputStream.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobOutputStream.java index dae6409998617..93d870b15e1bf 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobOutputStream.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobOutputStream.java @@ -356,7 +356,7 @@ private synchronized void dispatchWrite(final int writeLength) throws IOExceptio if (this.streamType == BlobType.BLOCK_BLOB) { final CloudBlockBlob blobRef = (CloudBlockBlob) this.parentBlobRef; final String blockID = Base64.encode(Utility.getBytesFromLong(this.blockIdSequenceNumber++)); - this.blockList.add(new BlockEntry(blockID, BlockSearchMode.UNCOMMITTED)); + this.blockList.add(new BlockEntry(blockID, BlockSearchMode.LATEST)); worker = new Callable() { @Override diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobProperties.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobProperties.java index 9fc4475b052da..0eaff8e5789a4 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobProperties.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/BlobProperties.java @@ -334,7 +334,7 @@ public void setLeaseStatus(final LeaseStatus leaseStatus) { /** * Sets the lease state for the blob. Reserved for internal use. * - * @param LeaseState + * @param leaseState * The lease state to set, represented by a LeaseState object. */ public void setLeaseState(final LeaseState leaseState) { @@ -344,7 +344,7 @@ public void setLeaseState(final LeaseState leaseState) { /** * Sets the lease duration for the blob. Reserved for internal use. * - * @param LeaseDuration + * @param leaseDuration * The lease duration value to set, represented by a LeaseDuration object. */ public void setLeaseDuration(final LeaseDuration leaseDuration) { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlob.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlob.java index 49ae8c7366fa7..84e345591cc55 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlob.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlob.java @@ -221,7 +221,7 @@ protected CloudBlob(final CloudBlob otherBlob) { * * @param leaseTimeInSeconds * Specifies the span of time for which to acquire the lease, in seconds. - * If null, an infinite lease will be acquired. If not null, the value must be greater than + * If null, an infinite lease will be acquired. If not null, the value must be greater than * zero. * * @param proposedLeaseId @@ -245,7 +245,7 @@ public final String acquireLease(final Integer leaseTimeInSeconds, final String * * @param leaseTimeInSeconds * Specifies the span of time for which to acquire the lease, in seconds. - * If null, an infinite lease will be acquired. If not null, the value must be greater than + * If null, an infinite lease will be acquired. If not null, the value must be greater than * zero. * * @param proposedLeaseId @@ -254,12 +254,12 @@ public final String acquireLease(final Integer leaseTimeInSeconds, final String * * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the blob. - * + * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). - * + * * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context * is used to track requests to the storage service, and to provide additional runtime information about @@ -298,7 +298,7 @@ public String execute(final CloudBlobClient client, final CloudBlob blob, final client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -342,7 +342,7 @@ protected final void assertCorrectBlobType() throws StorageException { } /** - * Breaks the lease and ensures that another client cannot acquire a new lease until the current lease period + * Breaks the lease and ensures that another client cannot acquire a new lease until the current lease period * has expired. * * @param breakPeriodInSeconds @@ -360,7 +360,7 @@ public final long breakLease(final Integer breakPeriodInSeconds) throws StorageE } /** - * Breaks the existing lease, using the specified request options and operation context, and ensures that another + * Breaks the existing lease, using the specified request options and operation context, and ensures that another * client cannot acquire a new lease until the current lease period has expired. * * @param breakPeriodInSeconds @@ -371,7 +371,7 @@ public final long breakLease(final Integer breakPeriodInSeconds) throws StorageE * An {@link AccessCondition} object that represents the access conditions for the blob. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context @@ -410,7 +410,7 @@ public Long execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); @@ -544,7 +544,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op BlobRequest.addMetadata(request, blob.metadata, opContext); client.getCredentials().signRequest(request, 0); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); @@ -623,7 +623,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); @@ -698,7 +698,7 @@ public CloudBlob execute(final CloudBlobClient client, final CloudBlob blob, client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -787,7 +787,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); @@ -878,7 +878,7 @@ public Boolean execute(final CloudBlobClient client, final CloudBlob blob, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_ACCEPTED) { return true; @@ -961,8 +961,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op blobOptions.getTimeoutIntervalInMs(), blob.snapshotID, accessCondition, blobOptions, opContext); client.getCredentials().signRequest(request, -1L); - final InputStream streamRef = ExecutionEngine.getInputStream(request, opContext); - this.setResult(opContext.getLastResult()); + final InputStream streamRef = ExecutionEngine.getInputStream(request, opContext, this.getResult()); final String contentMD5 = request.getHeaderField(Constants.HeaderConstants.CONTENT_MD5); final Boolean validateMD5 = !blobOptions.getDisableContentMD5Validation() @@ -1015,8 +1014,8 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op if ((ex.getHttpStatusCode() == Constants.HeaderConstants.HTTP_UNUSED_306 && !ex.getErrorCode().equals( StorageErrorCodeStrings.OUT_OF_RANGE_INPUT)) || ex.getHttpStatusCode() == HttpURLConnection.HTTP_PRECON_FAILED - || !dummyPolicy.shouldRetry(0, opContext.getLastResult().getStatusCode(), - (Exception) ex.getCause(), opContext).isShouldRetry()) { + || !dummyPolicy.shouldRetry(0, impl.getResult().getStatusCode(), (Exception) ex.getCause(), + opContext).isShouldRetry()) { opContext.setIntermediateMD5(null); throw ex; } @@ -1141,7 +1140,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1247,7 +1246,7 @@ public final void downloadRange(final long offset, final int length, final byte[ * the number of bytes to read * @param buffer * the byte buffer to write to. - * @param bufferOffet + * @param bufferOffset * the offset in the byte buffer to begin writing. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the blob. @@ -1298,8 +1297,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, -1L); - final InputStream sourceStream = ExecutionEngine.getInputStream(request, opContext); - this.setResult(opContext.getLastResult()); + final InputStream sourceStream = ExecutionEngine.getInputStream(request, opContext, this.getResult()); int totalRead = 0; int nextRead = buffer.length - bufferOffset; @@ -1328,14 +1326,16 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op return null; } - // Do not update blob length in downloadRangeInternal API. - final long orignalBlobLength = blob.properties.getLength(); + // Do not update blob length and Content-MD5 in downloadRangeInternal API. + final long originalBlobLength = blob.properties.getLength(); + final String originalContentMD5 = blob.properties.getContentMD5(); final BlobAttributes retrievedAttributes = BlobResponse.getAttributes(request, blob.getUri(), blob.snapshotID, opContext); blob.properties = retrievedAttributes.getProperties(); blob.metadata = retrievedAttributes.getMetadata(); blob.copyState = retrievedAttributes.getCopyState(); - blob.properties.setLength(orignalBlobLength); + blob.properties.setContentMD5(originalContentMD5); + blob.properties.setLength(originalBlobLength); final String contentLength = request.getHeaderField(Constants.HeaderConstants.CONTENT_LENGTH); final long expectedLength = Long.parseLong(contentLength); @@ -1433,7 +1433,7 @@ public Boolean execute(final CloudBlobClient client, final CloudBlob blob, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { final BlobAttributes retrievedAttributes = BlobResponse.getAttributes(request, blob.getUri(), @@ -1468,10 +1468,6 @@ else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { * signature. * @param groupPolicyIdentifier * A String that represents the container-level access policy. - * @param opContext - * An {@link OperationContext} object that represents the context for the current operation. This object - * is used to track requests to the storage service, and to provide additional runtime information about - * the operation. * * @return A String that represents the shared access signature. * @@ -1924,7 +1920,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -2004,7 +2000,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -2053,7 +2049,7 @@ public final void changeLease(final String proposedLeaseId, final AccessConditio * required to be set with an access condition. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context @@ -2093,7 +2089,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -2220,7 +2216,7 @@ public Long execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { final StorageException potentialConflictException = StorageException.translateException(request, @@ -2370,7 +2366,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op HttpURLConnection.HTTP_FORBIDDEN, null, null); } - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -2444,7 +2440,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op BlobRequest.addMetadata(request, blob.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -2518,7 +2514,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op BlobRequest.addMetadata(request, blob.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobClient.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobClient.java index 181549a8d5750..c000b97c98edc 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobClient.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobClient.java @@ -388,7 +388,7 @@ ResultSegment listContainersCore(final String prefix, this.getCredentials().signRequest(listContainerRequest, -1L); - taskReference.setResult(ExecutionEngine.processRequest(listContainerRequest, opContext)); + ExecutionEngine.processRequest(listContainerRequest, opContext, taskReference.getResult()); if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { taskReference.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainer.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainer.java index ff67b888bfe33..b1d1a7a6c8db1 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainer.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainer.java @@ -224,7 +224,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta ContainerRequest.addMetadata(request, container.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -298,7 +298,7 @@ public Boolean execute(final CloudBlobClient client, final CloudBlobContainer co ContainerRequest.addMetadata(request, container.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); // Validate response code here if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CREATED) { @@ -390,7 +390,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); @@ -460,7 +460,7 @@ public Boolean execute(final CloudBlobClient client, final CloudBlobContainer co client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_ACCEPTED) { container.updatePropertiesFromResponse(request); @@ -533,7 +533,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -610,7 +610,7 @@ public BlobContainerPermissions execute(final CloudBlobClient client, final Clou client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -689,7 +689,7 @@ public Boolean execute(final CloudBlobClient client, final CloudBlobContainer co client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { container.updatePropertiesFromResponse(request); @@ -1108,7 +1108,7 @@ ResultSegment listBlobsCore(final String prefix, final boolean use this.blobServiceClient.getCredentials().signRequest(listBlobsRequest, -1L); - taskReference.setResult(ExecutionEngine.processRequest(listBlobsRequest, opContext)); + ExecutionEngine.processRequest(listBlobsRequest, opContext, taskReference.getResult()); if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { taskReference.setNonExceptionedRetryableFailure(true); @@ -1533,7 +1533,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta ContainerRequest.addMetadata(request, container.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1613,7 +1613,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta final OutputStream outStreamRef = request.getOutputStream(); outStreamRef.write(aclBytes); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1633,7 +1633,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta * * @param leaseTimeInSeconds * Specifies the span of time for which to acquire the lease, in seconds. - * If null, an infinite lease will be acquired. If not null, the value must be greater than + * If null, an infinite lease will be acquired. If not null, the value must be greater than * zero. * * @param proposedLeaseId @@ -1657,7 +1657,7 @@ public final String acquireLease(final Integer leaseTimeInSeconds, final String * * @param leaseTimeInSeconds * Specifies the span of time for which to acquire the lease, in seconds. - * If null, an infinite lease will be acquired. If not null, the value must be greater than + * If null, an infinite lease will be acquired. If not null, the value must be greater than * zero. * * @param proposedLeaseId @@ -1666,12 +1666,12 @@ public final String acquireLease(final Integer leaseTimeInSeconds, final String * * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the container. - * + * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). - * + * * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context * is used to track requests to the storage service, and to provide additional runtime information about @@ -1710,7 +1710,7 @@ public String execute(final CloudBlobClient client, final CloudBlobContainer con client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -1731,8 +1731,8 @@ public String execute(final CloudBlobClient client, final CloudBlobContainer con * Renews an existing lease with the specified access conditions. * * @param accessCondition - * An {@link AccessCondition} object that represents the access conditions for the container. The lease ID is - * required to be set with an access condition. + * An {@link AccessCondition} object that represents the access conditions for the container. The lease + * ID is required to be set with an access condition. * * @throws StorageException * If a storage service error occurred. @@ -1748,12 +1748,12 @@ public final void renewLease(final AccessCondition accessCondition) throws Stora * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the blob. The lease ID is * required to be set with an access condition. - * + * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). - * + * * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context * is used to track requests to the storage service, and to provide additional runtime information about @@ -1792,7 +1792,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1824,17 +1824,18 @@ public final void releaseLease(final AccessCondition accessCondition) throws Sto } /** - * Releases the lease on the container using the specified access conditions, request options, and operation context. + * Releases the lease on the container using the specified access conditions, request options, and operation + * context. * * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the blob. The lease ID is * required to be set with an access condition. - * + * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). - * + * * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context * is used to track requests to the storage service, and to provide additional runtime information about @@ -1873,7 +1874,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1890,7 +1891,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta } /** - * Breaks the lease and ensures that another client cannot acquire a new lease until the current lease + * Breaks the lease and ensures that another client cannot acquire a new lease until the current lease * period has expired. * * @param breakPeriodInSeconds @@ -1908,7 +1909,7 @@ public final long breakLease(final Integer breakPeriodInSeconds) throws StorageE } /** - * Breaks the existing lease, using the specified request options and operation context, and ensures that + * Breaks the existing lease, using the specified request options and operation context, and ensures that * another client cannot acquire a new lease until the current lease period has expired. * * @param breakPeriodInSeconds @@ -1919,7 +1920,7 @@ public final long breakLease(final Integer breakPeriodInSeconds) throws StorageE * An {@link AccessCondition} object that represents the access conditions for the blob. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context @@ -1958,7 +1959,7 @@ public Long execute(final CloudBlobClient client, final CloudBlobContainer conta client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); @@ -2006,12 +2007,12 @@ public final void changeLease(final String proposedLeaseId, final AccessConditio * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the blob. The lease ID is * required to be set with an access condition. - * + * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client + * null will use the default request options from the associated service client * ({@link CloudBlobClient}). - * + * * @param opContext * An {@link OperationContext} object that represents the context for the current operation. The context * is used to track requests to the storage service, and to provide additional runtime information about @@ -2050,7 +2051,7 @@ public Void execute(final CloudBlobClient client, final CloudBlobContainer conta client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlockBlob.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlockBlob.java index b28a54a6affd6..9ee73d83c1d15 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlockBlob.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudBlockBlob.java @@ -204,7 +204,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op Utility.writeToOutputStream(blockListInputStream, request.getOutputStream(), descriptor.getLength(), false, false, null, opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -293,7 +293,7 @@ public ArrayList execute(final CloudBlobClient client, final CloudBl client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -624,7 +624,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op Utility.writeToOutputStream(sourceStream, request.getOutputStream(), length, true /* rewindSourceStream */, false /* calculateMD5 */, null, opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudPageBlob.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudPageBlob.java index e31eb5aff1961..d81af25c62672 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudPageBlob.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/client/CloudPageBlob.java @@ -272,7 +272,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -352,7 +352,7 @@ public ArrayList execute(final CloudBlobClient client, final CloudBlo client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -360,6 +360,8 @@ public ArrayList execute(final CloudBlobClient client, final CloudBlo } blob.updateEtagAndLastModifiedFromResponse(request); + blob.updateLengthFromResponse(request); + final GetPageRangesResponse response = new GetPageRangesResponse(request.getInputStream()); return response.getPageRanges(); } @@ -482,7 +484,7 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op client.getCredentials().signRequest(request, 0L); } - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -490,7 +492,6 @@ public Void execute(final CloudBlobClient client, final CloudBlob blob, final Op } blob.updateEtagAndLastModifiedFromResponse(request); - blob.updateLengthFromResponse(request); return null; } }; diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/core/storage/SharedAccessSignatureHelper.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/core/storage/SharedAccessSignatureHelper.java index 9be65bdcb88f6..f798b48382329 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/core/storage/SharedAccessSignatureHelper.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/core/storage/SharedAccessSignatureHelper.java @@ -149,10 +149,6 @@ public static UriQueryBuilder generateSharedAccessSignature(final SharedAccessQu /** * Get the complete query builder for creating the Shared Access Signature query. * - * @param policy - * The shared access policy to hash. - * @param groupPolicyIdentifier - * An optional identifier for the policy. * @param signature * The signature to use. * @return The finished query builder @@ -285,7 +281,7 @@ public static String generateSharedAccessSignatureHash(final SharedAccessBlobPol * * @param policy * The shared access policy to hash. - * @param groupPolicyIdentifier + * @param accessPolicyIdentifier * An optional identifier for the policy. * @param resourceName * the resource name. @@ -356,7 +352,7 @@ public static String generateSharedAccessSignatureHash(final String permissions, * * @param policy * The shared access policy to hash. - * @param groupPolicyIdentifier + * @param accessPolicyIdentifier * An optional identifier for the policy. * @param resourceName * the resource name. 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 8bae36798a8c7..3b0689cff0083 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 @@ -27,6 +27,7 @@ import com.microsoft.windowsazure.services.blob.models.AcquireLeaseResult; import com.microsoft.windowsazure.services.blob.models.BlobServiceOptions; import com.microsoft.windowsazure.services.blob.models.BlockList; +import com.microsoft.windowsazure.services.blob.models.BreakLeaseResult; import com.microsoft.windowsazure.services.blob.models.CommitBlobBlocksOptions; import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.CopyBlobOptions; @@ -888,9 +889,21 @@ public void releaseLease(String container, String blob, String leaseId, BlobServ } @Override + @Deprecated public void breakLease(String container, String blob, String leaseId) throws ServiceException { + breakLease(container, blob); + } + + @Override + @Deprecated + public void breakLease(String container, String blob, String leaseId, BlobServiceOptions options) throws ServiceException { + breakLease(container, blob, options); + } + + @Override + public BreakLeaseResult breakLease(String container, String blob) throws ServiceException { try { - service.breakLease(container, blob, leaseId); + return service.breakLease(container, blob); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); @@ -901,10 +914,10 @@ public void breakLease(String container, String blob, String leaseId) throws Ser } @Override - public void breakLease(String container, String blob, String leaseId, BlobServiceOptions options) + public BreakLeaseResult breakLease(String container, String blob, BlobServiceOptions options) throws ServiceException { try { - service.breakLease(container, blob, leaseId, options); + return service.breakLease(container, blob, options); } catch (UniformInterfaceException e) { throw processCatch(new ServiceException(e)); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobOperationRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobOperationRestProxy.java index b07f42f63f29d..24adf87f4a232 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobOperationRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/implementation/BlobOperationRestProxy.java @@ -26,6 +26,7 @@ import com.microsoft.windowsazure.services.blob.models.BlobProperties; import com.microsoft.windowsazure.services.blob.models.BlobServiceOptions; import com.microsoft.windowsazure.services.blob.models.BlockList; +import com.microsoft.windowsazure.services.blob.models.BreakLeaseResult; import com.microsoft.windowsazure.services.blob.models.CommitBlobBlocksOptions; import com.microsoft.windowsazure.services.blob.models.ContainerACL; import com.microsoft.windowsazure.services.blob.models.ContainerACL.PublicAccessType; @@ -531,7 +532,6 @@ public CreateBlobResult createBlockBlob(String container, String blob, InputStre 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); Builder builder = webResource.header("x-ms-version", API_VERSION); @@ -801,33 +801,56 @@ public void releaseLease(String container, String blob, String leaseId, BlobServ } @Override + @Deprecated public void breakLease(String container, String blob, String leaseId) throws ServiceException { - breakLease(container, blob, leaseId, new BlobServiceOptions()); + breakLease(container, blob); } @Override - public void breakLease(String container, String blob, String leaseId, BlobServiceOptions options) - throws ServiceException { - putLeaseImpl("break", container, blob, leaseId, options, null/* accessCondition */); + @Deprecated + public void breakLease(String container, String blob, String leaseId, BlobServiceOptions options) throws ServiceException { + breakLease(container, blob, options); + } + + @Override + public BreakLeaseResult breakLease(String container, String blob) throws ServiceException { + return breakLease(container, blob, new BlobServiceOptions()); + } + + @Override + public BreakLeaseResult breakLease(String container, String blob, BlobServiceOptions options) + throws ServiceException { + ClientResponse response = doLeaseOperation("break", container, blob, null, options, null); + + BreakLeaseResult result = new BreakLeaseResult(); + result.setRemainingLeaseTimeInSeconds(Integer.parseInt(response.getHeaders().getFirst("x-ms-lease-time"))); + return result; } private AcquireLeaseResult putLeaseImpl(String leaseAction, String container, String blob, String leaseId, BlobServiceOptions options, AccessCondition accessCondition) throws ServiceException { + ClientResponse response = doLeaseOperation(leaseAction, container, blob, leaseId, options, accessCondition); + + AcquireLeaseResult result = new AcquireLeaseResult(); + result.setLeaseId(response.getHeaders().getFirst("x-ms-lease-id")); + return result; + } + + private ClientResponse doLeaseOperation(String leaseAction, String container, String blob, String leaseId, BlobServiceOptions options, AccessCondition accessCondition) { String path = createPathFromContainer(container); WebResource webResource = getResource(options).path(path).path(blob).queryParam("comp", "lease"); Builder builder = webResource.header("x-ms-version", API_VERSION); - builder = addOptionalHeader(builder, "x-ms-lease-id", leaseId); + if (leaseId != null) { + builder = addOptionalHeader(builder, "x-ms-lease-id", leaseId); + } builder = addOptionalHeader(builder, "x-ms-lease-action", leaseAction); builder = addOptionalAccessConditionHeader(builder, accessCondition); // Note: Add content type here to enable proper HMAC signing ClientResponse response = builder.put(ClientResponse.class, ""); ThrowIfError(response); - - AcquireLeaseResult result = new AcquireLeaseResult(); - result.setLeaseId(response.getHeaders().getFirst("x-ms-lease-id")); - return result; + return response; } @Override 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 bb628ea9d72fc..ed87b549f79be 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 @@ -22,26 +22,29 @@ import com.microsoft.windowsazure.services.blob.BlobConfiguration; import com.microsoft.windowsazure.services.blob.BlobContract; import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.pipeline.HttpURLConnectionClient; import com.sun.jersey.api.client.Client; public class BlobRestProxy extends BlobOperationRestProxy implements BlobContract { - private final SharedKeyFilter filter; + private final SharedKeyFilter sharedKeyFilter; @Inject public BlobRestProxy(HttpURLConnectionClient channel, @Named(BlobConfiguration.ACCOUNT_NAME) String accountName, - @Named(BlobConfiguration.URI) String url, SharedKeyFilter filter) { + @Named(BlobConfiguration.URI) String url, SharedKeyFilter sharedKeyFilter, UserAgentFilter userAgentFilter) { super(channel, accountName, url); - this.filter = filter; - channel.addFilter(filter); + this.sharedKeyFilter = sharedKeyFilter; + + channel.addFilter(sharedKeyFilter); + channel.addFilter(userAgentFilter); } public BlobRestProxy(Client client, ServiceFilter[] filters, String accountName, String url, - SharedKeyFilter filter, RFC1123DateConverter dateMapper) { + SharedKeyFilter sharedKeyFilter, RFC1123DateConverter dateMapper) { super(client, filters, accountName, url, dateMapper); - this.filter = filter; + this.sharedKeyFilter = sharedKeyFilter; } @Override @@ -49,6 +52,7 @@ public BlobContract withFilter(ServiceFilter filter) { ServiceFilter[] currentFilters = getFilters(); ServiceFilter[] newFilters = Arrays.copyOf(currentFilters, currentFilters.length + 1); newFilters[currentFilters.length] = filter; - return new BlobRestProxy(getChannel(), newFilters, getAccountName(), getUrl(), this.filter, getDateMapper()); + return new BlobRestProxy(getChannel(), newFilters, getAccountName(), getUrl(), this.sharedKeyFilter, + getDateMapper()); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/AcquireLeaseResult.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/AcquireLeaseResult.java index 044833ada7ba8..4c4803afeb0f1 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/AcquireLeaseResult.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/AcquireLeaseResult.java @@ -18,9 +18,10 @@ /** * A wrapper class for the response returned from a Blob Service REST API Lease Blob operation. This is returned by - * calls to implementations of {@link BlobContract#breakLease(String, String, String, BlobServiceOptions)}, - * {@link BlobContract#releaseLease(String, String, String, BlobServiceOptions)} and - * {@link BlobContract#renewLease(String, String, String, BlobServiceOptions)}. + * calls to implementations of {@link BlobContract#acquireLease(String, String)}, + * {@link BlobContract#acquireLease(String, String, AcquireLeaseOptions)}, + * {@link BlobContract#renewLease(String, String, String, BlobServiceOptions)}, and + * {@link BlobContract#renewLease(String, String, String)}. *

* See the Lease Blob documentation on * MSDN for details of the underlying Blob Service REST API operation. diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/BreakLeaseResult.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/BreakLeaseResult.java new file mode 100644 index 0000000000000..d76f5e6564a1a --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/BreakLeaseResult.java @@ -0,0 +1,35 @@ +/** + * Copyright 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; + +/** + * A wrapper class for the response returned from a Blob Service REST API Break Lease Blob operation. This is returned by + * calls to implementations of {@link com.microsoft.windowsazure.services.blob.BlobContract#breakLease(String, String, BlobServiceOptions)}, + *

+ * See the Lease Blob documentation on + * MSDN for details of the underlying Blob Service REST API operation. + */ +public class BreakLeaseResult { + private int remainingLeaseTimeInSeconds; + + public int getRemainingLeaseTimeInSeconds() { + return remainingLeaseTimeInSeconds; + } + + public void setRemainingLeaseTimeInSeconds(int remainingLeaseTimeInSeconds) { + this.remainingLeaseTimeInSeconds = remainingLeaseTimeInSeconds; + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobOptions.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobOptions.java index 644f5e7b4718f..44e3e63090b45 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobOptions.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/blob/models/CreateBlobOptions.java @@ -20,7 +20,7 @@ /** * Represents the options that may be set on a - * {@link BlobContract#createPageBlob(String, String, int, CreateBlobOptions) createPageBlob} or + * {@link BlobContract#createPageBlob(String, String, long, CreateBlobOptions) createPageBlob} or * {@link BlobContract#createBlockBlob(String, String, java.io.InputStream, CreateBlobOptions) createBlockBlob} request. * These options include an optional server timeout for the operation, the MIME content type and content encoding for * the blob, the content language, the MD5 hash, a cache control value, blob metadata, a blob lease ID, a sequence 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 index 6181e7c7278f7..57a4c0faebce1 100644 --- 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 @@ -21,7 +21,7 @@ /** * 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)}. + * {@link BlobContract#createBlockBlob(String, String, java.io.InputStream, CreateBlobOptions)}. *

* See the Put Blob documentation on * MSDN for details of the underlying Blob Service REST API operation. diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/UserAgentFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/UserAgentFilter.java new file mode 100644 index 0000000000000..19de5d41d4ae5 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/UserAgentFilter.java @@ -0,0 +1,105 @@ +/** + * Copyright 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; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import com.sun.jersey.api.client.ClientHandlerException; +import com.sun.jersey.api.client.ClientRequest; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.filter.ClientFilter; + +/** + * The Class UserAgentFilter. + */ +public class UserAgentFilter extends ClientFilter { + + /** The azure sdk product token. */ + private static String azureSDKProductToken; + + /** + * Instantiates a new user agent filter. + */ + public UserAgentFilter() { + if ((azureSDKProductToken == null) || azureSDKProductToken.isEmpty()) { + azureSDKProductToken = createAzureSDKProductToken(); + } + + } + + /* (non-Javadoc) + * @see com.sun.jersey.api.client.filter.ClientFilter#handle(com.sun.jersey.api.client.ClientRequest) + */ + @Override + public ClientResponse handle(ClientRequest clientRequest) throws ClientHandlerException { + String userAgent; + + if (clientRequest.getHeaders().containsKey("User-Agent")) { + String currentUserAgent = (String) clientRequest.getHeaders().getFirst("User-Agent"); + userAgent = azureSDKProductToken + " " + currentUserAgent; + clientRequest.getHeaders().remove("User-Agent"); + } + else { + userAgent = azureSDKProductToken; + } + + clientRequest.getHeaders().add("User-Agent", userAgent); + + return this.getNext().handle(clientRequest); + } + + /** + * Creates the azure sdk product token. + * + * @return the string + */ + private String createAzureSDKProductToken() { + String version = getVersionFromResources(); + String productToken; + if ((version != null) && (!version.isEmpty())) { + productToken = "Azure-SDK-For-Java/" + version; + } + else { + productToken = "Azure-SDK-For-Java"; + } + + return productToken; + } + + /** + * Gets the version of the SDK from resources. + * + * @return the version from resources + */ + private String getVersionFromResources() { + String version = "unknown"; + Properties properties = new Properties(); + try { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream( + "META-INF/maven/com.microsoft.windowsazure/microsoft-windowsazure-api/pom.properties"); + if (inputStream != null) { + properties.load(inputStream); + version = properties.getProperty("version"); + inputStream.close(); + } + } + catch (IOException e) { + } + + return version; + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/Constants.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/Constants.java index 021acc7a3ad8b..baea2ec847207 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/Constants.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/Constants.java @@ -327,7 +327,7 @@ public static class HeaderConstants { /** * Specifies the value to use for UserAgent header. */ - public static final String USER_AGENT_VERSION = "Client v0.1.3.1"; + public static final String USER_AGENT_VERSION = "Client v0.1.3.2"; } /** diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/OperationContext.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/OperationContext.java index 7e6e3a3320dae..d19a8eba6b649 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/OperationContext.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/OperationContext.java @@ -51,7 +51,7 @@ public final class OperationContext { * Represents request results, in the form of an ArrayList object that contains the * {@link RequestResult} objects, for each physical request that is made. */ - private ArrayList requestResults; + private final ArrayList requestResults; /** * Represents an event that is triggered before sending a request. @@ -135,7 +135,7 @@ public MessageDigest getIntermediateMD5() { * * @return A {@link RequestResult} object that represents the last request result. */ - public RequestResult getLastResult() { + public synchronized RequestResult getLastResult() { if (this.requestResults == null || this.requestResults.size() == 0) { return null; } @@ -165,6 +165,16 @@ public ArrayList getRequestResults() { return this.requestResults; } + /** + * Reserved for internal use. appends a {@link RequestResult} object to the internal collection in a synchronized + * manner. + * + * @param requestResult + */ + public synchronized void appendRequestResult(RequestResult requestResult) { + this.requestResults.add(requestResult); + } + /** * @return the SendingRequestEvent */ diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ResponseReceivedEvent.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ResponseReceivedEvent.java index f0b8419d1ab5b..bf1506495a5db 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ResponseReceivedEvent.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ResponseReceivedEvent.java @@ -23,13 +23,18 @@ public final class ResponseReceivedEvent { * Represents a connection object. Currently only java.net.HttpURLConnection is supported as a * connection object. */ - private Object connectionObject; + private final Object connectionObject; /** * Represents a context for the current operation. This object is used to track requests to the storage service, and * to provide additional runtime information about the operation. */ - private OperationContext opContext; + private final OperationContext opContext; + + /** + * A {@link RequestResult} object that represents the last request result. + */ + private final RequestResult requestResult; /** * Creates an instance of the ResponseReceivedEvent class. @@ -41,10 +46,14 @@ public final class ResponseReceivedEvent { * @param connectionObject * Represents a connection object. Currently only java.net.HttpURLConnection is supported as * a connection object. + * @param requestResult + * A {@link RequestResult} object that represents the current request result. */ - public ResponseReceivedEvent(final OperationContext opContext, final Object connectionObject) { + public ResponseReceivedEvent(final OperationContext opContext, final Object connectionObject, + final RequestResult requestResult) { this.opContext = opContext; this.connectionObject = connectionObject; + this.requestResult = requestResult; } /** @@ -60,4 +69,11 @@ public Object getConnectionObject() { public OperationContext getOpContext() { return this.opContext; } + + /** + * @return A {@link RequestResult} object that represents the current request result. + */ + public RequestResult getRequestResult() { + return this.requestResult; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/SendingRequestEvent.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/SendingRequestEvent.java index 8b61f7e092ff9..8d0e6da594d66 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/SendingRequestEvent.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/SendingRequestEvent.java @@ -31,6 +31,11 @@ public final class SendingRequestEvent { */ private final OperationContext opContext; + /** + * A {@link RequestResult} object that represents the last request result. + */ + private final RequestResult requestResult; + /** * Creates an instance of the SendingRequestEvent class. * @@ -41,10 +46,14 @@ public final class SendingRequestEvent { * @param connectionObject * Represents a connection object. Currently only java.net.HttpURLConnection is supported as * a connection object. + * @param requestResult + * A {@link RequestResult} object that represents the current request result. */ - public SendingRequestEvent(final OperationContext opContext, final Object connectionObject) { + public SendingRequestEvent(final OperationContext opContext, final Object connectionObject, + final RequestResult requestResult) { this.opContext = opContext; this.connectionObject = connectionObject; + this.requestResult = requestResult; } /** @@ -60,4 +69,11 @@ public Object getConnectionObject() { public OperationContext getOpContext() { return this.opContext; } + + /** + * @return A {@link RequestResult} object that represents the current request result. + */ + public RequestResult getRequestResult() { + return this.requestResult; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ServiceClient.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ServiceClient.java index 02f0322b2808d..8a6df9f916f3e 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ServiceClient.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/ServiceClient.java @@ -144,7 +144,7 @@ public ServiceProperties execute(final ServiceClient client, final Void v, final .getRequestOptions().getTimeoutIntervalInMs(), null, opContext); client.getCredentials().signRequest(request, -1); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -242,13 +242,13 @@ public void setRetryPolicyFactory(final RetryPolicyFactory retryPolicyFactory) { /** * Sets the timeout to use when making requests to the storage service. *

- * The server timeout interval begins at the time that the complete request has been received by the service, and the - * server begins processing the response. If the timeout interval elapses before the response is returned to the + * The server timeout interval begins at the time that the complete request has been received by the service, and + * the server begins processing the response. If the timeout interval elapses before the response is returned to the * client, the operation times out. The timeout interval resets with each retry, if the request is retried. * - * The default timeout interval for a request made via the service client is 90 seconds. You can change this value on - * the service client by setting this property, so that all subsequent requests made via the service client will use - * the new timeout interval. You can also change this value for an individual request, by setting the + * The default timeout interval for a request made via the service client is 90 seconds. You can change this value + * on the service client by setting this property, so that all subsequent requests made via the service client will + * use the new timeout interval. You can also change this value for an individual request, by setting the * {@link RequestOptions#timeoutIntervalInMs} property. * * If you are downloading a large blob, you should increase the value of the timeout beyond the default value. @@ -330,7 +330,7 @@ public Void execute(final ServiceClient client, final Void v, final OperationCon Utility.writeToOutputStream(dataInputStream, request.getOutputStream(), descriptor.getLength(), false /* rewindSourceStream */, false /* calculateMD5 */, null, opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/ExecutionEngine.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/ExecutionEngine.java index ba188fb376928..9d3ad41e569ab 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/ExecutionEngine.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/ExecutionEngine.java @@ -106,7 +106,7 @@ public static RESULT_TYPE executeWithRet while (true) { try { // reset result flags - task.initialize(); + task.initialize(opContext); final RESULT_TYPE result = task.execute(client, parentObject, opContext); @@ -119,7 +119,7 @@ public static RESULT_TYPE executeWithRet else { // The task may have already parsed an exception. translatedException = task.materializeException(getLastRequestObject(opContext), opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); // throw on non retryable status codes: 501, 505, blob type // mismatch @@ -134,45 +134,45 @@ public static RESULT_TYPE executeWithRet // Retryable translatedException = StorageException .translateException(getLastRequestObject(opContext), e, opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); } catch (final SocketTimeoutException e) { // Retryable translatedException = new StorageException(StorageErrorCodeStrings.OPERATION_TIMED_OUT, "The operation did not complete in the specified time.", -1, null, e); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); } catch (final IOException e) { // Retryable translatedException = StorageException .translateException(getLastRequestObject(opContext), e, opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); } catch (final XMLStreamException e) { // Non Retryable, just throw translatedException = StorageException .translateException(getLastRequestObject(opContext), e, opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); throw translatedException; } catch (final InvalidKeyException e) { // Non Retryable, just throw translatedException = StorageException .translateException(getLastRequestObject(opContext), e, opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); throw translatedException; } catch (final URISyntaxException e) { // Non Retryable, just throw translatedException = StorageException .translateException(getLastRequestObject(opContext), e, opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); throw translatedException; } catch (final TableServiceException e) { task.getResult().setStatusCode(e.getHttpStatusCode()); task.getResult().setStatusMessage(e.getMessage()); - setLastException(opContext, e); + task.getResult().setException(e); if (!e.isRetryable()) { throw e; } @@ -183,20 +183,20 @@ public static RESULT_TYPE executeWithRet catch (final StorageException e) { // Non Retryable, just throw // do not translate StorageException - setLastException(opContext, e); + task.getResult().setException(e); throw e; } catch (final Exception e) { // Non Retryable, just throw translatedException = StorageException .translateException(getLastRequestObject(opContext), e, opContext); - setLastException(opContext, translatedException); + task.getResult().setException(translatedException); throw translatedException; } // Evaluate Retry Policy - retryRes = policy.shouldRetry(currentRetryCount, task.getResult().getStatusCode(), opContext - .getLastResult().getException(), opContext); + retryRes = policy.shouldRetry(currentRetryCount, task.getResult().getStatusCode(), task.getResult() + .getException(), opContext); if (!retryRes.isShouldRetry()) { throw translatedException; } @@ -214,19 +214,21 @@ public static RESULT_TYPE executeWithRet * the request to process * @param opContext * an object used to track the execution of the operation + * @param currResult + * A {@link RequestResult} object that represents the current request result. * @return the input stream from the request * @throws IOException * if there is an error making the connection */ - public static InputStream getInputStream(final HttpURLConnection request, final OperationContext opContext) - throws IOException { - final RequestResult currResult = new RequestResult(); + public static InputStream getInputStream(final HttpURLConnection request, final OperationContext opContext, + final RequestResult currResult) throws IOException { + opContext.setCurrentRequestObject(request); currResult.setStartDate(new Date()); - opContext.getRequestResults().add(currResult); if (opContext.getSendingRequestEventHandler().hasListeners()) { - opContext.getSendingRequestEventHandler().fireEvent(new SendingRequestEvent(opContext, request)); + opContext.getSendingRequestEventHandler() + .fireEvent(new SendingRequestEvent(opContext, request, currResult)); } try { @@ -278,7 +280,8 @@ public static void getResponseCode(final RequestResult currResult, final HttpURL currResult.setContentMD5(BaseResponse.getContentMD5(request)); if (opContext.getResponseReceivedEventHandler().hasListeners()) { - opContext.getResponseReceivedEventHandler().fireEvent(new ResponseReceivedEvent(opContext, request)); + opContext.getResponseReceivedEventHandler().fireEvent( + new ResponseReceivedEvent(opContext, request, currResult)); } } @@ -290,19 +293,20 @@ public static void getResponseCode(final RequestResult currResult, final HttpURL * the request to process * @param opContext * an object used to track the execution of the operation - * @return a RequestResult object representing the status code/ message of the current request + * @param currResult + * A {@link RequestResult} object that represents the current request result. * @throws IOException * if there is an error making the connection */ - public static RequestResult processRequest(final HttpURLConnection request, final OperationContext opContext) - throws IOException { - final RequestResult currResult = new RequestResult(); - currResult.setStartDate(new Date()); - opContext.getRequestResults().add(currResult); + public static void processRequest(final HttpURLConnection request, final OperationContext opContext, + final RequestResult currResult) throws IOException { + opContext.setCurrentRequestObject(request); + currResult.setStartDate(new Date()); if (opContext.getSendingRequestEventHandler().hasListeners()) { - opContext.getSendingRequestEventHandler().fireEvent(new SendingRequestEvent(opContext, request)); + opContext.getSendingRequestEventHandler() + .fireEvent(new SendingRequestEvent(opContext, request, currResult)); } // Send the request @@ -316,25 +320,9 @@ public static RequestResult processRequest(final HttpURLConnection request, fina currResult.setContentMD5(BaseResponse.getContentMD5(request)); if (opContext.getResponseReceivedEventHandler().hasListeners()) { - opContext.getResponseReceivedEventHandler().fireEvent(new ResponseReceivedEvent(opContext, request)); - } - - return currResult; - } - - /** - * Sets the exception on the last request result in a safe way, if there is no last result one is added. - * - * @param opContext - * an object used to track the execution of the operation - * @param exceptionToSet - * the exception to set on the result. - */ - private static void setLastException(final OperationContext opContext, final Exception exceptionToSet) { - if (opContext.getLastResult() == null) { - opContext.getRequestResults().add(new RequestResult()); + opContext.getResponseReceivedEventHandler().fireEvent( + new ResponseReceivedEvent(opContext, request, currResult)); } - opContext.getLastResult().setException(exceptionToSet); } /** diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/StorageOperation.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/StorageOperation.java index 32ff5a00459a0..803bbdfa5481c 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/StorageOperation.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/storage/utils/implementation/StorageOperation.java @@ -109,8 +109,11 @@ public final RequestResult getResult() { /** * Resets the operation status flags between operations. */ - protected final void initialize() { - this.setResult(new RequestResult()); + protected final void initialize(OperationContext opContext) { + RequestResult currResult = new RequestResult(); + this.setResult(currResult); + opContext.appendRequestResult(currResult); + this.setException(null); this.setNonExceptionedRetryableFailure(false); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ConnectionStringSyntaxException.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ConnectionStringSyntaxException.java new file mode 100644 index 0000000000000..4b611302e2caf --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ConnectionStringSyntaxException.java @@ -0,0 +1,29 @@ +/** + * Copyright 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; + +public class ConnectionStringSyntaxException extends Exception { + + private static final long serialVersionUID = 9074252127254835859L; + + public ConnectionStringSyntaxException(String message) { + super(message); + } + + public ConnectionStringSyntaxException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ExportUtils.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ExportUtils.java new file mode 100644 index 0000000000000..d07a57c029418 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ExportUtils.java @@ -0,0 +1,56 @@ +/** + * Copyright 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; + +import java.util.Map; + +/** + * Helper functions useful when creating Exports classses. + * + */ +public abstract class ExportUtils { + + private static String normalizeProfile(String profile) { + if (profile == null || profile.equals("")) { + return ""; + } + + if (profile.endsWith(".")) { + return profile; + } + + return profile + "."; + } + + /** + * Check if the given property exists under the given profile. If + * so, return the value, otherwise return null. + * + * @param profile profile to search + * @param properties the set of property values + * @param propertyName name of desired property + * @return the property value, or null if it is not set. + */ + public static Object getPropertyIfExists(String profile, Map properties, String propertyName) { + String fullPropertyName = normalizeProfile(profile) + propertyName; + + if (properties.containsKey(fullPropertyName)) { + return properties.get(fullPropertyName); + } + return null; + } + +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ParsedConnectionString.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ParsedConnectionString.java new file mode 100644 index 0000000000000..8be49de1b5383 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/ParsedConnectionString.java @@ -0,0 +1,329 @@ +/** + * Copyright 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; + +import com.microsoft.windowsazure.services.core.utils.pipeline.ConnectionStringField; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Base class representing an Azure connection string. This + * provides parsing logic to split the string up into + * the various fields. + */ +public abstract class ParsedConnectionString { + private String connectionString; + private int currentIndex; + private String currentKey; + private String currentValue; + + public ParsedConnectionString(String connectionString) throws ConnectionStringSyntaxException { + // Forcing a separator at the end makes implementation below + // easier - don't have to check for end of string everywhere + this.connectionString = connectionString + ';'; + this.currentIndex = 0; + + matchConnectionString(); + } + + private char currentChar() { + return connectionString.charAt(currentIndex); + } + + private void consumeChar() { + currentIndex++; + } + + private boolean charsLeft() { + return currentIndex < connectionString.length(); + } + + // + // PEG Grammar for a connection string: + // + // ConnectionString <- Attribute (Separator+ Attribute)* Separator* END + // Attribute <- Spacing (KeyValuePair / &Separator) + // KeyValuePair <- Key Equals Spacing Value + // Key <- QuotedKey / RawKey + // QuotedKey <- DoubleQuote (!DoubleQuote .)* DoubleQuote / SingleQuote (!SingleQuote .)* SingleQuote + // RawKey <- (!Equals .)+ + // Equals <- Spacing '=' + // Value <- QuotedValue / RawValue + // QuotedValue <- DoubleQuote (!DoubleQuote .)* DoubleQuote / SingleQuote (!SingleQuote .*) SingleQuote + // RawValue <- (!Separator .)* + // Separator <- Spacing ';' + // Spacing <- WS* + // WS <- ' ' / '\t' + // END <- !. + // + + private boolean matchConnectionString() throws ConnectionStringSyntaxException { + if (!matchAttribute()) { + throw new ConnectionStringSyntaxException(String.format( + "Could not parse connection string '%1$s'", connectionString)); + } + + boolean moreAttributes = true; + int bookmark; + + while (moreAttributes) { + bookmark = currentIndex; + boolean separators = false; + while (matchSeparator()) { + separators = true; + } + moreAttributes = separators && matchAttribute(); + if (!moreAttributes) { + currentIndex = bookmark; + } + } + + while (matchSeparator()) { + } + + if (!matchEND()) { + throw new ConnectionStringSyntaxException(String.format( + "Expected end of connection string '%1$s', did not get it", connectionString)); + } + + return true; + } + + private boolean matchAttribute() throws ConnectionStringSyntaxException { + matchSpacing(); + if (matchKeyValuePair()) { + return true; + } + int bookmark = currentIndex; + boolean matchedSeparator = matchSeparator(); + currentIndex = bookmark; + return matchedSeparator; + } + + private boolean matchKeyValuePair() throws ConnectionStringSyntaxException { + if (!charsLeft()) { + return false; + } + if (!matchKey()) { + throw new ConnectionStringSyntaxException(String.format( + "Expected key in connection string '%1$s' at position %2$d but did not find one", + connectionString, currentIndex)); + } + if (!matchEquals()) { + throw new ConnectionStringSyntaxException(String.format( + "Expected '=' character in connection string '%1$s' after key near position %2$d", + connectionString, currentIndex)); + } + if (!matchValue()) { + throw new ConnectionStringSyntaxException(String.format( + "Expected value in connection string '%1$s' for key '%3$s' at position %2$d but did not find one", + connectionString, currentIndex, currentKey)); + } + + saveValue(currentKey, currentValue); + return true; + } + + private boolean matchKey() throws ConnectionStringSyntaxException { + return matchQuotedKey() || matchRawKey(); + } + + private boolean matchQuotedKey() throws ConnectionStringSyntaxException { + if (!charsLeft()) { + return false; + } + String value = ""; + char quote = currentChar(); + int bookmark = currentIndex; + + if (quote == '"' || quote == '\'') { + consumeChar(); + while (charsLeft() && currentChar() != quote) { + value += currentChar(); + consumeChar(); + } + if (!charsLeft()) { + throw new ConnectionStringSyntaxException(String.format( + "Unterminated quoted value in string '%1$s', starting at character %2$d", connectionString, bookmark)); + } + consumeChar(); + currentKey = value; + return true; + } else { + return false; + } + } + + private boolean matchRawKey() throws ConnectionStringSyntaxException { + if (!charsLeft()) { + return false; + } + + String value = ""; + int bookmark = currentIndex; + + while (charsLeft() && !matchEquals()) { + value += currentChar(); + consumeChar(); + bookmark = currentIndex; + } + + if (!charsLeft()) { + throw new ConnectionStringSyntaxException(String.format( + "Expected '=' in connection string '%1$s', key started at index %2$d", connectionString, bookmark + )); + } + + currentIndex = bookmark; + currentKey = value; + return true; + } + + private boolean matchEquals() { + int bookmark = currentIndex; + matchSpacing(); + if (charsLeft() && currentChar() == '=') { + consumeChar(); + return true; + } + currentIndex = bookmark; + return false; + } + + private boolean matchValue() throws ConnectionStringSyntaxException { + return matchQuotedValue() || matchRawValue(); + } + + private boolean matchQuotedValue() throws ConnectionStringSyntaxException { + String value = ""; + char quote = currentChar(); + int bookmark = currentIndex; + + if (quote == '"' || quote == '\'') { + consumeChar(); + while (charsLeft() && currentChar() != quote) { + value += currentChar(); + consumeChar(); + } + if (!charsLeft()) { + throw new ConnectionStringSyntaxException(String.format( + "Unterminated quoted value in string '%1$s', starting at character %2$d", connectionString, bookmark)); + } + consumeChar(); + currentValue = value; + return true; + } else { + return false; + } + } + + private boolean matchRawValue() { + String value = ""; + int bookmark = currentIndex; + + while (charsLeft() && !matchSeparator()) { + value += currentChar(); + consumeChar(); + bookmark = currentIndex; + } + currentIndex = bookmark; + currentValue = value; + return true; + } + + private boolean matchSeparator() { + int bookmark = currentIndex; + matchSpacing(); + if (charsLeft() && currentChar() == ';') { + consumeChar(); + return true; + } + currentIndex = bookmark; + return false; + } + + private boolean matchSpacing() { + while (matchWS()) { + } + return true; + } + + private boolean matchWS() { + if (charsLeft() && (currentChar() == ' ' || currentChar() == '\t')) { + consumeChar(); + return true; + } + return false; + } + + private boolean matchEND() { + return !(currentIndex < connectionString.length()); + } + + /** + * Store the value for the given key. + * + * Default implementation looks for a property setter with the + * matching name or the @ConnectionStringField annotation on the + * setter method to set the field. You can override this method + * for other behavior. + * + * @param key Key to store value under. If keys repeat, older values are overwritten. + * @param value value to associate with the key. + * + * @throws ConnectionStringSyntaxException + */ + protected void saveValue(String key, String value) throws ConnectionStringSyntaxException { + Method setter; + try { + setter = findSetter(key); + setter.invoke(this, value); + } catch (NoSuchMethodException e) { + throw new ConnectionStringSyntaxException(String.format( + "The key '%1$s' is not valid for this connection string", key), e); + } catch (InvocationTargetException e) { + throw new ConnectionStringSyntaxException(String.format( + "Could not invoke setter for key '%1$s'", key), e); + } catch (IllegalAccessException e) { + throw new ConnectionStringSyntaxException(String.format( + "Setter for key '%1$s' is not accessible in class %2$s", key, getClass().getName()), e); + } + } + + private Method findSetter(String key) throws NoSuchMethodException { + Class thisClass = getClass(); + for (Method m : thisClass.getDeclaredMethods()) { + if (methodMatches(m, key)) { + return m; + } + } + throw new NoSuchMethodException(); + } + + private boolean methodMatches(Method method, String key) { + return matchesViaAnnotation(method, key) || matchesByName(method, key); + } + + private boolean matchesViaAnnotation(Method method, String key) { + ConnectionStringField annotation = method.getAnnotation(ConnectionStringField.class); + return annotation != null && annotation.name().toLowerCase().equals(key.toLowerCase()); + } + + private boolean matchesByName(Method method, String key) { + return method.getName().toLowerCase().equals("set" + key.toLowerCase()); + } +} 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 2efac14c00b04..2d7a029c30c71 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 @@ -28,7 +28,7 @@ public static ServiceException process(String serviceName, ServiceException exce Throwable cause = exception.getCause(); for (Throwable scan = cause; scan != null; scan = scan.getCause()) { - Class scanClass = scan.getClass(); + Class scanClass = scan.getClass(); if (ServiceException.class.isAssignableFrom(scanClass)) { return populate(exception, serviceName, (ServiceException) scan); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/ConnectionStringField.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/ConnectionStringField.java new file mode 100644 index 0000000000000..ef773b7054655 --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/core/utils/pipeline/ConnectionStringField.java @@ -0,0 +1,33 @@ +/** + * Copyright 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 java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Annotation used to mark method setters to be used + * when the field name in the connection string isn't + * a valid Java method name. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ConnectionStringField { + public String name(); +} 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 23b7ae8215268..4acda86f735b6 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 @@ -23,6 +23,8 @@ import com.sun.jersey.api.client.config.ClientConfig; import com.sun.jersey.api.client.config.DefaultClientConfig; +import static com.microsoft.windowsazure.services.core.utils.ExportUtils.getPropertyIfExists; + public class Exports implements Builder.Exports { @Override @@ -71,25 +73,4 @@ public HttpURLConnectionClient create(String profile, Builder builder, Map properties, String propertyName) { - String fullPropertyName = normalizeProfile(profile) + propertyName; - - if (properties.containsKey(fullPropertyName)) { - return properties.get(fullPropertyName); - } - return null; - } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java index dfd199c90b9bc..f2c6e3afbc287 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/Exports.java @@ -20,6 +20,7 @@ import javax.xml.parsers.ParserConfigurationException; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.media.implementation.MediaContentProvider; import com.microsoft.windowsazure.services.media.implementation.MediaExceptionProcessor; import com.microsoft.windowsazure.services.media.implementation.MediaRestProxy; @@ -50,6 +51,7 @@ public void register(Builder.Registry registry) { registry.add(ResourceLocationManager.class); registry.add(RedirectFilter.class); registry.add(VersionHeadersFilter.class); + registry.add(UserAgentFilter.class); registry.alter(ClientConfig.class, new Builder.Alteration() { @SuppressWarnings("rawtypes") diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java index f25537df87f46..e85fd9803b60c 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java @@ -22,6 +22,9 @@ */ public class MediaConfiguration { + private MediaConfiguration() { + } + /** * Defines the media service configuration URI constant. * diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityContract.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityContract.java index d42fcdc14d30a..67c539bfe63ed 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityContract.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityContract.java @@ -38,7 +38,7 @@ public interface EntityContract { * the service exception * The created entity */ - public abstract T create(EntityCreateOperation creator) throws ServiceException; + T create(EntityCreateOperation creator) throws ServiceException; /** * Retrieve an existing entity by id. @@ -51,7 +51,7 @@ public interface EntityContract { * @throws ServiceException * the service exception */ - public abstract T get(EntityGetOperation getter) throws ServiceException; + T get(EntityGetOperation getter) throws ServiceException; /** * Retrieve a list of entities. @@ -64,7 +64,7 @@ public interface EntityContract { * @throws ServiceException * the service exception */ - public abstract ListResult list(EntityListOperation lister) throws ServiceException; + ListResult list(EntityListOperation lister) throws ServiceException; /** * Update an existing entity. @@ -74,7 +74,7 @@ public interface EntityContract { * @throws ServiceException * the service exception */ - public abstract void update(EntityUpdateOperation updater) throws ServiceException; + void update(EntityUpdateOperation updater) throws ServiceException; /** * Delete an entity. @@ -84,7 +84,7 @@ public interface EntityContract { * @throws ServiceException * the service exception */ - public abstract void delete(EntityDeleteOperation deleter) throws ServiceException; + void delete(EntityDeleteOperation deleter) throws ServiceException; /** * Perform an action on an entity. @@ -94,7 +94,7 @@ public interface EntityContract { * @throws ServiceException * the service exception */ - public abstract void action(EntityActionOperation action) throws ServiceException; + void action(EntityActionOperation action) throws ServiceException; /** * Action. @@ -107,6 +107,6 @@ public interface EntityContract { * @throws ServiceException * the service exception */ - public abstract T action(EntityTypeActionOperation entityActionOperation) throws ServiceException; + T action(EntityTypeActionOperation entityActionOperation) throws ServiceException; } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperation.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperation.java index 6ac4b38c6f08f..4317bd39f08d2 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperation.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperation.java @@ -25,16 +25,15 @@ public interface EntityOperation { * Supplies the current proxy information to the action. * * @param proxyData - * @return */ - public void setProxyData(EntityProxyData proxyData); + void setProxyData(EntityProxyData proxyData); /** * Get the URI the creation request should be sent to. * * @return The uri */ - public abstract String getUri(); + String getUri(); /** * Get the MIME type for the content that's being sent to the server. @@ -42,12 +41,12 @@ public interface EntityOperation { * @return The MIME type * @throws ServiceException */ - public abstract MediaType getContentType(); + MediaType getContentType(); /** * Get the MIME type that we're expecting the server to send back. */ - public abstract MediaType getAcceptType(); + MediaType getAcceptType(); /** * Process response process. @@ -58,5 +57,5 @@ public interface EntityOperation { * @throws ServiceException * the service exception */ - public abstract Object processResponse(Object rawResponse) throws ServiceException; + Object processResponse(Object rawResponse) throws ServiceException; } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperationSingleResult.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperationSingleResult.java index f3eeb0141d637..67586641b5f8b 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperationSingleResult.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/entityoperations/EntityOperationSingleResult.java @@ -22,5 +22,5 @@ public interface EntityOperationSingleResult extends EntityOperation { * * @return Class object for response. */ - public abstract Class getResponseClass(); + Class getResponseClass(); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaBatchOperations.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaBatchOperations.java index 85a9dce36971b..f3798aed41e2b 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaBatchOperations.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaBatchOperations.java @@ -61,6 +61,10 @@ */ public class MediaBatchOperations { + private static final int BUFFER_SIZE = 1024; + + private static final int HTTP_ERROR = 400; + /** The operations. */ private final List entityBatchOperations; @@ -138,7 +142,7 @@ private List createRequestBody() throws JAXBException { */ private int addJobPart(List bodyPartContents, URI jobURI, int contentId) throws JAXBException { int jobContentId = contentId; - ValidateJobOperation(); + validateJobOperation(); for (EntityBatchOperation entityBatchOperation : entityBatchOperations) { DataSource bodyPartContent = null; @@ -157,7 +161,7 @@ private int addJobPart(List bodyPartContents, URI jobURI, int conten return jobContentId; } - private void ValidateJobOperation() { + private void validateJobOperation() { int jobCount = 0; for (EntityBatchOperation entityBatchOperation : entityBatchOperations) { if (entityBatchOperation instanceof Job.CreateBatchOperation) { @@ -324,7 +328,7 @@ public void parseBatchResult(ClientResponse response) throws IOException, Servic InternetHeaders headers = parseHeaders(ds); InputStream content = parseEntity(ds); - if (status.getStatus() >= 400) { + if (status.getStatus() >= HTTP_ERROR) { InBoundHeaders inBoundHeaders = new InBoundHeaders(); @SuppressWarnings("unchecked") @@ -520,11 +524,12 @@ private void appendHeaders(OutputStream outputStream, InternetHeaders internetHe */ private void appendEntity(OutputStream outputStream, ByteArrayInputStream byteArrayInputStream) { try { - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[BUFFER_SIZE]; while (true) { int bytesRead = byteArrayInputStream.read(buffer); - if (bytesRead <= 0) + if (bytesRead <= 0) { break; + } outputStream.write(buffer, 0, bytesRead); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaContentProvider.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaContentProvider.java index 9e04edf56d038..eae063529e67d 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaContentProvider.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaContentProvider.java @@ -21,7 +21,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.xml.bind.JAXBException; @@ -56,8 +55,7 @@ public boolean isReadable(Class type, Type genericType, Annotation[] annotati @Override public T readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, InputStream entityStream) throws IOException, - WebApplicationException { + MultivaluedMap httpHeaders, InputStream entityStream) throws IOException { throw new UnsupportedOperationException(); } @@ -68,8 +66,7 @@ public boolean isWriteable(Class type, Type genericType, Annotation[] annotat @Override public void writeTo(T t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException, - WebApplicationException { + MultivaluedMap httpHeaders, OutputStream entityStream) throws IOException { try { marshaller.marshalEntry(t, entityStream); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java index cb8480f28920b..aa756c90f0c83 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/MediaRestProxy.java @@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory; import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.pipeline.ClientConfigSettings; import com.microsoft.windowsazure.services.media.MediaContract; import com.microsoft.windowsazure.services.media.WritableBlobContainerContract; @@ -58,13 +59,16 @@ public class MediaRestProxy extends EntityRestProxy implements MediaContract { * the redirect filter * @param versionHeadersFilter * the version headers filter + * @param userAgentFilter + * the user agent filter * @param clientConfigSettings * Currently configured HTTP client settings * */ @Inject public MediaRestProxy(Client channel, OAuthFilter authFilter, RedirectFilter redirectFilter, - VersionHeadersFilter versionHeadersFilter, ClientConfigSettings clientConfigSettings) { + VersionHeadersFilter versionHeadersFilter, UserAgentFilter userAgentFilter, + ClientConfigSettings clientConfigSettings) { super(channel, new ServiceFilter[0]); this.clientConfigSettings = clientConfigSettings; @@ -72,6 +76,7 @@ public MediaRestProxy(Client channel, OAuthFilter authFilter, RedirectFilter red channel.addFilter(redirectFilter); channel.addFilter(authFilter); channel.addFilter(versionHeadersFilter); + channel.addFilter(userAgentFilter); } /** diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java index ef2982aa2c170..603e9b0caeb11 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java @@ -38,7 +38,7 @@ public interface OAuthContract { * @return OAuthTokenResponse * @throws ServiceException */ - public OAuthTokenResponse getAccessToken(URI oAuthUri, String clientId, String clientSecret, String scope) + OAuthTokenResponse getAccessToken(URI oAuthUri, String clientId, String clientSecret, String scope) throws ServiceException; } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java index 81d50e6a6bfc4..dff2e042c7714 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java @@ -41,7 +41,7 @@ public OAuthFilter(OAuthTokenManager oAuthTokenManager) { /* (non-Javadoc) * @see com.microsoft.windowsazure.services.core.IdempotentClientFilter#doHandle(com.sun.jersey.api.client.ClientRequest) */@Override - public ClientResponse doHandle(ClientRequest clientRequest) throws ClientHandlerException { + public ClientResponse doHandle(ClientRequest clientRequest) { String accessToken; try { accessToken = oAuthTokenManager.getAccessToken(); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java index ecf179072bc59..77bc0ce745896 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java @@ -28,6 +28,7 @@ import org.codehaus.jackson.type.TypeReference; import com.microsoft.windowsazure.services.core.ServiceException; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.ServiceExceptionFactory; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; @@ -41,13 +42,14 @@ public class OAuthRestProxy implements OAuthContract { Client channel; - private final String _grantType = "client_credentials"; + private final String grantType = "client_credentials"; static Log log = LogFactory.getLog(OAuthContract.class); @Inject - public OAuthRestProxy(Client channel) { + public OAuthRestProxy(Client channel, UserAgentFilter userAgentFilter) { this.channel = channel; + channel.addFilter(userAgentFilter); } /** @@ -76,7 +78,7 @@ public OAuthTokenResponse getAccessToken(URI oAuthUri, String clientId, String c ClientResponse clientResponse; String responseJson; - requestForm.add("grant_type", _grantType); + requestForm.add("grant_type", grantType); requestForm.add("client_id", clientId); requestForm.add("client_secret", clientSecret); requestForm.add("scope", scope); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java index bc8d3622e0688..1a124d4dd6626 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java @@ -23,10 +23,10 @@ */ public class OAuthTokenResponse { - private String _accessToken; - private String _scope; - private String _tokenType; - private long _expiresIn; + private String accessToken; + private String scope; + private String tokenType; + private long expiresIn; /** * Sets the token type. @@ -35,41 +35,41 @@ public class OAuthTokenResponse { */ @JsonProperty("token_type") public void setTokenType(String tokenType) { - _tokenType = tokenType; + this.tokenType = tokenType; } @JsonProperty("token_type") public String getTokenType() { - return _tokenType; + return tokenType; } @JsonProperty("expires_in") public long getExpiresIn() { - return _expiresIn; + return expiresIn; } @JsonProperty("expires_in") public void setExpiresIn(long expiresIn) { - _expiresIn = expiresIn; + this.expiresIn = expiresIn; } @JsonProperty("access_token") public String getAccessToken() { - return _accessToken; + return accessToken; } @JsonProperty("access_token") public void setAccessToken(String accessToken) { - _accessToken = accessToken; + this.accessToken = accessToken; } @JsonProperty("scope") public String getScope() { - return _scope; + return scope; } @JsonProperty("scope") public void setScope(String scope) { - _scope = scope; + this.scope = scope; } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataDateAdapter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataDateAdapter.java index c09aa98d873dc..a23d7a712ddac 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataDateAdapter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataDateAdapter.java @@ -30,14 +30,14 @@ */ public class ODataDateAdapter extends XmlAdapter { - private final static Pattern hasTimezoneRegex; - private final static TimeZone utc; + private static final Pattern HAS_TIMEZONE_REGEX; + private static final TimeZone UTC; static { - hasTimezoneRegex = Pattern.compile("^.*(\\+|-)\\d\\d:\\d\\d$"); + HAS_TIMEZONE_REGEX = Pattern.compile("^.*(\\+|-)\\d\\d:\\d\\d$"); - utc = TimeZone.getDefault(); - utc.setRawOffset(0); + UTC = TimeZone.getDefault(); + UTC.setRawOffset(0); } @Override @@ -53,11 +53,11 @@ public Date unmarshal(String dateString) throws Exception { public String marshal(Date date) throws Exception { Calendar dateToMarshal = Calendar.getInstance(); dateToMarshal.setTime(date); - dateToMarshal.setTimeZone(utc); + dateToMarshal.setTimeZone(UTC); return DatatypeConverter.printDateTime(dateToMarshal); } private boolean hasTimezone(String dateString) { - return dateString.endsWith("Z") || hasTimezoneRegex.matcher(dateString).matches(); + return dateString.endsWith("Z") || HAS_TIMEZONE_REGEX.matcher(dateString).matches(); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntity.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntity.java index c89f3453c89d8..65765129905bb 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntity.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntity.java @@ -89,7 +89,7 @@ public boolean hasLink(String rel) { public > LinkInfo getLink(String rel) { for (Object child : entry.getEntryChildren()) { - LinkType link = LinkFromChild(child); + LinkType link = linkFromChild(child); if (link != null && link.getRel().equals(rel)) { return new LinkInfo(link); } @@ -109,14 +109,14 @@ public > LinkInfo getRelationLink(String relationNam } @SuppressWarnings("rawtypes") - private static LinkType LinkFromChild(Object child) { + private static LinkType linkFromChild(Object child) { if (child instanceof JAXBElement) { - return LinkFromElement((JAXBElement) child); + return linkFromElement((JAXBElement) child); } return null; } - private static LinkType LinkFromElement(@SuppressWarnings("rawtypes") JAXBElement element) { + private static LinkType linkFromElement(@SuppressWarnings("rawtypes") JAXBElement element) { if (element.getDeclaredType() == LinkType.class) { return (LinkType) element.getValue(); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityCollectionProvider.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityCollectionProvider.java index 5b04e13ce4e77..1a63e2f3c99e3 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityCollectionProvider.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityCollectionProvider.java @@ -21,7 +21,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.xml.bind.JAXBException; @@ -50,7 +49,7 @@ public boolean isReadable(Class type, Type genericType, Annotation[] annotati @Override public ListResult> readFrom(Class>> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, - InputStream entityStream) throws IOException, WebApplicationException { + InputStream entityStream) throws IOException { String responseType = mediaType.getParameters().get("type"); try { @@ -89,7 +88,7 @@ public boolean isWriteable(Class type, Type genericType, Annotation[] annotat @Override public void writeTo(ListResult> t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) - throws IOException, WebApplicationException { + throws IOException { throw new UnsupportedOperationException(); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityProvider.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityProvider.java index 0a21506085605..c879f1e5ee947 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityProvider.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/ODataEntityProvider.java @@ -22,7 +22,6 @@ import java.lang.reflect.Type; import java.util.List; -import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import javax.xml.bind.JAXBException; @@ -57,7 +56,7 @@ public boolean isReadable(Class type, Type genericType, Annotation[] annotati @Override public ODataEntity readFrom(Class> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) - throws IOException, WebApplicationException { + throws IOException { ODataEntity result = null; String responseType = mediaType.getParameters().get("type"); @@ -97,7 +96,7 @@ public boolean isWriteable(Class type, Type genericType, Annotation[] annotat @Override public void writeTo(ODataEntity t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream) - throws IOException, WebApplicationException { + throws IOException { throw new UnsupportedOperationException(); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/RedirectFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/RedirectFilter.java index 433e5ec7e6e89..6efebe7453d9c 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/RedirectFilter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/RedirectFilter.java @@ -34,7 +34,7 @@ public RedirectFilter(ResourceLocationManager locationManager) { * @see com.microsoft.windowsazure.services.core.IdempotentClientFilter#doHandle(com.sun.jersey.api.client.ClientRequest) */ @Override - public ClientResponse doHandle(ClientRequest request) throws ClientHandlerException { + public ClientResponse doHandle(ClientRequest request) { if (request == null) { throw new IllegalArgumentException("Request should not be null"); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java index f5c3ef493a686..400b304a07d6c 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java @@ -15,12 +15,9 @@ package com.microsoft.windowsazure.services.media.implementation; -import java.net.URISyntaxException; - import javax.ws.rs.core.UriBuilder; import com.microsoft.windowsazure.services.core.IdempotentClientFilter; -import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; import com.sun.jersey.api.client.ClientResponse; @@ -37,7 +34,6 @@ public class SASTokenFilter extends IdempotentClientFilter { * * @param sasUrl * URL containing authentication information - * @throws URISyntaxException */ public SASTokenFilter(String sasToken) { this.sasToken = sasToken; @@ -47,7 +43,7 @@ public SASTokenFilter(String sasToken) { * @see com.microsoft.windowsazure.services.core.IdempotentClientFilter#doHandle(com.sun.jersey.api.client.ClientRequest) */ @Override - public ClientResponse doHandle(ClientRequest cr) throws ClientHandlerException { + public ClientResponse doHandle(ClientRequest cr) { UriBuilder newUri = UriBuilder.fromUri(cr.getURI()); String currentQuery = cr.getURI().getRawQuery(); if (currentQuery == null) { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/StatusLine.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/StatusLine.java index d3fabaa0c4606..70be929297edc 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/StatusLine.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/StatusLine.java @@ -24,6 +24,7 @@ import com.sun.mail.util.LineInputStream; public class StatusLine { + private static final int DELIMITER = -1; private int status; private String reason; @@ -37,7 +38,7 @@ public static StatusLine create(DataSource dataSource) { expect(lineReader, "HTTP/1.1"); expect(lineReader, " "); String statusString = extractInput(lineReader, ' '); - String reason = extractInput(lineReader, -1); + String reason = extractInput(lineReader, DELIMITER); return new StatusLine().setStatus(Integer.parseInt(statusString)).setReason(reason); } @@ -72,8 +73,9 @@ private static String extractInput(Reader reader, int delimiter) { StringBuilder sb = new StringBuilder(); while (true) { int ch = reader.read(); - if (ch == -1 || ch == delimiter) + if (ch == DELIMITER || ch == delimiter) { break; + } sb.append((char) ch); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java index d21e3852162c4..84b1a670a763a 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java @@ -18,7 +18,6 @@ import javax.ws.rs.core.MultivaluedMap; import com.microsoft.windowsazure.services.core.IdempotentClientFilter; -import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; import com.sun.jersey.api.client.ClientResponse; @@ -33,7 +32,7 @@ public class VersionHeadersFilter extends IdempotentClientFilter { * @see com.microsoft.windowsazure.services.core.IdempotentClientFilter#doHandle(com.sun.jersey.api.client.ClientRequest) */ @Override - public ClientResponse doHandle(ClientRequest cr) throws ClientHandlerException { + public ClientResponse doHandle(ClientRequest cr) { MultivaluedMap headers = cr.getHeaders(); headers.add("DataServiceVersion", "3.0"); headers.add("MaxDataServiceVersion", "3.0"); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/Constants.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/Constants.java index b713aedf0961d..a6e75b29512a0 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/Constants.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/Constants.java @@ -23,7 +23,11 @@ * media services entities. */ -public class Constants { +public final class Constants { + + private Constants() { + } + /** * XML Namespace for Atom syndication format, as defined by IETF RFC 4287 */ diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskHistoricalEventType.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskHistoricalEventType.java new file mode 100644 index 0000000000000..973b9b53c3e2c --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskHistoricalEventType.java @@ -0,0 +1,107 @@ +/** + * Copyright 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.media.implementation.content; + +import java.util.Date; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * This type maps the XML returned in the odata ATOM serialization + * for ErrorDetail entities. + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +public class TaskHistoricalEventType implements MediaServiceDTO { + + /** The code. */ + @XmlElement(name = "Code", namespace = Constants.ODATA_DATA_NS) + protected String code; + + /** The message. */ + @XmlElement(name = "Message", namespace = Constants.ODATA_DATA_NS) + protected String message; + + /** The time stamp. */ + @XmlElement(name = "TimeStamp", namespace = Constants.ODATA_DATA_NS) + protected Date timeStamp; + + /** + * Gets the code. + * + * @return the code + */ + public String getCode() { + return code; + } + + /** + * Sets the code. + * + * @param code + * the id to set + * @return the error detail type + */ + public TaskHistoricalEventType setCode(String code) { + this.code = code; + return this; + } + + /** + * Gets the message. + * + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * Sets the message. + * + * @param message + * the message to set + * @return the error detail type + */ + public TaskHistoricalEventType setMessage(String message) { + this.message = message; + return this; + } + + /** + * Gets the time stamp. + * + * @return the time stamp + */ + public Date getTimeStamp() { + return timeStamp; + } + + /** + * Sets the time stamp. + * + * @param timeStamp + * the time stamp + * @return the task historical event type + */ + public TaskHistoricalEventType setTimeStamp(Date timeStamp) { + this.timeStamp = timeStamp; + return this; + } + +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskType.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskType.java index 9436ca9ab0255..e6486eb697d0b 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskType.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/implementation/content/TaskType.java @@ -44,6 +44,10 @@ public class TaskType implements MediaServiceDTO { @XmlElement(name = "element", namespace = Constants.ODATA_DATA_NS) protected List errorDetails; + @XmlElementWrapper(name = "HistoricalEvents", namespace = Constants.ODATA_DATA_NS) + @XmlElement(name = "element", namespace = Constants.ODATA_DATA_NS) + protected List historicalEventTypes; + @XmlElement(name = "MediaProcessorId", namespace = Constants.ODATA_DATA_NS) protected String mediaProcessorId; @@ -269,4 +273,13 @@ public TaskType setInputMediaAssets(List inputMediaAssets) { this.inputMediaAssets = inputMediaAssets; return this; } + + public List getHistoricalEventTypes() { + return historicalEventTypes; + } + + public TaskType setHistoricalEventTypes(List historicalEventTypes) { + this.historicalEventTypes = historicalEventTypes; + return this; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ContentKey.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ContentKey.java index 4d93a5e773567..fea8d2ba62e2b 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ContentKey.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ContentKey.java @@ -172,7 +172,7 @@ public Creator setProtectionKeyType(ProtectionKeyType protectionKeyType) { /** * Create an operation that will retrieve the given content key. * - * @param ContentKeyId + * @param contentKeyId * id of content key to retrieve * @return the operation */ @@ -205,7 +205,7 @@ public static DefaultListOperation list(LinkInfo /** * Create an operation to delete the given content key. * - * @param ContentKeyId + * @param contentKeyId * id of content key to delete * @return the delete operation */ diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ProtectionKey.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ProtectionKey.java index 7b9a6bb15d1c5..5ec69e13bf6aa 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ProtectionKey.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/ProtectionKey.java @@ -37,6 +37,9 @@ */ public class ProtectionKey { + private ProtectionKey() { + } + /** * Gets the protection key id. * diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskHistoricalEvent.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskHistoricalEvent.java new file mode 100644 index 0000000000000..14d44fc85142e --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskHistoricalEvent.java @@ -0,0 +1,76 @@ +/* + * Copyright 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.media.models; + +import java.util.Date; + +/** + * The Class TaskHistoricalEvent. + */ +public class TaskHistoricalEvent { + + /** The code. */ + private final String code; + + /** The message. */ + private final String message; + + /** The time stamp. */ + private final Date timeStamp; + + /** + * Instantiates a new error detail. + * + * @param code + * the code + * @param message + * the message + * @param timeStamp + * the time stamp + */ + public TaskHistoricalEvent(String code, String message, Date timeStamp) { + this.code = code; + this.message = message; + this.timeStamp = timeStamp; + } + + /** + * Gets the code. + * + * @return the code + */ + public String getCode() { + return this.code; + } + + /** + * Gets the message. + * + * @return the message + */ + public String getMessage() { + return this.message; + } + + /** + * Gets the time stamp. + * + * @return the time stamp + */ + public Date getTimeStamp() { + return this.timeStamp; + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskInfo.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskInfo.java index 8e8c3cd110877..6f22c00bb7697 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskInfo.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/media/models/TaskInfo.java @@ -22,6 +22,7 @@ import com.microsoft.windowsazure.services.media.implementation.ODataEntity; import com.microsoft.windowsazure.services.media.implementation.atom.EntryType; import com.microsoft.windowsazure.services.media.implementation.content.ErrorDetailType; +import com.microsoft.windowsazure.services.media.implementation.content.TaskHistoricalEventType; import com.microsoft.windowsazure.services.media.implementation.content.TaskType; /** @@ -86,6 +87,30 @@ public List getErrorDetails() { return null; } + /** + * Gets the task historical events. + * + * @return the task historical events + */ + public List getHistoricalEvents() { + List result = new ArrayList(); + List historicalEventTypes = getContent().getHistoricalEventTypes(); + + if (historicalEventTypes != null) { + for (TaskHistoricalEventType taskHistoricalEventType : historicalEventTypes) { + String message = taskHistoricalEventType.getMessage(); + if ((message != null) && (message.isEmpty())) { + message = null; + } + TaskHistoricalEvent taskHistoricalEvent = new TaskHistoricalEvent(taskHistoricalEventType.getCode(), + message, taskHistoricalEventType.getTimeStamp()); + result.add(taskHistoricalEvent); + } + } + + return result; + } + /** * Gets the media processor id. * @@ -213,7 +238,7 @@ public String getInitializationVector() { } /** - * Gets link to the task's input assets + * Gets link to the task's input assets. * * @return the link */ @@ -222,7 +247,7 @@ public LinkInfo getInputAssetsLink() { } /** - * Gets link to the task's output assets + * Gets link to the task's output assets. * * @return the link */ diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/Exports.java index 3d57a69f82c7a..3be2f2909feee 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/Exports.java @@ -2,19 +2,20 @@ * Copyright 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.queue; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.queue.implementation.QueueExceptionProcessor; import com.microsoft.windowsazure.services.queue.implementation.QueueRestProxy; import com.microsoft.windowsazure.services.queue.implementation.SharedKeyFilter; @@ -28,5 +29,6 @@ public void register(Builder.Registry registry) { registry.add(QueueRestProxy.class); registry.add(SharedKeyLiteFilter.class); registry.add(SharedKeyFilter.class); + registry.add(UserAgentFilter.class); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueue.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueue.java index 93771ce03de9e..c29f1067844c6 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueue.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueue.java @@ -220,7 +220,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final final OutputStream outStreamRef = request.getOutputStream(); outStreamRef.write(messageBytes); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); @@ -286,7 +286,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -351,7 +351,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final QueueRequest.addMetadata(request, queue.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED && this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { @@ -424,7 +424,7 @@ public Boolean execute(final CloudQueueClient client, final CloudQueue queue, QueueRequest.addMetadata(request, queue.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CREATED) { return true; @@ -509,7 +509,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -580,7 +580,7 @@ public Boolean execute(final CloudQueueClient client, final CloudQueue queue, client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NO_CONTENT) { return true; @@ -667,7 +667,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -733,7 +733,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -806,7 +806,7 @@ public Boolean execute(final CloudQueueClient client, final CloudQueue queue, client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { return Boolean.valueOf(true); @@ -1021,7 +1021,7 @@ public ArrayList execute(final CloudQueueClient client, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1155,7 +1155,7 @@ public ArrayList execute(final CloudQueueClient client, final client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1293,7 +1293,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final client.getCredentials().signRequest(request, 0L); } - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -1366,7 +1366,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final QueueRequest.addMetadata(request, queue.metadata, opContext); client.getCredentials().signRequest(request, 0L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -1445,7 +1445,7 @@ public Void execute(final CloudQueueClient client, final CloudQueue queue, final final OutputStream outStreamRef = request.getOutputStream(); outStreamRef.write(aclBytes); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -1515,7 +1515,7 @@ public QueuePermissions execute(final CloudQueueClient client, final CloudQueue client.getCredentials().signRequest(request, -1L); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); @@ -1545,11 +1545,11 @@ public QueuePermissions execute(final CloudQueueClient client, final CloudQueue * A queue-level access policy. * @return A shared access signature for the queue. * @throws InvalidKeyException - * If an invalid key was passed. + * If an invalid key was passed. * @throws StorageException - * If a storage service error occurred. + * If a storage service error occurred. * @throws IllegalArgumentException - * If an unexpected value is passed. + * If an unexpected value is passed. */ public String generateSharedAccessSignature(final SharedAccessQueuePolicy policy, final String groupPolicyIdentifier) throws InvalidKeyException, StorageException { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClient.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClient.java index 0ca46aaf25bc3..addec40b3b9cd 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClient.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClient.java @@ -227,7 +227,7 @@ ResultSegment listQueuesCore(final String prefix, final QueueListing this.getCredentials().signRequest(listQueueRequest, -1L); - taskReference.setResult(ExecutionEngine.processRequest(listQueueRequest, opContext)); + ExecutionEngine.processRequest(listQueueRequest, opContext, taskReference.getResult()); if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { taskReference.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/SharedAccessQueuePolicy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/SharedAccessQueuePolicy.java index cd6b9085b4de7..77ffca21efd7b 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/SharedAccessQueuePolicy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/client/SharedAccessQueuePolicy.java @@ -75,7 +75,7 @@ public static EnumSet permissionsFromString(final * A {@link SharedAccessQueuePermissions} object that represents the shared access permissions. * * @return A String that represents the shared access permissions in the "rwdl" format, which is - * described at {@link SharedAccessQueuePermissions#permissionsFromString}. + * described at {@link SharedAccessQueuePolicy#permissionsFromString(String)}. */ public static String permissionsToString(final EnumSet permissions) { if (permissions == null) { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/implementation/QueueRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/implementation/QueueRestProxy.java index 4b038a023b20d..5f3c663c37db3 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/implementation/QueueRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/queue/implementation/QueueRestProxy.java @@ -2,15 +2,15 @@ * Copyright 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.queue.implementation; @@ -24,6 +24,7 @@ import com.microsoft.windowsazure.services.blob.implementation.RFC1123DateConverter; import com.microsoft.windowsazure.services.core.ServiceException; import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.pipeline.ClientFilterAdapter; import com.microsoft.windowsazure.services.core.utils.pipeline.HttpURLConnectionClient; import com.microsoft.windowsazure.services.core.utils.pipeline.PipelineHelpers; @@ -55,19 +56,20 @@ public class QueueRestProxy implements QueueContract { private final String url; private final RFC1123DateConverter dateMapper; private final ServiceFilter[] filters; - private final SharedKeyFilter filter; + private final SharedKeyFilter sharedKeyFilter; @Inject public QueueRestProxy(HttpURLConnectionClient channel, @Named(QueueConfiguration.ACCOUNT_NAME) String accountName, - @Named(QueueConfiguration.URI) String url, SharedKeyFilter filter) { + @Named(QueueConfiguration.URI) String url, SharedKeyFilter sharedKeyFilter, UserAgentFilter userAgentFilter) { this.channel = channel; this.accountName = accountName; this.url = url; - this.filter = filter; + this.sharedKeyFilter = sharedKeyFilter; this.dateMapper = new RFC1123DateConverter(); this.filters = new ServiceFilter[0]; - channel.addFilter(filter); + channel.addFilter(sharedKeyFilter); + channel.addFilter(userAgentFilter); } public QueueRestProxy(HttpURLConnectionClient channel, ServiceFilter[] filters, String accountName, String url, @@ -77,14 +79,15 @@ public QueueRestProxy(HttpURLConnectionClient channel, ServiceFilter[] filters, this.filters = filters; this.accountName = accountName; this.url = url; - this.filter = filter; + this.sharedKeyFilter = filter; this.dateMapper = dateMapper; } + @Override public QueueContract withFilter(ServiceFilter filter) { ServiceFilter[] newFilters = Arrays.copyOf(filters, filters.length + 1); newFilters[filters.length] = filter; - return new QueueRestProxy(this.channel, newFilters, this.accountName, this.url, this.filter, this.dateMapper); + return new QueueRestProxy(this.channel, newFilters, this.accountName, this.url, this.sharedKeyFilter, this.dateMapper); } private void ThrowIfError(ClientResponse r) { @@ -117,10 +120,12 @@ private WebResource getResource(QueueServiceOptions options) { return webResource; } + @Override public GetServicePropertiesResult getServiceProperties() throws ServiceException { return getServiceProperties(new QueueServiceOptions()); } + @Override public GetServicePropertiesResult getServiceProperties(QueueServiceOptions options) throws ServiceException { WebResource webResource = getResource(options).path("/").queryParam("resType", "service") .queryParam("comp", "properties"); @@ -132,10 +137,12 @@ public GetServicePropertiesResult getServiceProperties(QueueServiceOptions optio return result; } + @Override public void setServiceProperties(ServiceProperties serviceProperties) throws ServiceException { setServiceProperties(serviceProperties, new QueueServiceOptions()); } + @Override public void setServiceProperties(ServiceProperties serviceProperties, QueueServiceOptions options) throws ServiceException { WebResource webResource = getResource(options).path("/").queryParam("resType", "service") @@ -146,11 +153,13 @@ public void setServiceProperties(ServiceProperties serviceProperties, QueueServi builder.put(serviceProperties); } + @Override public void createQueue(String queue) throws ServiceException { createQueue(queue, new CreateQueueOptions()); } + @Override public void createQueue(String queue, CreateQueueOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); @@ -163,10 +172,12 @@ public void createQueue(String queue, CreateQueueOptions options) throws Service builder.put(); } + @Override public void deleteQueue(String queue) throws ServiceException { deleteQueue(queue, new QueueServiceOptions()); } + @Override public void deleteQueue(String queue, QueueServiceOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); @@ -178,10 +189,12 @@ public void deleteQueue(String queue, QueueServiceOptions options) throws Servic builder.delete(); } + @Override public ListQueuesResult listQueues() throws ServiceException { return listQueues(new ListQueuesOptions()); } + @Override public ListQueuesResult listQueues(ListQueuesOptions options) throws ServiceException { WebResource webResource = getResource(options).path("/").queryParam("comp", "list"); webResource = addOptionalQueryParam(webResource, "prefix", options.getPrefix()); @@ -196,10 +209,12 @@ public ListQueuesResult listQueues(ListQueuesOptions options) throws ServiceExce return builder.get(ListQueuesResult.class); } + @Override public GetQueueMetadataResult getQueueMetadata(String queue) throws ServiceException { return getQueueMetadata(queue, new QueueServiceOptions()); } + @Override public GetQueueMetadataResult getQueueMetadata(String queue, QueueServiceOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); @@ -219,10 +234,12 @@ public GetQueueMetadataResult getQueueMetadata(String queue, QueueServiceOptions return result; } + @Override public void setQueueMetadata(String queue, HashMap metadata) throws ServiceException { setQueueMetadata(queue, metadata, new QueueServiceOptions()); } + @Override public void setQueueMetadata(String queue, HashMap metadata, QueueServiceOptions options) throws ServiceException { if (queue == null) @@ -236,10 +253,12 @@ public void setQueueMetadata(String queue, HashMap metadata, Que builder.put(); } + @Override public void createMessage(String queue, String messageText) throws ServiceException { createMessage(queue, messageText, new CreateMessageOptions()); } + @Override public void createMessage(String queue, String messageText, CreateMessageOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); @@ -256,12 +275,14 @@ public void createMessage(String queue, String messageText, CreateMessageOptions builder.post(queueMessage); } + @Override public UpdateMessageResult updateMessage(String queue, String messageId, String popReceipt, String messageText, int visibilityTimeoutInSeconds) throws ServiceException { return updateMessage(queue, messageId, popReceipt, messageText, visibilityTimeoutInSeconds, new QueueServiceOptions()); } + @Override public UpdateMessageResult updateMessage(String queue, String messageId, String popReceipt, String messageText, int visibilityTimeoutInSeconds, QueueServiceOptions options) throws ServiceException { if (queue == null) @@ -287,10 +308,12 @@ public UpdateMessageResult updateMessage(String queue, String messageId, String return result; } + @Override public ListMessagesResult listMessages(String queue) throws ServiceException { return listMessages(queue, new ListMessagesOptions()); } + @Override public ListMessagesResult listMessages(String queue, ListMessagesOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); @@ -304,10 +327,12 @@ public ListMessagesResult listMessages(String queue, ListMessagesOptions options return builder.get(ListMessagesResult.class); } + @Override public PeekMessagesResult peekMessages(String queue) throws ServiceException { return peekMessages(queue, new PeekMessagesOptions()); } + @Override public PeekMessagesResult peekMessages(String queue, PeekMessagesOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); @@ -320,10 +345,12 @@ public PeekMessagesResult peekMessages(String queue, PeekMessagesOptions options return builder.get(PeekMessagesResult.class); } + @Override public void deleteMessage(String queue, String messageId, String popReceipt) throws ServiceException { deleteMessage(queue, messageId, popReceipt, new QueueServiceOptions()); } + @Override public void deleteMessage(String queue, String messageId, String popReceipt, QueueServiceOptions options) throws ServiceException { if (queue == null) @@ -339,10 +366,12 @@ public void deleteMessage(String queue, String messageId, String popReceipt, Que builder.delete(); } + @Override public void clearMessages(String queue) throws ServiceException { clearMessages(queue, new QueueServiceOptions()); } + @Override public void clearMessages(String queue, QueueServiceOptions options) throws ServiceException { if (queue == null) throw new NullPointerException(); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/Exports.java index b335a9f9106f7..d0466bb31cb75 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/Exports.java @@ -2,21 +2,22 @@ * Copyright 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; import java.util.Map; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.serviceBus.implementation.BrokerPropertiesMapper; import com.microsoft.windowsazure.services.serviceBus.implementation.EntryModelProvider; import com.microsoft.windowsazure.services.serviceBus.implementation.MarshallerProvider; @@ -33,6 +34,7 @@ public void register(Builder.Registry registry) { registry.add(ServiceBusContract.class, ServiceBusExceptionProcessor.class); registry.add(ServiceBusExceptionProcessor.class); registry.add(ServiceBusRestProxy.class); + registry.add(UserAgentFilter.class); // alter jersey client config for serviceBus registry.alter(ClientConfig.class, new Builder.Alteration() { 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 87202a8b22542..eb01a664440ea 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 @@ -22,6 +22,13 @@ */ public class ServiceBusConfiguration { + + /** + * Defines the configuration connection string constant. + * + */ + public final static String CONNECTION_STRING = "serviceBus.connection.string"; + /** * Defines the configuration URI constant. * @@ -57,7 +64,20 @@ public class ServiceBusConfiguration { * * @param authenticationPassword * A String object that represents the authentication password. - * + * + * @param serviceBusRootUri + * A String object containing the base URI that is added to your + * Service Bus namespace to form the URI to connect to the Service Bus service. + * + * To access the default public Azure service, pass ".servicebus.windows.net" + * + * @param wrapRootUri + * A String object containing the base URI that is added to your + * Service Bus namespace to form the URI to get an access token for the Service + * Bus service. + * + * To access the default public Azure service, pass "-sb.accesscontrol.windows.net/WRAPv0.9" + * * @return * A Configuration object that can be used when creating an instance of the * ServiceBusService class. @@ -83,7 +103,20 @@ public static Configuration configureWithWrapAuthentication(String namespace, St * * @param authenticationPassword * A String object that represents the authentication password. - * + * + * @param serviceBusRootUri + * A String object containing the base URI that is added to your + * Service Bus namespace to form the URI to connect to the Service Bus service. + * + * To access the default public Azure service, pass ".servicebus.windows.net" + * + * @param wrapRootUri + * A String object containing the base URI that is added to your + * Service Bus namespace to form the URI to get an access token for the Service + * Bus service. + * + * To access the default public Azure service, pass "-sb.accesscontrol.windows.net/WRAPv0.9" + * * @return * A Configuration object that can be used when creating an instance of the * ServiceBusService class. @@ -112,7 +145,20 @@ public static Configuration configureWithWrapAuthentication(Configuration config * * @param authenticationPassword * A String object that represents the authentication password. - * + * + * @param serviceBusRootUri + * A String object containing the base URI that is added to your + * Service Bus namespace to form the URI to connect to the Service Bus service. + * + * To access the default public Azure service, pass ".servicebus.windows.net" + * + * @param wrapRootUri + * A String object containing the base URI that is added to your + * Service Bus namespace to form the URI to get an access token for the Service + * Bus service. + * + * To access the default public Azure service, pass "-sb.accesscontrol.windows.net/WRAPv0.9" + * * @return * A Configuration object that can be used when creating an instance of the * ServiceBusService class. @@ -129,6 +175,8 @@ else if (profile.length() != 0 && !profile.endsWith(".")) { profile = profile + "."; } + configuration.setProperty(profile + CONNECTION_STRING, null); + configuration.setProperty(profile + URI, "https://" + namespace + serviceBusRootUri); configuration.setProperty(profile + WRAP_URI, "https://" + namespace + wrapRootUri); @@ -138,4 +186,32 @@ else if (profile.length() != 0 && !profile.endsWith(".")) { return configuration; } + + /** + * Creates a service bus configuration using the specified connection string. + * @param profile + * A String object that represents the profile. + * @param configuration + * A previously instantiated Configuration object. + * @param connectionString + * A String object the contains the connection string for the + * service bus connection information. + * @return + * A Configuration object that can be used when creating an instance of the + * ServiceBusService class. + */ + public static Configuration configureWithConnectionString(String profile, Configuration configuration, + String connectionString) { + + if (profile == null) { + profile = ""; + } + else if (profile.length() != 0 && !profile.endsWith(".")) { + profile = profile + "."; + } + + configuration.setProperty(profile + CONNECTION_STRING, connectionString); + + return configuration; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerProperties.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerProperties.java index 2db84273def96..e677178530558 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerProperties.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerProperties.java @@ -2,15 +2,15 @@ * Copyright 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.implementation; @@ -19,7 +19,7 @@ import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonWriteNullProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; // // members of this class defined per specification at @@ -27,7 +27,7 @@ // @JsonIgnoreProperties(ignoreUnknown = true) -@JsonWriteNullProperties(false) +@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) public class BrokerProperties { @JsonProperty("CorrelationId") diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerPropertiesMapper.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerPropertiesMapper.java index 5a8dda45f9bae..a01aa2aed43b0 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerPropertiesMapper.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/BrokerPropertiesMapper.java @@ -2,15 +2,15 @@ * Copyright 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.implementation; @@ -31,18 +31,12 @@ public BrokerProperties fromString(String value) throws IllegalArgumentException return mapper.readValue(value.getBytes(), BrokerProperties.class); } catch (JsonParseException e) { - // TODO Auto-generated catch block - e.printStackTrace(); throw new IllegalArgumentException(e); } catch (JsonMappingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); throw new IllegalArgumentException(e); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); throw new IllegalArgumentException(e); } } @@ -54,18 +48,12 @@ public String toString(BrokerProperties value) { mapper.writeValue(writer, value); } catch (JsonGenerationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); throw new RuntimeException(e); } catch (JsonMappingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); throw new RuntimeException(e); } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); throw new RuntimeException(e); } return writer.toString(); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/Exports.java index d0f454a255179..40a04ba676def 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/Exports.java @@ -1,11 +1,11 @@ /** * Copyright 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. @@ -15,6 +15,13 @@ package com.microsoft.windowsazure.services.serviceBus.implementation; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.core.utils.ConnectionStringSyntaxException; +import com.microsoft.windowsazure.services.serviceBus.ServiceBusConfiguration; + +import java.net.URISyntaxException; +import java.util.Map; + +import static com.microsoft.windowsazure.services.core.utils.ExportUtils.getPropertyIfExists; public class Exports implements Builder.Exports { @@ -22,6 +29,24 @@ public void register(Builder.Registry registry) { registry.add(WrapContract.class, WrapRestProxy.class); registry.add(WrapTokenManager.class); registry.add(WrapFilter.class); - } + registry.add(new Builder.Factory() { + + @Override + public ServiceBusConnectionSettings create(String profile, Builder builder, Map properties) { + try { + return new ServiceBusConnectionSettings( + (String) getPropertyIfExists(profile, properties, ServiceBusConfiguration.CONNECTION_STRING), + (String) getPropertyIfExists(profile, properties, ServiceBusConfiguration.URI), + (String) getPropertyIfExists(profile, properties, ServiceBusConfiguration.WRAP_URI), + (String) getPropertyIfExists(profile, properties, ServiceBusConfiguration.WRAP_NAME), + (String) getPropertyIfExists(profile, properties, ServiceBusConfiguration.WRAP_PASSWORD)); + } catch (ConnectionStringSyntaxException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (URISyntaxException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + }); + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/MarshallerProvider.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/MarshallerProvider.java index fbda9c3f7f5e1..3edfc51d87c26 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/MarshallerProvider.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/MarshallerProvider.java @@ -2,15 +2,15 @@ * Copyright 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.implementation; @@ -30,19 +30,16 @@ public class MarshallerProvider implements ContextResolver { @Context private ContextResolver jaxbContextResolver; + @Override public Marshaller getContext(Class type) { Marshaller marshaller; try { marshaller = getJAXBContext(type).createMarshaller(); } catch (JAXBException e) { - // TODO Auto-generated catch block - e.printStackTrace(); return null; } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); return null; } com.sun.xml.bind.marshaller.NamespacePrefixMapper mapper = new NamespacePrefixMapperImpl(); @@ -50,8 +47,6 @@ public Marshaller getContext(Class type) { marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper); } catch (PropertyException e) { - // TODO Auto-generated catch block - e.printStackTrace(); return null; } return marshaller; diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionSettings.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionSettings.java new file mode 100644 index 0000000000000..dc0d3da353c8c --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionSettings.java @@ -0,0 +1,86 @@ +/** + * Copyright 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.serviceBus.implementation; + +import com.microsoft.windowsazure.services.core.utils.ConnectionStringSyntaxException; + +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Class that encapsulates all the various settings needed + * to connect to Service Bus, provided via either a + * connection string or via separate configuration variables. + *

+ * The connection string is looked for first, falling back + * to separate config values if not found. + */ +class ServiceBusConnectionSettings { + private String uri; + private String wrapUri; + private String wrapName; + private String wrapPassword; + + public ServiceBusConnectionSettings(String connectionString, String uri, String wrapUri, String wrapName, String wrapPassword) throws ConnectionStringSyntaxException, URISyntaxException { + if (connectionString != null) { + parseConnectionString(connectionString); + } else { + this.uri = uri; + this.wrapUri = wrapUri; + this.wrapName = wrapName; + this.wrapPassword = wrapPassword; + } + } + + public String getUri() { + return uri; + } + + public String getWrapUri() { + return wrapUri; + } + + public String getWrapName() { + return wrapName; + } + + public String getWrapPassword() { + return wrapPassword; + } + + private boolean parseConnectionString(String connectionString) throws URISyntaxException, ConnectionStringSyntaxException { + ServiceBusConnectionString cs = new ServiceBusConnectionString(connectionString); + setUri(cs); + setWrapUri(cs); + wrapName = cs.getSharedSecretIssuer(); + wrapPassword = cs.getSharedSecretValue(); + return true; + } + + private void setUri(ServiceBusConnectionString connectionString) { + uri = connectionString.getEndpoint().replaceFirst("^sb://", "https://"); + } + + private void setWrapUri(ServiceBusConnectionString connectionString) throws URISyntaxException { + if (connectionString.getStsEndpoint() == null || connectionString.getStsEndpoint().isEmpty()) { + URI hostUri = new URI(uri); + String namespace = hostUri.getHost().split("\\.")[0]; + wrapUri = "https://" + namespace + "-sb.accesscontrol.windows.net/WRAPv0.9"; + } else { + wrapUri = connectionString.getStsEndpoint(); + } + } +} diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionString.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionString.java new file mode 100644 index 0000000000000..ee63db4ccaf8a --- /dev/null +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionString.java @@ -0,0 +1,107 @@ +/** + * Copyright 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.serviceBus.implementation; + +import com.microsoft.windowsazure.services.core.utils.ConnectionStringSyntaxException; +import com.microsoft.windowsazure.services.core.utils.ParsedConnectionString; + +/** + * Class that parses the fields present in a service bus connection string. + * + */ +public class ServiceBusConnectionString extends ParsedConnectionString { + + /** + * Construct the {@link ServiceBusConnectionString} instance with the + * data from the given connection string + * + * @param connectionString The connection string + * + * @throws ConnectionStringSyntaxException + */ + public ServiceBusConnectionString(String connectionString) throws ConnectionStringSyntaxException { + super(connectionString); + } + + private String endpoint; + private String stsEndpoint; + private String sharedSecretIssuer; + private String sharedSecretValue; + + /** + * Get the endpoint from the connection string + * @return the endpoint + */ + public String getEndpoint() { + return endpoint; + } + + /** + * Sets the endpoint value + * @param endpoint + */ + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + /** + * Get the StsEndpoint from the connection string + * @return the sts endpoint + */ + public String getStsEndpoint() { + return stsEndpoint; + } + + /** + * Sets the StsEndpoint value + * @param stsEndpoint + */ + public void setStsEndpoint(String stsEndpoint) { + this.stsEndpoint = stsEndpoint; + } + + /** + * Get the shared secret issuer + * @return the issuer + */ + public String getSharedSecretIssuer() { + return sharedSecretIssuer; + } + + /** + * Set the shared secret issuer + * @param sharedSecretIssuer + */ + public void setSharedSecretIssuer(String sharedSecretIssuer) { + this.sharedSecretIssuer = sharedSecretIssuer; + } + + /** + * Get the shared secret value + * @return the shared secret value + */ + public String getSharedSecretValue() { + return sharedSecretValue; + } + + /** + * Set the shared secret value + * @param sharedSecretValue + */ + public void setSharedSecretValue(String sharedSecretValue) { + this.sharedSecretValue = sharedSecretValue; + } +} 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 b2007513afb2f..86a104fcaeadd 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 @@ -21,7 +21,6 @@ import java.util.Date; import javax.inject.Inject; -import javax.inject.Named; import javax.ws.rs.core.MediaType; import org.apache.commons.logging.Log; @@ -29,6 +28,7 @@ import com.microsoft.windowsazure.services.core.ServiceException; import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.pipeline.ClientFilterAdapter; import com.microsoft.windowsazure.services.serviceBus.ServiceBusContract; import com.microsoft.windowsazure.services.serviceBus.models.AbstractListOptions; @@ -73,15 +73,16 @@ public class ServiceBusRestProxy implements ServiceBusContract { ServiceFilter[] filters; @Inject - public ServiceBusRestProxy(Client channel, @Named("serviceBus") WrapFilter authFilter, - @Named("serviceBus.uri") String uri, BrokerPropertiesMapper mapper) { + public ServiceBusRestProxy(Client channel, WrapFilter authFilter, UserAgentFilter userAgentFilter, + ServiceBusConnectionSettings connectionSettings, BrokerPropertiesMapper mapper) { this.channel = channel; this.filters = new ServiceFilter[0]; - this.uri = uri; + this.uri = connectionSettings.getUri(); this.mapper = mapper; this.customPropertiesMapper = new CustomPropertiesMapper(); channel.addFilter(authFilter); + channel.addFilter(userAgentFilter); } public ServiceBusRestProxy(Client channel, ServiceFilter[] filters, String uri, BrokerPropertiesMapper mapper) { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxy.java index ec124f718c2a7..3de13aea1d265 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxy.java @@ -2,15 +2,15 @@ * Copyright 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.implementation; @@ -21,6 +21,7 @@ import org.apache.commons.logging.LogFactory; import com.microsoft.windowsazure.services.core.ServiceException; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.ServiceExceptionFactory; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.UniformInterfaceException; @@ -32,10 +33,12 @@ public class WrapRestProxy implements WrapContract { static Log log = LogFactory.getLog(WrapContract.class); @Inject - public WrapRestProxy(Client channel) { + public WrapRestProxy(Client channel, UserAgentFilter userAgentFilter) { this.channel = channel; + this.channel.addFilter(userAgentFilter); } + @Override public WrapAccessTokenResult wrapAccessToken(String uri, String name, String password, String scope) throws ServiceException { Form requestForm = new Form(); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManager.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManager.java index 407b839ddbb81..5255b4ec25cd8 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManager.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManager.java @@ -2,15 +2,15 @@ * Copyright 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.implementation; @@ -23,7 +23,6 @@ import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; -import javax.inject.Named; import javax.management.timer.Timer; import com.microsoft.windowsazure.services.core.ServiceException; @@ -40,13 +39,13 @@ public class WrapTokenManager { private final Map activeTokens; @Inject - public WrapTokenManager(WrapContract contract, DateFactory dateFactory, @Named("wrap.uri") String uri, - @Named("wrap.name") String name, @Named("wrap.password") String password) { + public WrapTokenManager(WrapContract contract, DateFactory dateFactory, + ServiceBusConnectionSettings connectionSettings) { this.contract = contract; this.dateFactory = dateFactory; - this.uri = uri; - this.name = name; - this.password = password; + this.uri = connectionSettings.getWrapUri(); + this.name = connectionSettings.getWrapName(); + this.password = connectionSettings.getWrapPassword(); activeTokens = new ConcurrentHashMap(); } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/Exports.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/Exports.java index 39fea9c07eb1b..485104a66a291 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/Exports.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/Exports.java @@ -15,6 +15,7 @@ package com.microsoft.windowsazure.services.table; import com.microsoft.windowsazure.services.core.Builder; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.table.implementation.AtomReaderWriter; import com.microsoft.windowsazure.services.table.implementation.DefaultEdmValueConterter; import com.microsoft.windowsazure.services.table.implementation.DefaultXMLStreamFactory; @@ -39,5 +40,6 @@ public void register(Builder.Registry registry) { registry.add(MimeReaderWriter.class); registry.add(HttpReaderWriter.class); registry.add(EdmValueConverter.class, DefaultEdmValueConterter.class); + registry.add(UserAgentFilter.class); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTable.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTable.java index 536b3adfb5821..f13eac657acfc 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTable.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTable.java @@ -493,7 +493,7 @@ public Void execute(final CloudTableClient client, final CloudTable table, final final OutputStream outStreamRef = request.getOutputStream(); outStreamRef.write(aclBytes); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { this.setNonExceptionedRetryableFailure(true); @@ -564,7 +564,7 @@ public TablePermissions execute(final CloudTableClient client, final CloudTable client.getCredentials().signRequestLite(request, -1L, opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTableClient.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTableClient.java index e49f6e3fdfca6..26a506cc39a65 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTableClient.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/CloudTableClient.java @@ -800,7 +800,7 @@ protected ResultSegment executeQuerySegmentedCore( this.getCredentials().signRequestLite(queryRequest, -1L, opContext); - taskReference.setResult(ExecutionEngine.processRequest(queryRequest, opContext)); + ExecutionEngine.processRequest(queryRequest, opContext, taskReference.getResult()); if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { throw TableServiceException.generateTableServiceException(true, taskReference.getResult(), null, diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/QueryTableOperation.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/QueryTableOperation.java index bc5c112c31876..14c130540b18c 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/QueryTableOperation.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/QueryTableOperation.java @@ -189,7 +189,7 @@ tableName, generateRequestIdentity(isTableEntry, operation.getPartitionKey(), fa client.getCredentials().signRequestLite(request, -1L, opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { // Parse response for updates diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/SharedAccessTablePolicy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/SharedAccessTablePolicy.java index fbeb55dae5be7..4bca919332cac 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/SharedAccessTablePolicy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/SharedAccessTablePolicy.java @@ -75,7 +75,7 @@ public static EnumSet permissionsFromString(final * A set of {@link SharedAccessTablePermissions} objects that represent the shared access permissions. * * @return A String that represents the shared access permissions in the "rwdl" format, which is - * described at {@link SharedAccessTablePermissions#permissionsFromString}. + * described at {@link SharedAccessTablePolicy#permissionsFromString(String)}. */ public static String permissionsToString(final EnumSet permissions) { if (permissions == null) { diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableBatchOperation.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableBatchOperation.java index 4f81296856b6f..a2e814a92e00a 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableBatchOperation.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableBatchOperation.java @@ -399,10 +399,9 @@ public ArrayList execute(final CloudTableClient client, final Table MimeHelper.writeBatchToStream(request.getOutputStream(), tableName, batch, batchID, changeSet, opContext); - final InputStream streamRef = ExecutionEngine.getInputStream(request, opContext); + final InputStream streamRef = ExecutionEngine.getInputStream(request, opContext, this.getResult()); ArrayList responseParts = null; try { - this.setResult(opContext.getLastResult()); final String contentType = request.getHeaderField(Constants.HeaderConstants.CONTENT_TYPE); final String[] headerVals = contentType.split("multipart/mixed; boundary="); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableOperation.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableOperation.java index 130d59fe9914d..65987567691ce 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableOperation.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableOperation.java @@ -256,13 +256,13 @@ private TableResult performDelete(final CloudTableClient client, final String ta public TableResult execute(final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { - final HttpURLConnection request = TableRequest.delete(client.getTransformedEndPoint(opContext), tableName, - generateRequestIdentity(isTableEntry, tableIdentity, false), operation.getEntity().getEtag(), - options.getTimeoutIntervalInMs(), null, options, opContext); + final HttpURLConnection request = TableRequest.delete(client.getTransformedEndPoint(opContext), + tableName, generateRequestIdentity(isTableEntry, tableIdentity, false), operation.getEntity() + .getEtag(), options.getTimeoutIntervalInMs(), null, options, opContext); client.getCredentials().signRequestLite(request, -1L, opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND || this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { @@ -323,8 +323,8 @@ private TableResult performInsert(final CloudTableClient client, final String ta @Override public TableResult execute(final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { - final HttpURLConnection request = TableRequest.insert(client.getTransformedEndPoint(opContext), tableName, - generateRequestIdentity(isTableEntry, tableIdentity, false), + final HttpURLConnection request = TableRequest.insert(client.getTransformedEndPoint(opContext), + tableName, generateRequestIdentity(isTableEntry, tableIdentity, false), operation.opType != TableOperationType.INSERT ? operation.getEntity().getEtag() : null, operation.opType.getUpdateType(), options.getTimeoutIntervalInMs(), null, options, opContext); @@ -333,7 +333,7 @@ public TableResult execute(final CloudTableClient client, final TableOperation o AtomPubParser.writeSingleEntityToStream(operation.getEntity(), isTableEntry, request.getOutputStream(), opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (operation.opType == TableOperationType.INSERT) { if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { throw TableServiceException.generateTableServiceException(false, this.getResult(), operation, @@ -410,8 +410,8 @@ private TableResult performMerge(final CloudTableClient client, final String tab public TableResult execute(final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { - final HttpURLConnection request = TableRequest.merge(client.getTransformedEndPoint(opContext), tableName, - generateRequestIdentity(false, null, false), operation.getEntity().getEtag(), + final HttpURLConnection request = TableRequest.merge(client.getTransformedEndPoint(opContext), + tableName, generateRequestIdentity(false, null, false), operation.getEntity().getEtag(), options.getTimeoutIntervalInMs(), null, options, opContext); client.getCredentials().signRequestLite(request, -1L, opContext); @@ -419,7 +419,7 @@ public TableResult execute(final CloudTableClient client, final TableOperation o AtomPubParser.writeSingleEntityToStream(operation.getEntity(), false, request.getOutputStream(), opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND || this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { @@ -476,8 +476,8 @@ private TableResult performUpdate(final CloudTableClient client, final String ta public TableResult execute(final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { - final HttpURLConnection request = TableRequest.update(client.getTransformedEndPoint(opContext), tableName, - generateRequestIdentity(false, null, false), operation.getEntity().getEtag(), + final HttpURLConnection request = TableRequest.update(client.getTransformedEndPoint(opContext), + tableName, generateRequestIdentity(false, null, false), operation.getEntity().getEtag(), options.getTimeoutIntervalInMs(), null, options, opContext); client.getCredentials().signRequestLite(request, -1L, opContext); @@ -485,7 +485,7 @@ public TableResult execute(final CloudTableClient client, final TableOperation o AtomPubParser.writeSingleEntityToStream(operation.getEntity(), false, request.getOutputStream(), opContext); - this.setResult(ExecutionEngine.processRequest(request, opContext)); + ExecutionEngine.processRequest(request, opContext, this.getResult()); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND || this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { @@ -686,7 +686,8 @@ protected TableResult parseResponse(final XMLStreamReader xmlr, final int httpSt resObj = new TableResult(httpStatusCode); resObj.setResult(this.getEntity()); - if (this.opType != TableOperationType.DELETE) { + if (this.opType != TableOperationType.DELETE && etagFromHeader != null) { + resObj.setEtag(etagFromHeader); this.getEntity().setEtag(etagFromHeader); } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableQuery.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableQuery.java index 6b5e126951015..924ab0fead225 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableQuery.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/client/TableQuery.java @@ -202,6 +202,8 @@ public static String generateFilterCondition(String propertyName, String operati for (byte b : value) { formatter.format("%02x", b); } + formatter.flush(); + formatter.close(); return generateFilterCondition(propertyName, operation, sb.toString(), EdmType.BINARY); } @@ -232,6 +234,8 @@ public static String generateFilterCondition(String propertyName, String operati for (byte b : value) { formatter.format("%02x", b); } + formatter.flush(); + formatter.close(); return generateFilterCondition(propertyName, operation, sb.toString(), EdmType.BINARY); } 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 01fbab3a870f4..fc4003870ce83 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 @@ -1,11 +1,11 @@ /** * Copyright 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. @@ -84,8 +84,7 @@ public void write(XMLStreamWriter writer) throws XMLStreamException { if (value != null) { writer.writeCharacters(value); - } - else { + } else { writer.writeAttribute("m:null", "true"); } @@ -108,8 +107,7 @@ public List parseTableEntries(InputStream stream) { // Process "entry" elements only if (isStartElement(xmlr, "entry")) { result.add(parseTableEntry(xmlr)); - } - else { + } else { nextSignificant(xmlr); } } @@ -118,8 +116,7 @@ public List parseTableEntries(InputStream stream) { expect(xmlr, XMLStreamConstants.END_DOCUMENT); return result; - } - catch (XMLStreamException e) { + } catch (XMLStreamException e) { throw new RuntimeException(e); } } @@ -133,8 +130,7 @@ public TableEntry parseTableEntry(InputStream stream) { expect(xmlr, XMLStreamConstants.END_DOCUMENT); return result; - } - catch (XMLStreamException e) { + } catch (XMLStreamException e) { throw new RuntimeException(e); } } @@ -151,8 +147,7 @@ public List parseEntityEntries(InputStream stream) { // Process "entry" elements only if (isStartElement(xmlr, "entry")) { result.add(parseEntityEntry(xmlr)); - } - else { + } else { nextSignificant(xmlr); } } @@ -161,8 +156,7 @@ public List parseEntityEntries(InputStream stream) { expect(xmlr, XMLStreamConstants.END_DOCUMENT); return result; - } - catch (XMLStreamException e) { + } catch (XMLStreamException e) { throw new RuntimeException(e); } } @@ -176,8 +170,7 @@ public Entity parseEntityEntry(InputStream stream) { expect(xmlr, XMLStreamConstants.END_DOCUMENT); return result; - } - catch (XMLStreamException e) { + } catch (XMLStreamException e) { throw new RuntimeException(e); } } @@ -227,8 +220,7 @@ private InputStream generateEntry(PropertiesWriter propertiesWriter) { writer.close(); return new ByteArrayInputStream(stream.toByteArray()); - } - catch (XMLStreamException e) { + } catch (XMLStreamException e) { throw new RuntimeException(e); } } @@ -243,8 +235,7 @@ private TableEntry parseTableEntry(XMLStreamReader xmlr) throws XMLStreamExcepti Map properties = parseEntryProperties(xmlr); result.setName((String) properties.get("TableName").getValue()); - } - else { + } else { nextSignificant(xmlr); } } @@ -263,8 +254,7 @@ private Entity parseEntityEntry(XMLStreamReader xmlr) throws XMLStreamException while (!isEndElement(xmlr, "entry")) { if (isStartElement(xmlr, "properties")) { result.setProperties(parseEntryProperties(xmlr)); - } - else { + } else { nextSignificant(xmlr); } } @@ -336,12 +326,11 @@ private void expect(XMLStreamReader xmlr, int eventType, String localName) throw private String encodeNumericCharacterReference(String value) { if (value == null) { return null; - } - else { + } else { char[] charArray = value.toCharArray(); StringBuffer stringBuffer = new StringBuffer(); for (int index = 0; index < charArray.length; index++) { - if (charArray[index] < 0x20 || charArray[index] > 0x7f) + if (isIllegalChar(charArray[index])) stringBuffer.append("&#x").append(Integer.toHexString(charArray[index])).append(";"); else stringBuffer.append(charArray[index]); @@ -349,4 +338,8 @@ private String encodeNumericCharacterReference(String value) { return stringBuffer.toString(); } } + + private boolean isIllegalChar(char c) { + return !(c == 9 || c == 0xA || c == 0xD || (c >= 0x20 && c < 0xFFFE)); + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/SharedKeyFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/SharedKeyFilter.java index d14843554216f..352115a45dbae 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/SharedKeyFilter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/SharedKeyFilter.java @@ -55,8 +55,6 @@ public void sign(ClientRequest cr) { if (log.isDebugEnabled()) { log.debug(String.format("String to sign: \"%s\"", stringToSign)); } - //TODO: Remove or comment the following line - //System.out.println(String.format("String to sign: \"%s\"", stringToSign)); String signature = this.getSigner().sign(stringToSign); cr.getHeaders().putSingle("Authorization", "SharedKey " + this.getAccountName() + ":" + signature); diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/TableRestProxy.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/TableRestProxy.java index 72379bb2582bd..0daec9926c025 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/TableRestProxy.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/table/implementation/TableRestProxy.java @@ -43,6 +43,7 @@ import com.microsoft.windowsazure.services.blob.implementation.RFC1123DateConverter; import com.microsoft.windowsazure.services.core.ServiceException; import com.microsoft.windowsazure.services.core.ServiceFilter; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.CommaStringBuilder; import com.microsoft.windowsazure.services.core.utils.DateFactory; import com.microsoft.windowsazure.services.core.utils.ServiceExceptionFactory; @@ -107,8 +108,9 @@ public class TableRestProxy implements TableContract { @Inject public TableRestProxy(HttpURLConnectionClient channel, @Named(TableConfiguration.URI) String url, - SharedKeyFilter filter, DateFactory dateFactory, ISO8601DateConverter iso8601DateConverter, - AtomReaderWriter atomReaderWriter, MimeReaderWriter mimeReaderWriter, HttpReaderWriter httpReaderWriter) { + SharedKeyFilter filter, UserAgentFilter userAgentFilter, DateFactory dateFactory, + ISO8601DateConverter iso8601DateConverter, AtomReaderWriter atomReaderWriter, + MimeReaderWriter mimeReaderWriter, HttpReaderWriter httpReaderWriter) { this.channel = channel; this.url = url; @@ -121,6 +123,7 @@ public TableRestProxy(HttpURLConnectionClient channel, @Named(TableConfiguration this.mimeReaderWriter = mimeReaderWriter; this.httpReaderWriter = httpReaderWriter; channel.addFilter(filter); + channel.addFilter(userAgentFilter); } public TableRestProxy(HttpURLConnectionClient channel, ServiceFilter[] filters, String url, SharedKeyFilter filter, @@ -257,6 +260,8 @@ else if (value.getClass() == byte[].class) { for (byte b : byteArray) { formatter.format("%02x", b); } + formatter.flush(); + formatter.close(); sb.append("'"); } else if (value.getClass() == Byte[].class) { @@ -266,6 +271,8 @@ else if (value.getClass() == Byte[].class) { for (Byte b : byteArray) { formatter.format("%02x", b); } + formatter.flush(); + formatter.close(); sb.append("'"); } else { diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/serviceruntime/Protocol1RuntimeGoalStateClientTests.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/serviceruntime/Protocol1RuntimeGoalStateClientTests.java index 42f4d4acab31f..00a669a080ffe 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/serviceruntime/Protocol1RuntimeGoalStateClientTests.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/serviceruntime/Protocol1RuntimeGoalStateClientTests.java @@ -2,25 +2,26 @@ * Copyright 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.serviceruntime; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + import java.io.InputStream; import java.util.LinkedList; import java.util.List; import org.junit.Test; -import static org.junit.Assert.*; -import static org.hamcrest.Matchers.*; /** * @@ -88,7 +89,7 @@ public void goalStateClientRestartsThread() { Protocol1RuntimeCurrentStateClient currentStateClient = new Protocol1RuntimeCurrentStateClient(null, null); GoalStateDeserializer goalStateDeserializer = new GoalStateDeserializer() { - private ChunkedGoalStateDeserializer deserializer = new ChunkedGoalStateDeserializer(); + private final ChunkedGoalStateDeserializer deserializer = new ChunkedGoalStateDeserializer(); @Override public void initialize(InputStream inputStream) { @@ -148,7 +149,6 @@ public RoleEnvironmentData deserialize(InputStream stream) { client.getCurrentGoalState(); } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } 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 01040883db402..49f73558f7609 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 @@ -42,6 +42,7 @@ import com.microsoft.windowsazure.services.blob.models.AccessCondition; import com.microsoft.windowsazure.services.blob.models.BlobProperties; import com.microsoft.windowsazure.services.blob.models.BlockList; +import com.microsoft.windowsazure.services.blob.models.BreakLeaseResult; 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; @@ -325,7 +326,7 @@ public void deleteContainerWorks() throws Exception { // Assert for (Container container : listContainerResult.getContainers()) { - assertTrue(!container.getName().equals(container)); + assertTrue(!container.getName().equals(containerName)); } } @@ -1263,7 +1264,7 @@ public void getBlobWithIfNotModifiedSinceAccessConditionWorks() throws Exception Date lastModifiedBase = (Date) props.getProperties().getLastModified().clone(); // +1 second - Date lastModifiedNext = new Date(lastModifiedBase.getTime() + 1 * 1000); + Date lastModifiedNext = new Date(lastModifiedBase.getTime() + 1000); while (true) { HashMap metadata = new HashMap(); @@ -1492,7 +1493,7 @@ public void deleteBlobSnapshotSuccess() throws Exception { ListBlobsResult listBlobsResult = service.listBlobs(TEST_CONTAINER_FOR_BLOBS); List blobEntry = listBlobsResult.getBlobs(); for (BlobEntry blobEntryItem : blobEntry) { - assertTrue(blobEntryItem.getSnapshot() != snapshot); + assertTrue(blobEntryItem.getSnapshot() == null || !blobEntryItem.getSnapshot().equals(snapshot)); } assertTrue(true); } @@ -1595,11 +1596,13 @@ public void breakLeaseWorks() throws Exception { String content = "some content2"; service.createBlockBlob(TEST_CONTAINER_FOR_BLOBS, "test6", new ByteArrayInputStream(content.getBytes("UTF-8"))); String leaseId = service.acquireLease(TEST_CONTAINER_FOR_BLOBS, "test6").getLeaseId(); - service.breakLease(TEST_CONTAINER_FOR_BLOBS, "test6", leaseId); + BreakLeaseResult breakResult = service.breakLease(TEST_CONTAINER_FOR_BLOBS, "test6"); service.releaseLease(TEST_CONTAINER_FOR_BLOBS, "test6", leaseId); // Assert assertNotNull(leaseId); + assertNotNull(breakResult); + assertTrue(breakResult.getRemainingLeaseTimeInSeconds() > 0); } class RetryPolicyObserver implements ServiceFilter { 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 81ac9334d8dc3..cba0245c4270c 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 @@ -40,13 +40,6 @@ public class BlobTestBase { @BeforeClass public static void setup() throws URISyntaxException, StorageException, InvalidKeyException { - - // UNCOMMENT TO USE FIDDLER - System.setProperty("http.proxyHost", "localhost"); - System.setProperty("http.proxyPort", "8888"); - System.setProperty("https.proxyHost", "localhost"); - System.setProperty("https.proxyPort", "8888"); - if (USE_DEV_FABRIC) { httpAcc = CloudStorageAccount.getDevelopmentStorageAccount(); } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainerTests.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainerTests.java index f16cfe5a2db6d..e007c41511408 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainerTests.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/blob/client/CloudBlobContainerTests.java @@ -688,6 +688,7 @@ public void testSendingRequestEventBlob() throws StorageException, URISyntaxExce @Override public void eventOccurred(SendingRequestEvent eventArg) { + Assert.assertEquals(eventArg.getRequestResult(), eventArg.getOpContext().getLastResult()); callList.add(true); } }); @@ -719,6 +720,43 @@ public void eventOccurred(SendingRequestEvent eventArg) { } } + @Test + public void testBlobInputStream() throws URISyntaxException, StorageException, IOException { + final int blobLength = 16 * 1024; + final Random randGenerator = new Random(); + String blobName = "testblob" + Integer.toString(randGenerator.nextInt(50000)); + blobName = blobName.replace('-', '_'); + + final CloudBlobContainer containerRef = bClient.getContainerReference(BlobTestBase.testSuiteContainerName); + + final CloudBlockBlob blobRef = containerRef.getBlockBlobReference(blobName); + + final byte[] buff = new byte[blobLength]; + randGenerator.nextBytes(buff); + buff[0] = -1; + buff[1] = -128; + final ByteArrayInputStream sourceStream = new ByteArrayInputStream(buff); + + final BlobRequestOptions options = new BlobRequestOptions(); + final OperationContext operationContext = new OperationContext(); + options.setStoreBlobContentMD5(true); + options.setTimeoutIntervalInMs(90000); + options.setRetryPolicyFactory(new RetryNoRetry()); + blobRef.uploadFullBlob(sourceStream, blobLength, null, options, operationContext); + + BlobInputStream blobStream = blobRef.openInputStream(); + + for (int i = 0; i < blobLength; i++) { + int data = blobStream.read(); + Assert.assertTrue(data >= 0); + Assert.assertEquals(buff[i], (byte) data); + } + + Assert.assertEquals(-1, blobStream.read()); + + blobRef.delete(); + } + @Test public void testCurrentOperationByteCount() throws URISyntaxException, StorageException, IOException { final int blockLength = 4 * 1024 * 1024; @@ -750,6 +788,7 @@ public void testCurrentOperationByteCount() throws URISyntaxException, StorageEx BlobRequestOptions options = new BlobRequestOptions(); options.setTimeoutIntervalInMs(2000); options.setRetryPolicyFactory(new RetryNoRetry()); + ByteArrayOutputStream downloadedDataStream = new ByteArrayOutputStream(); try { blobRef.download(downloadedDataStream, null, options, operationContext); @@ -769,5 +808,4 @@ public void testCurrentOperationByteCount() throws URISyntaxException, StorageEx blobRef.delete(); } - } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/core/utils/ParsedConnectionStringTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/core/utils/ParsedConnectionStringTest.java new file mode 100644 index 0000000000000..68c5972d1d7f3 --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/core/utils/ParsedConnectionStringTest.java @@ -0,0 +1,130 @@ +/** + * Copyright 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; + +import static org.junit.Assert.*; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import com.microsoft.windowsazure.services.core.utils.pipeline.ConnectionStringField; + +public class ParsedConnectionStringTest { + + private static class OneField extends ParsedConnectionString { + private String aField; + + public OneField(String connectionString) throws ConnectionStringSyntaxException { + super(connectionString); + } + + public String getAField() { + return aField; + } + + @SuppressWarnings("unused") + protected void setAField(String aField) { + this.aField = aField; + } + } + + @Test + public void shouldSuccessfullyParseValidStringWithOneField() throws Exception { + OneField cs = new OneField("AField=avalue"); + + assertEquals("avalue", cs.getAField()); + } + + private static class ThreeFields extends ParsedConnectionString { + private String fieldOne; + private String fieldTwo; + private int fieldThree; + + public ThreeFields(String connectionString) throws ConnectionStringSyntaxException { + super(connectionString); + } + + public String getFieldOne() { + return fieldOne; + } + + @SuppressWarnings("unused") + protected void setFieldOne(String fieldOne) { + this.fieldOne = fieldOne; + } + + public String getFieldTwo() { + return fieldTwo; + } + + @SuppressWarnings("unused") + protected void setFieldTwo(String fieldTwo) { + this.fieldTwo = fieldTwo; + } + + public int getFieldThree() { + return fieldThree; + } + + @ConnectionStringField(name = "fieldthree") + protected void setNumericField(String fieldThree) { + this.fieldThree = Integer.parseInt(fieldThree); + } + } + + @Test + public void shouldSuccessfullyParseValidStringWithMultipleFields() throws Exception { + ThreeFields cs = new ThreeFields("FieldOne=hello;FieldTwo=world;FieldThree=27"); + + assertEquals("hello", cs.getFieldOne()); + assertEquals("world", cs.getFieldTwo()); + assertEquals(27, cs.getFieldThree()); + } + + @Test + public void shouldSuccessFullyParseValisStringWithQuotedKeysAndValues() throws Exception { + ThreeFields cs = new ThreeFields("FieldOne=hello;'FieldTwo'=world;FieldThree='27'"); + + assertEquals("hello", cs.getFieldOne()); + assertEquals("world", cs.getFieldTwo()); + assertEquals(27, cs.getFieldThree()); + } + + @Rule + public ExpectedException exception = ExpectedException.none(); + + @Test + public void shouldThrowForFieldThatDoesntExist() throws Exception { + exception.expect(ConnectionStringSyntaxException.class); + new OneField("nosuchfield=nothing"); + } + + @Test + public void shouldNotThrowIfValueMissing() throws Exception { + ThreeFields cs = new ThreeFields(" FieldOne= hello; FieldTwo =;FieldThree=19 "); + assertEquals("", cs.getFieldTwo()); + } + + @Test + public void shouldIgnoreEmptyPairsAndExtraSemicolons() throws Exception { + ThreeFields cs = new ThreeFields("FieldOne=hello;; ; 'FieldTwo'=world;FieldThree='27';"); + + assertEquals("hello", cs.getFieldOne()); + assertEquals("world", cs.getFieldTwo()); + assertEquals(27, cs.getFieldThree()); + } +} diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/AssetIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/AssetIntegrationTest.java index 2c012d168f514..b9bcbb3bfeef8 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/AssetIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/AssetIntegrationTest.java @@ -47,6 +47,7 @@ import com.microsoft.windowsazure.services.media.models.Locator; import com.microsoft.windowsazure.services.media.models.LocatorInfo; import com.microsoft.windowsazure.services.media.models.LocatorType; +import com.microsoft.windowsazure.services.media.models.ProtectionKey; import com.microsoft.windowsazure.services.media.models.Task; import com.microsoft.windowsazure.services.media.models.Task.CreateBatchOperation; @@ -288,12 +289,15 @@ public void deleteAssetFailedWithInvalidId() throws ServiceException { @Test public void linkAssetContentKeySuccess() throws ServiceException, URISyntaxException { // Arrange - String originalTestName = testAssetPrefix + "linkAssetContentKeyInvalidIdFailed"; + String originalTestName = testAssetPrefix + "linkAssetContentKeySuccess"; AssetInfo assetInfo = service.create(Asset.create().setName(originalTestName) .setOptions(AssetOption.StorageEncrypted)); + + String protectionKeyId = service.action(ProtectionKey.getProtectionKeyId(ContentKeyType.StorageEncryption)); String contentKeyId = String.format("nb:kid:UUID:%s", UUID.randomUUID()); String encryptedContentKey = "dummyEncryptedContentKey"; - service.create(ContentKey.create(contentKeyId, ContentKeyType.StorageEncryption, encryptedContentKey)); + service.create(ContentKey.create(contentKeyId, ContentKeyType.StorageEncryption, encryptedContentKey) + .setProtectionKeyId(protectionKeyId)); // Act service.action(Asset.linkContentKey(assetInfo.getId(), contentKeyId)); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ContentKeyIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ContentKeyIntegrationTest.java index 3f479a6ea8b79..d7c6f40b96d7d 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ContentKeyIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/ContentKeyIntegrationTest.java @@ -27,6 +27,7 @@ import com.microsoft.windowsazure.services.media.models.ContentKey; import com.microsoft.windowsazure.services.media.models.ContentKeyInfo; import com.microsoft.windowsazure.services.media.models.ContentKeyType; +import com.microsoft.windowsazure.services.media.models.ProtectionKey; import com.microsoft.windowsazure.services.media.models.ProtectionKeyType; public class ContentKeyIntegrationTest extends IntegrationTestBase { @@ -65,15 +66,17 @@ public void canCreateContentKey() throws Exception { // Arrange String testCanCreateContentKeyId = createRandomContentKeyId(); String testCanCreateContentKeyName = "testCanCreateContentKey"; + String protectionKeyId = service.action(ProtectionKey.getProtectionKeyId(testContentKeyType)); // Act - ContentKeyInfo contentKeyInfo = service.create(ContentKey.create(testCanCreateContentKeyId, testContentKeyType, - testEncryptedContentKey).setName(testCanCreateContentKeyName)); + ContentKeyInfo contentKeyInfo = service.create(ContentKey + .create(testCanCreateContentKeyId, testContentKeyType, testEncryptedContentKey) + .setName(testCanCreateContentKeyName).setProtectionKeyId(protectionKeyId)); // Assert verifyContentKeyProperties("ContentKey", testCanCreateContentKeyId, testContentKeyType, - testEncryptedContentKey, testCanCreateContentKeyName, "", ProtectionKeyType.fromCode(0), "", - contentKeyInfo); + testEncryptedContentKey, testCanCreateContentKeyName, protectionKeyId, ProtectionKeyType.fromCode(0), + "", contentKeyInfo); } @Test @@ -81,8 +84,10 @@ public void canGetSingleContentKeyById() throws Exception { // Arrange String expectedName = testContentKeyPrefix + "GetOne"; String testGetSingleContentKeyByIdId = createRandomContentKeyId(); - ContentKeyInfo ContentKeyToGet = service.create(ContentKey.create(testGetSingleContentKeyByIdId, - testContentKeyType, testEncryptedContentKey).setName(expectedName)); + String protectionKeyId = service.action(ProtectionKey.getProtectionKeyId(testContentKeyType)); + ContentKeyInfo ContentKeyToGet = service.create(ContentKey + .create(testGetSingleContentKeyByIdId, testContentKeyType, testEncryptedContentKey) + .setName(expectedName).setProtectionKeyId(protectionKeyId)); // Act ContentKeyInfo retrievedContentKeyInfo = service.get(ContentKey.get(ContentKeyToGet.getId())); @@ -90,7 +95,8 @@ public void canGetSingleContentKeyById() throws Exception { // Assert assertEquals(ContentKeyToGet.getId(), retrievedContentKeyInfo.getId()); verifyContentKeyProperties("ContentKey", testGetSingleContentKeyByIdId, testContentKeyType, - testEncryptedContentKey, expectedName, "", ProtectionKeyType.fromCode(0), "", retrievedContentKeyInfo); + testEncryptedContentKey, expectedName, protectionKeyId, ProtectionKeyType.fromCode(0), "", + retrievedContentKeyInfo); } @Test @@ -102,18 +108,22 @@ public void cannotGetSingleContentKeyByInvalidId() throws Exception { @Test public void canRetrieveListOfContentKeys() throws Exception { + // Arrange String[] ContentKeyNames = new String[] { testContentKeyPrefix + "ListOne", testContentKeyPrefix + "ListTwo" }; + String protectionKeyId = service.action(ProtectionKey.getProtectionKeyId(testContentKeyType)); List expectedContentKeys = new ArrayList(); for (int i = 0; i < ContentKeyNames.length; i++) { String testCanRetrieveListOfContentKeysId = createRandomContentKeyId(); ContentKeyInfo contentKey = service.create(ContentKey.create(testCanRetrieveListOfContentKeysId, - testContentKeyType, testEncryptedContentKey)); + testContentKeyType, testEncryptedContentKey).setProtectionKeyId(protectionKeyId)); expectedContentKeys.add(contentKey); } + // Act List actualContentKeys = service.list(ContentKey.list()); + // Assert verifyListResultContains("listContentKeyss", expectedContentKeys, actualContentKeys, new ComponentDelegate() { @Override public void verifyEquals(String message, Object expected, Object actual) { @@ -124,32 +134,41 @@ public void verifyEquals(String message, Object expected, Object actual) { @Test public void canUseQueryParametersWhenListingContentKeys() throws Exception { + // Arrange String[] ContentKeyNames = new String[] { testContentKeyPrefix + "ListThree", testContentKeyPrefix + "ListFour", testContentKeyPrefix + "ListFive", testContentKeyPrefix + "ListSix", testContentKeyPrefix + "ListSeven" }; + String protectionKeyId = service.action(ProtectionKey.getProtectionKeyId(testContentKeyType)); List expectedContentKeys = new ArrayList(); for (int i = 0; i < ContentKeyNames.length; i++) { ContentKeyInfo contentKeyInfo = service.create(ContentKey.create(createRandomContentKeyId(), - testContentKeyType, testEncryptedContentKey)); + testContentKeyType, testEncryptedContentKey).setProtectionKeyId(protectionKeyId)); expectedContentKeys.add(contentKeyInfo); } + // Act List actualContentKeys = service.list(ContentKey.list().setTop(2)); + // Assert assertEquals(2, actualContentKeys.size()); } @Test public void canDeleteContentKeyById() throws Exception { + // Arrange + String protectionKeyId = service.action(ProtectionKey.getProtectionKeyId(testContentKeyType)); String contentKeyName = testContentKeyPrefix + "ToDelete"; - ContentKeyInfo contentKeyToDelete = service.create(ContentKey.create(createRandomContentKeyId(), - testContentKeyType, testEncryptedContentKey).setName(contentKeyName)); + ContentKeyInfo contentKeyToDelete = service.create(ContentKey + .create(createRandomContentKeyId(), testContentKeyType, testEncryptedContentKey) + .setName(contentKeyName).setProtectionKeyId(protectionKeyId)); List listContentKeysResult = service.list(ContentKey.list()); int ContentKeyCountBaseline = listContentKeysResult.size(); + // Act service.delete(ContentKey.delete(contentKeyToDelete.getId())); + // Assert listContentKeysResult = service.list(ContentKey.list()); assertEquals("listPoliciesResult.size", ContentKeyCountBaseline - 1, listContentKeysResult.size()); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/EncryptionIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/EncryptionIntegrationTest.java index 964bafa5072ea..2b2e78d125e86 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/EncryptionIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/EncryptionIntegrationTest.java @@ -98,7 +98,7 @@ public void uploadAesProtectedAssetAndDownloadSuccess() throws Exception { uploadEncryptedAssetFile(assetInfo, blobWriter, "MPEG4-H264.mp4", encryptedContent, contentKeyId, iv); // submit and execute the decoding job. - JobInfo jobInfo = decodeAsset("uploadAesProtectedAssetSuccess", assetInfo.getId()); + JobInfo jobInfo = decodeAsset(testJobPrefix + "uploadAesProtectedAssetSuccess", assetInfo.getId()); // assert LinkInfo taskLinkInfo = jobInfo.getTasksLink(); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java index ffa12bb064fa4..6e125ca859b16 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java @@ -101,8 +101,8 @@ protected static void cleanupEnvironment() { removeAllTestLocators(); removeAllTestAssets(); removeAllTestAccessPolicies(); - removeAllTestContentKeys(); removeAllTestJobs(); + removeAllTestContentKeys(); } private static void removeAllTestContentKeys() { diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java index d93041f2c5330..a8032b0bdd3df 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java @@ -35,6 +35,7 @@ import com.microsoft.windowsazure.services.media.models.ListResult; import com.microsoft.windowsazure.services.media.models.Task; import com.microsoft.windowsazure.services.media.models.Task.CreateBatchOperation; +import com.microsoft.windowsazure.services.media.models.TaskHistoricalEvent; import com.microsoft.windowsazure.services.media.models.TaskInfo; public class JobIntegrationTest extends IntegrationTestBase { @@ -301,7 +302,6 @@ public void canGetTasksFromJob() throws Exception { @Test public void canGetErrorDetailsFromTask() throws Exception { - cleanupEnvironment(); String name = testJobPrefix + "canGetErrorDetailsFromTask"; JobInfo actualJob = service.create(Job.create().setName(name).addInputMediaAsset(assetInfo.getId()) @@ -344,4 +344,32 @@ public void canGetInputOutputAssetsFromTask() throws Exception { assertTrue(outputs.get(0).getName().contains(name)); } + @Test + public void canGetTaskHistoricalEventsFromTask() throws Exception { + // Arrange + String jobName = testJobPrefix + "canGetTaskHistoricalEventsFromTask"; + int priority = 3; + int retryCounter = 0; + + // Act + JobInfo actualJobInfo = service.create(Job.create().setName(jobName).setPriority(priority) + .addInputMediaAsset(assetInfo.getId()).addTaskCreator(getTaskCreator(0))); + + while (actualJobInfo.getState().getCode() < 3 && retryCounter < 30) { + Thread.sleep(10000); + actualJobInfo = service.get(Job.get(actualJobInfo.getId())); + retryCounter++; + } + ListResult tasks = service.list(Task.list(actualJobInfo.getTasksLink())); + TaskInfo taskInfo = tasks.get(0); + List historicalEvents = taskInfo.getHistoricalEvents(); + TaskHistoricalEvent historicalEvent = historicalEvents.get(0); + + // Assert + assertTrue(historicalEvents.size() >= 5); + assertNotNull(historicalEvent.getCode()); + assertNotNull(historicalEvent.getTimeStamp()); + assertNull(historicalEvent.getMessage()); + } + } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/MediaProcessorIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/MediaProcessorIntegrationTest.java index 052fdc0811ef0..176220765c00b 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/MediaProcessorIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/MediaProcessorIntegrationTest.java @@ -73,6 +73,6 @@ public void listMediaProcessorWithOptionSuccess() throws ServiceException { assertEquals("listMediaProcessors size", 1, listMediaProcessorsResult.size()); MediaProcessorInfo mediaProcessorInfo = listMediaProcessorsResult.get(0); verifyMediaProcessorInfo("mediaProcessorInfo", "nb:mpid:UUID:aec03716-7c5e-4f68-b592-f4850eba9f10", - "Storage Decryption", "Storage Decryption", "", "Microsoft", "1.5.3", mediaProcessorInfo); + "Storage Decryption", "Storage Decryption", "", "Microsoft", "1.5.3.0", mediaProcessorInfo); } } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java index ad9ca21b6750c..2c576c8c193b7 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java @@ -71,7 +71,7 @@ public void createTaskSuccess() throws ServiceException, UnsupportedEncodingExce // Optional parameters String configuration = new String(Base64.encode(commonConfiguration), "UTF8"); String name = "My encoding Task " + UUID.randomUUID().toString(); - int priority = 0; + int jobPriority = 3; TaskOption options = TaskOption.ProtectedConfiguration; // Use a fake id, to simulate real use. String encryptionKeyId = "nb:kid:UUID:" + UUID.randomUUID().toString(); @@ -81,7 +81,7 @@ public void createTaskSuccess() throws ServiceException, UnsupportedEncodingExce String initializationVector = new String(Base64.encode(new byte[16]), "UTF8"); CreateBatchOperation taskCreator = Task.create(mediaProcessorId, taskBody).setConfiguration(configuration) - .setName(name).setPriority(priority).setOptions(options).setEncryptionKeyId(encryptionKeyId) + .setName(name).setPriority(jobPriority).setOptions(options).setEncryptionKeyId(encryptionKeyId) .setEncryptionScheme(encryptionScheme).setEncryptionVersion(encryptionVersion) .setInitializationVector(initializationVector); jobCreator.addTaskCreator(taskCreator); @@ -92,8 +92,9 @@ public void createTaskSuccess() throws ServiceException, UnsupportedEncodingExce // Assert assertEquals("taskInfos count", 1, taskInfos.size()); - verifyTaskPropertiesJustStarted("taskInfo", mediaProcessorId, options, taskBody, configuration, name, priority, - encryptionKeyId, encryptionScheme, encryptionVersion, initializationVector, taskInfos.get(0)); + verifyTaskPropertiesJustStarted("taskInfo", mediaProcessorId, options, taskBody, configuration, name, + jobPriority, encryptionKeyId, encryptionScheme, encryptionVersion, initializationVector, + taskInfos.get(0)); } @Test @@ -108,7 +109,7 @@ public void createTwoTasksSuccess() throws ServiceException { String configuration = commonConfiguration; String baseName = "My encoding Task " + UUID.randomUUID().toString(); String[] suffixes = new String[] { " 1", " 2" }; - int priority = 0; + int jobPriority = 3; TaskOption options = TaskOption.None; List taskCreators = new ArrayList(); @@ -128,7 +129,7 @@ public void createTwoTasksSuccess() throws ServiceException { assertEquals("taskInfos count", taskCreators.size(), taskInfos.size()); for (int i = 0; i < taskCreators.size(); i++) { verifyTaskPropertiesJustStartedNoEncryption("taskInfo", mediaProcessorId, options, taskBodies[i], - configuration, baseName + suffixes[i], priority, taskInfos.get(i)); + configuration, baseName + suffixes[i], jobPriority, taskInfos.get(i)); } } @@ -184,7 +185,7 @@ public void cancelTaskSuccess() throws ServiceException, InterruptedException { List taskInfos = service.list(Task.list(cancellingJobInfo.getTasksLink())); for (TaskInfo taskInfo : taskInfos) { verifyTaskPropertiesNoEncryption("canceled task", mediaProcessorId, TaskOption.None, taskBody, - configuration, name, 0, new Date(), null, 0.0, 0.0, null, TaskState.Canceled, taskInfo); + configuration, name, 3, new Date(), null, 0.0, 0.0, null, TaskState.Canceled, taskInfo); } } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java index f559ba17d5a6f..472b1a6ddfbf0 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java @@ -20,6 +20,7 @@ import org.junit.Test; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.media.IntegrationTestBase; import com.microsoft.windowsazure.services.media.MediaConfiguration; import com.sun.jersey.api.client.Client; @@ -28,7 +29,7 @@ public class OAuthRestProxyIntegrationTest extends IntegrationTestBase { @Test public void serviceCanBeCalledToCreateAccessToken() throws Exception { // Arrange - OAuthContract oAuthContract = new OAuthRestProxy(config.create(Client.class)); + OAuthContract oAuthContract = new OAuthRestProxy(config.create(Client.class), new UserAgentFilter()); // Act URI oAuthUri = new URI((String) config.getProperty(MediaConfiguration.OAUTH_URI)); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java index 580a8909fec5e..3fc50cae73e71 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java @@ -23,6 +23,7 @@ import org.junit.Assert; import org.junit.Test; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.core.utils.DefaultDateFactory; import com.microsoft.windowsazure.services.media.IntegrationTestBase; import com.microsoft.windowsazure.services.media.MediaConfiguration; @@ -72,7 +73,7 @@ public void canBuildJerseyClientToCreateAnAssetWhichIsProperlyDeserialized() thr } private OAuthContract createOAuthContract() { - return new OAuthRestProxy(Client.create()); + return new OAuthRestProxy(Client.create(), new UserAgentFilter()); } private OAuthTokenManager createTokenManager() throws URISyntaxException { diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientGB18030Test.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientGB18030Test.java new file mode 100644 index 0000000000000..9066107dacd53 --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientGB18030Test.java @@ -0,0 +1,108 @@ +/** + * Copyright 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.queue.client; + +import java.net.URISyntaxException; +import java.util.EnumSet; + +import junit.framework.Assert; + +import org.junit.Test; + +import com.microsoft.windowsazure.services.core.storage.StorageException; + +public class CloudQueueClientGB18030Test extends QueueTestBase { + + // GB18030CharSet is "啊齄丂狛狜隣郎隣兀﨩ˊ▇█〞〡¦℡㈱‐ー﹡﹢﹫、〓ⅰⅹ⒈€㈠㈩ⅠⅫ! ̄ぁんァヶΑ︴АЯаяāɡㄅㄩ─╋︵﹄︻︱︳︴ⅰⅹɑɡ〇〾⿻⺁䜣€㐀㒣㕴㕵㙉㙊䵯䵰䶴䶵". + public static final String GB18030CharSet = new String(new char[] { 0x554A, 0x9F44, 0x4E02, 0x72DB, 0x72DC, 0xF9F1, + 0xF92C, 0xF9F1, 0xFA0C, 0xFA29, 0x02CA, 0x2587, 0x2588, 0x301E, 0x3021, 0xFFE4, 0x2121, 0x3231, 0x2010, + 0x30FC, 0xFE61, 0xFE62, 0xFE6B, 0x3001, 0x3013, 0x2170, 0x2179, 0x2488, 0x20AC, 0x3220, 0x3229, 0x2160, + 0x216B, 0xFF01, 0xFFE3, 0x3041, 0x3093, 0x30A1, 0x30F6, 0x0391, 0xFE34, 0x0410, 0x042F, 0x0430, 0x044F, + 0x0101, 0x0261, 0x3105, 0x3129, 0x2500, 0x254B, 0xFE35, 0xFE44, 0xFE3B, 0xFE31, 0xFE33, 0xFE34, 0x2170, + 0x2179, 0x0251, 0xE7C7, 0x0261, 0x3007, 0x303E, 0x2FFB, 0x2E81, 0xE843, 0x4723, 0xE864, 0x20AC, 0x3400, + 0x34A3, 0x3574, 0x3575, 0x3649, 0x364A, 0x4D6F, 0x4D70, 0x4DB4, 0x4DB5 }); + + @Test + public void GB18030TestForSingleMessage() throws URISyntaxException, StorageException { + String messageContent = GB18030CharSet; + CloudQueueMessage cqm = new CloudQueueMessage(messageContent); + queue.addMessage(cqm); + + CloudQueueMessage messageFromPeekMessage = queue.peekMessage(); + Assert.assertEquals(messageContent, messageFromPeekMessage.getMessageContentAsString()); + + CloudQueueMessage messageFromRetrieveMessage = queue.retrieveMessage(); + Assert.assertEquals(messageContent, messageFromRetrieveMessage.getMessageContentAsString()); + + String messageContentUpdated = messageContent + " updated"; + messageFromRetrieveMessage.setMessageContent(messageContentUpdated); + queue.updateMessage(messageFromRetrieveMessage, 0); + + messageFromPeekMessage = queue.peekMessage(null, null); + Assert.assertEquals(messageContent, messageFromPeekMessage.getMessageContentAsString()); + + messageContentUpdated = messageContent + " updated again"; + messageFromRetrieveMessage.setMessageContent(messageContentUpdated); + queue.updateMessage(messageFromRetrieveMessage, 0, + EnumSet.of(MessageUpdateFields.VISIBILITY, MessageUpdateFields.CONTENT), null, null); + + messageFromRetrieveMessage = queue.retrieveMessage(5, null, null); + Assert.assertEquals(messageContentUpdated, messageFromRetrieveMessage.getMessageContentAsString()); + + queue.deleteMessage(messageFromRetrieveMessage); + } + + @Test + public void GB18030TestForMultipleMessages() throws URISyntaxException, StorageException { + int messageLength = 2; + String[] messageContents = new String[messageLength]; + for (int i = 0; i < messageLength; i++) { + messageContents[i] = GB18030CharSet + i; + queue.addMessage(new CloudQueueMessage(messageContents[i]), 600, 0, null, null); + } + + Iterable messagesFromPeekMessages = queue.peekMessages(messageLength); + int count = 0; + for (CloudQueueMessage message : messagesFromPeekMessages) { + Assert.assertEquals(messageContents[count], message.getMessageContentAsString()); + count++; + } + + Iterable messagesFromRetrieveMessages = queue.retrieveMessages(messageLength); + count = 0; + for (CloudQueueMessage message : messagesFromRetrieveMessages) { + Assert.assertEquals(messageContents[count], message.getMessageContentAsString()); + message.setMessageContent(message.getMessageContentAsString() + " updated"); + queue.updateMessage(message, 0, EnumSet.of(MessageUpdateFields.VISIBILITY, MessageUpdateFields.CONTENT), + null, null); + count++; + } + + messagesFromPeekMessages = queue.peekMessages(messageLength, null, null); + count = 0; + for (CloudQueueMessage message : messagesFromPeekMessages) { + Assert.assertEquals(messageContents[count] + " updated", message.getMessageContentAsString()); + count++; + } + + messagesFromRetrieveMessages = queue.retrieveMessages(messageLength, 5, null, null); + count = 0; + for (CloudQueueMessage message : messagesFromRetrieveMessages) { + Assert.assertEquals(messageContents[count] + " updated", message.getMessageContentAsString()); + queue.deleteMessage(message, null, null); + count++; + } + } +} diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientTests.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientTests.java index b3c266fac5aed..fd3a57a7f1f1b 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientTests.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueClientTests.java @@ -67,6 +67,7 @@ public void testListQueuesSmallNumber() throws URISyntaxException, StorageExcept int initialCount = 0; for (CloudQueue queue : qClient.listQueues()) { + Assert.assertNotNull(queue); initialCount++; } @@ -82,6 +83,7 @@ public void testListQueuesSmallNumber() throws URISyntaxException, StorageExcept int count = 0; for (CloudQueue queue : qClient.listQueues()) { + Assert.assertNotNull(queue); count++; } @@ -111,6 +113,7 @@ public void testListQueuesSmallNumber() throws URISyntaxException, StorageExcept public void testListQueuesAndListQueuesSegmentedLargeNumber() throws URISyntaxException, StorageException { int count = 0; for (CloudQueue queue : qClient.listQueues()) { + Assert.assertNotNull(queue); count++; } @@ -130,6 +133,7 @@ public void testListQueuesAndListQueuesSegmentedLargeNumber() throws URISyntaxEx count = 0; for (CloudQueue queue : qClient.listQueues()) { + Assert.assertNotNull(queue); count++; } } @@ -181,16 +185,19 @@ public void testListQueuesSegmented() throws URISyntaxException, StorageExceptio public void testListQueuesEqual() throws URISyntaxException, StorageException { int count1 = 0; for (CloudQueue queue : qClient.listQueues()) { + Assert.assertNotNull(queue); count1++; } int count2 = 0; for (CloudQueue queue : qClient.listQueues("")) { + Assert.assertNotNull(queue); count2++; } int count3 = 0; for (CloudQueue queue : qClient.listQueues(null)) { + Assert.assertNotNull(queue); count3++; } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueTests.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueTests.java index d97bb4bdc7b45..53c95807d4650 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueTests.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/queue/client/CloudQueueTests.java @@ -487,6 +487,7 @@ public void testClearMessages() throws URISyntaxException, StorageException, Uns int count = 0; for (CloudQueueMessage m : queue.peekMessages(32)) { + Assert.assertNotNull(m); count++; } @@ -498,6 +499,7 @@ public void testClearMessages() throws URISyntaxException, StorageException, Uns count = 0; for (CloudQueueMessage m : queue.peekMessages(32)) { + Assert.assertNotNull(m); count++; } @@ -674,7 +676,7 @@ public void testAddMessageLargeMessageInput() throws URISyntaxException, Storage @Test public void testAddMessageWithVisibilityTimeout() throws URISyntaxException, StorageException, - UnsupportedEncodingException { + UnsupportedEncodingException, InterruptedException { final String queueName = UUID.randomUUID().toString().toLowerCase(); final CloudQueue queue = qClient.getQueueReference(queueName); queue.create(); @@ -683,13 +685,7 @@ public void testAddMessageWithVisibilityTimeout() throws URISyntaxException, Sto Date d1 = m1.getExpirationTime(); queue.deleteMessage(m1); - try { - Thread.sleep(2000); - } - catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + Thread.sleep(2000); queue.addMessage(new CloudQueueMessage("message"), 20, 0, null, null); CloudQueueMessage m2 = queue.retrieveMessage(); @@ -818,7 +814,8 @@ public void testDeleteMessageNullMessage() throws URISyntaxException, StorageExc } @Test - public void testRetrieveMessage() throws URISyntaxException, StorageException, UnsupportedEncodingException { + public void testRetrieveMessage() throws URISyntaxException, StorageException, UnsupportedEncodingException, + InterruptedException { String queueName = UUID.randomUUID().toString().toLowerCase(); CloudQueue newQueue = qClient.getQueueReference(queueName); newQueue.create(); @@ -833,13 +830,7 @@ public void testRetrieveMessage() throws URISyntaxException, StorageException, U newQueue.deleteMessage(message1); - try { - Thread.sleep(2000); - } - catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + Thread.sleep(2000); newQueue.addMessage(new CloudQueueMessage("message"), 20, 0, null, null); CloudQueueMessage message2 = newQueue.retrieveMessage(); @@ -917,7 +908,8 @@ public void testRetrieveMessagesNonFound() throws URISyntaxException, StorageExc } @Test - public void testDequeueCountIncreases() throws URISyntaxException, StorageException, UnsupportedEncodingException { + public void testDequeueCountIncreases() throws URISyntaxException, StorageException, UnsupportedEncodingException, + InterruptedException { String queueName = UUID.randomUUID().toString().toLowerCase(); CloudQueue newQueue = qClient.getQueueReference(queueName); newQueue.create(); @@ -926,14 +918,7 @@ public void testDequeueCountIncreases() throws URISyntaxException, StorageExcept Assert.assertTrue(message1.getDequeueCount() == 1); for (int i = 2; i < 5; i++) { - try { - Thread.sleep(2000); - } - catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - + Thread.sleep(2000); CloudQueueMessage message2 = newQueue.retrieveMessage(1, null, null); Assert.assertTrue(message2.getDequeueCount() == i); } @@ -1127,6 +1112,8 @@ public void testPeekMessagesFromEmptyQueue() throws URISyntaxException, StorageE @Test public void testUpdateMessage() throws URISyntaxException, StorageException, UnsupportedEncodingException { + queue.clear(); + String messageContent = "messagetest"; CloudQueueMessage message1 = new CloudQueueMessage(messageContent); queue.addMessage(message1); @@ -1147,7 +1134,8 @@ public void testUpdateMessage() throws URISyntaxException, StorageException, Uns } @Test - public void testUpdateMessageFullPass() throws URISyntaxException, StorageException, UnsupportedEncodingException { + public void testUpdateMessageFullPass() throws URISyntaxException, StorageException, UnsupportedEncodingException, + InterruptedException { String queueName = UUID.randomUUID().toString().toLowerCase(); CloudQueue newQueue = qClient.getQueueReference(queueName); newQueue.create(); @@ -1162,13 +1150,7 @@ public void testUpdateMessageFullPass() throws URISyntaxException, StorageExcept Assert.assertTrue(popreceipt2 != popreceipt1); Assert.assertTrue(NextVisibleTim1.before(NextVisibleTim2)); - try { - Thread.sleep(2000); - } - catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + Thread.sleep(2000); String newMesage = message.getMessageContentAsString() + "updated"; message.setMessageContent(newMesage); 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 ead279ce3dbdb..e44acb2a21000 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 @@ -41,13 +41,6 @@ public class QueueTestBase { @BeforeClass public static void setup() throws URISyntaxException, StorageException, InvalidKeyException { - - // UNCOMMENT TO USE FIDDLER - System.setProperty("http.proxyHost", "localhost"); - System.setProperty("http.proxyPort", "8888"); - System.setProperty("https.proxyHost", "localhost"); - System.setProperty("https.proxyPort", "8888"); - if (USE_DEV_FABRIC) { httpAcc = CloudStorageAccount.getDevelopmentStorageAccount(); } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java index 16ba0ddcdf920..19933421282f0 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java @@ -278,7 +278,7 @@ public Task.CreateBatchOperation createTaskOptions(String taskName, int inputAss configuration = "VC1 Broadband SD 4x3"; break; case StorageDecryption: - processor = getMediaProcessorIdByName(MEDIA_PROCESSOR_STORAGE_DECRYPTION, "1.5.3"); + processor = getMediaProcessorIdByName(MEDIA_PROCESSOR_STORAGE_DECRYPTION, "1.5.3.0"); configuration = null; break; default: diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/IntegrationTestBase.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/IntegrationTestBase.java index 1d57ed6fbb814..aa8c21ec5cbbc 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/IntegrationTestBase.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/IntegrationTestBase.java @@ -16,6 +16,7 @@ import static com.microsoft.windowsazure.services.serviceBus.Util.*; +import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -54,7 +55,7 @@ public void initialize() throws Exception { for (TopicInfo topic : iterateTopics(service)) { String topicName = topic.getPath(); if (topicName.startsWith("Test") || topicName.startsWith("test")) { - service.deleteQueue(topicName); + service.deleteTopic(topicName); } } if (!testAlphaExists) { @@ -62,12 +63,27 @@ public void initialize() throws Exception { } } + @AfterClass + public static void cleanUpTestArtifacts() throws Exception { + Configuration config = createConfiguration(); + ServiceBusContract service = ServiceBusService.create(config); + for (QueueInfo queue : iterateQueues(service)) { + String queueName = queue.getPath(); + if (queueName.startsWith("Test") || queueName.startsWith("test")) { + service.deleteQueue(queueName); + } + } + for (TopicInfo topic : iterateTopics(service)) { + String topicName = topic.getPath(); + if (topicName.startsWith("Test") || topicName.startsWith("test")) { + service.deleteTopic(topicName); + } + } + } + protected static Configuration createConfiguration() throws Exception { Configuration config = Configuration.load(); - overrideWithEnv(config, ServiceBusConfiguration.URI); - overrideWithEnv(config, ServiceBusConfiguration.WRAP_URI); - overrideWithEnv(config, ServiceBusConfiguration.WRAP_NAME); - overrideWithEnv(config, ServiceBusConfiguration.WRAP_PASSWORD); + overrideWithEnv(config, ServiceBusConfiguration.CONNECTION_STRING); return config; } 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 9cc4d707c900e..d86163d799467 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 @@ -39,6 +39,22 @@ public Configuration newConfiguration() { return config; } + private Configuration newConfigurationWithProfile() { + Configuration config = newConfiguration(); + ServiceBusConfiguration.configureWithWrapAuthentication("other", config, + "my-other-namespace", "my-other-identity", + "my-shared-secret", ".servicebus.windows.net", "-sb.accesscontrol.windows.net/WRAPv0.9"); + return config; + } + + private Configuration newConfigurationWithConnectionString() { + Configuration config = newConfiguration(); + ServiceBusConfiguration.configureWithConnectionString(null, config, + "Endpoint=https://my-other-namespace.servicebus.windows.net/;" + + "SharedSecretIssuer=owner;" + + "SharedSecretValue=my-shared-secret"); + return config; + } @Test public void theServiceClassMayBeCreatedDirectlyWithConfig() throws Exception { Configuration config = newConfiguration(); @@ -64,4 +80,21 @@ public void testDefaultBuilderCreatesServiceImpl() throws Exception { assertNotNull(service); } + + @Test + public void theServiceClassCanBeCreatedThroughAProfile() throws Exception { + Configuration config = newConfigurationWithProfile(); + ServiceBusContract service = config.create("other", ServiceBusContract.class); + + assertNotNull(service); + assertEquals(ServiceBusExceptionProcessor.class, service.getClass()); + } + + @Test + public void theServiceClassCanBeCreatedThroughConnectionString() throws Exception { + Configuration config = newConfigurationWithConnectionString(); + + ServiceBusContract service = config.create(ServiceBusContract.class); + assertNotNull(service); + } } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusIntegrationTest.java index bd86d9b7abf9f..c09af13305b8b 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusIntegrationTest.java @@ -128,7 +128,7 @@ public void getNonExistQueueFail() throws Exception { String queuePath = "testGetNonExistQueueFail"; // Act - GetQueueResult getQueueResult = service.getQueue(queuePath); + service.getQueue(queuePath); // Assert } diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionSettingsTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionSettingsTest.java new file mode 100644 index 0000000000000..ec64e7d76effb --- /dev/null +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/ServiceBusConnectionSettingsTest.java @@ -0,0 +1,112 @@ +/** + * Copyright 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.serviceBus.implementation; + +import com.microsoft.windowsazure.services.core.Configuration; +import com.microsoft.windowsazure.services.serviceBus.ServiceBusConfiguration; +import org.junit.Test; + +import static junit.framework.Assert.*; + +public class ServiceBusConnectionSettingsTest { + + @Test + public void settingsAreParsedFromConnectionString() throws Exception { + String ns = "myNamespace"; + String issuer = "myissuer"; + String secret = "mysecret"; + + String connectionString = getConnectionString(ns, issuer, secret); + + ServiceBusConnectionSettings settings = new ServiceBusConnectionSettings(connectionString, null, null, null, null); + + assertEquals(String.format("https://%1$s.servicebus.windows.net/", ns), settings.getUri()); + assertEquals(String.format("https://%1$s-sb.accesscontrol.windows.net/WRAPv0.9", ns), settings.getWrapUri()); + assertEquals(issuer, settings.getWrapName()); + assertEquals(secret, settings.getWrapPassword()); + } + + private String getConnectionString(String ns, String issuer, String secret) { + return String.format( + "Endpoint=sb://%1$s.servicebus.windows.net/;SharedSecretIssuer=%2$s;SharedSecretValue=%3$s", + ns, issuer, secret); + } + + private String getConnectionString(String ns, String stsEndpoint, String issuer, String secret) { + return String.format( + "Endpoint=sb://%1$s.servicebus.windows.net/;StsEndpoint=https://%1$s%4$s;SharedSecretIssuer=%2$s;SharedSecretValue=%3$s", + ns, issuer, secret, stsEndpoint); + } + @Test + public void settingsAreUsedFromConnectionStringInConfig() throws Exception { + Configuration config = Configuration.load(); + ServiceBusConfiguration.configureWithConnectionString(null, config, + getConnectionString("myNamespace", "owner", "secret")); + + ServiceBusConnectionSettings settings = config.create(ServiceBusConnectionSettings.class); + + assertEquals("https://myNamespace.servicebus.windows.net/", settings.getUri()); + assertEquals("https://myNamespace-sb.accesscontrol.windows.net/WRAPv0.9", settings.getWrapUri()); + assertEquals("owner", settings.getWrapName()); + assertEquals("secret", settings.getWrapPassword()); + } + + @Test + public void settingsAreUsedFromIndividualSettingsInConfiguration() throws Exception { + Configuration config = Configuration.load(); + + ServiceBusConfiguration.configureWithWrapAuthentication(config, + "myNamespace", "owner", "secret", ".servicebus.windows.net/", "-sb.accesscontrol.windows.net/WRAPv0.9"); + + ServiceBusConnectionSettings settings = config.create(ServiceBusConnectionSettings.class); + + assertEquals("https://myNamespace.servicebus.windows.net/", settings.getUri()); + assertEquals("https://myNamespace-sb.accesscontrol.windows.net/WRAPv0.9", settings.getWrapUri()); + assertEquals("owner", settings.getWrapName()); + assertEquals("secret", settings.getWrapPassword()); + } + + @Test + public void settingsPreferConnectionStringIfBothPresentInConfiguration() throws Exception { + Configuration config = Configuration.load(); + + ServiceBusConfiguration.configureWithWrapAuthentication(config, + "myIndividualNamespace", "individualowner", "individualsecret", + ".servicebus.windows.net/", "-sb.accesscontrol.windows.net/WRAPv0.9"); + + ServiceBusConfiguration.configureWithConnectionString(null, config, + getConnectionString("myNamespaceCS", "ownerCS", "secretCS")); + + ServiceBusConnectionSettings settings = config.create(ServiceBusConnectionSettings.class); + + assertEquals("https://myNamespaceCS.servicebus.windows.net/", settings.getUri()); + assertEquals("https://myNamespaceCS-sb.accesscontrol.windows.net/WRAPv0.9", settings.getWrapUri()); + assertEquals("ownerCS", settings.getWrapName()); + assertEquals("secretCS", settings.getWrapPassword()); + } + + @Test + public void canSetStSEndPointInConnectionString() throws Exception { + ServiceBusConnectionSettings settings = new ServiceBusConnectionSettings( + getConnectionString("myNs", "-some.accesscontrol.net", "owner", "secret"), + null, null, null, null); + + assertEquals("https://myNs.servicebus.windows.net/", settings.getUri()); + assertEquals("https://myNs-some.accesscontrol.net", settings.getWrapUri()); + assertEquals("owner", settings.getWrapName()); + assertEquals("secret", settings.getWrapPassword()); + } +} diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxyIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxyIntegrationTest.java index 016de94febc64..7033d388c392b 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxyIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapRestProxyIntegrationTest.java @@ -2,15 +2,15 @@ * Copyright 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.implementation; @@ -21,6 +21,7 @@ import org.junit.Test; import com.microsoft.windowsazure.services.core.Configuration; +import com.microsoft.windowsazure.services.core.UserAgentFilter; import com.microsoft.windowsazure.services.serviceBus.ServiceBusConfiguration; import com.sun.jersey.api.client.Client; @@ -33,7 +34,7 @@ public void serviceCanBeCalledToCreateAccessToken() throws Exception { overrideWithEnv(config, ServiceBusConfiguration.WRAP_URI); overrideWithEnv(config, ServiceBusConfiguration.WRAP_NAME); overrideWithEnv(config, ServiceBusConfiguration.WRAP_PASSWORD); - WrapContract contract = new WrapRestProxy(config.create(Client.class)); + WrapContract contract = new WrapRestProxy(config.create(Client.class), new UserAgentFilter()); // Act String serviceBusUri = (String) config.getProperty(ServiceBusConfiguration.URI); diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerIntegrationTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerIntegrationTest.java index 3eb2fd952a7a4..6d2cefd85fbf9 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerIntegrationTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerIntegrationTest.java @@ -27,15 +27,12 @@ public class WrapTokenManagerIntegrationTest { @Test public void wrapClientWillAcquireAccessToken() throws Exception { // Arrange - Configuration config = Configuration.getInstance(); - overrideWithEnv(config, ServiceBusConfiguration.URI); - overrideWithEnv(config, ServiceBusConfiguration.WRAP_URI); - overrideWithEnv(config, ServiceBusConfiguration.WRAP_NAME); - overrideWithEnv(config, ServiceBusConfiguration.WRAP_PASSWORD); - WrapTokenManager client = config.create("serviceBus", WrapTokenManager.class); - + Configuration config = Configuration.load(); + overrideWithEnv(config, ServiceBusConfiguration.CONNECTION_STRING); + WrapTokenManager client = config.create(WrapTokenManager.class); + ServiceBusConnectionSettings settings = config.create(ServiceBusConnectionSettings.class); // Act - URI serviceBusURI = new URI((String) config.getProperty(ServiceBusConfiguration.URI)); + URI serviceBusURI = new URI(settings.getUri()); String accessToken = client.getAccessToken(serviceBusURI); // Assert diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerTest.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerTest.java index 11d2abfbd9bdd..5fb85b33358ed 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerTest.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapTokenManagerTest.java @@ -38,12 +38,13 @@ public class WrapTokenManagerTest { private Calendar calendar; @Before - public void init() { + public void init() throws Exception { calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); dateFactory = mock(DateFactory.class); contract = mock(WrapContract.class); - client = new WrapTokenManager(contract, dateFactory, "testurl", "testname", "testpassword"); + ServiceBusConnectionSettings settings = new ServiceBusConnectionSettings(null, null, "testurl", "testname", "testpassword"); + client = new WrapTokenManager(contract, dateFactory, settings); when(dateFactory.getDate()).thenAnswer(new Answer() { @Override 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 485c239890a33..c6a5a15564cc8 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 @@ -48,6 +48,8 @@ import com.microsoft.windowsazure.services.table.models.QueryTablesResult; import com.microsoft.windowsazure.services.table.models.ServiceProperties; import com.microsoft.windowsazure.services.table.models.TableEntry; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.config.ClientConfig; public class TableServiceIntegrationTest extends IntegrationTestBase { private static final String testTablesPrefix = "sdktest"; @@ -74,13 +76,14 @@ public static void setup() throws Exception { // Setup container names array (list of container names used by // integration tests) testTables = new String[10]; + int uniqueId = (new java.util.Random()).nextInt(100000); for (int i = 0; i < testTables.length; i++) { - testTables[i] = String.format("%s%d", testTablesPrefix, i + 1); + testTables[i] = String.format("%s%d%d", testTablesPrefix, uniqueId, i + 1); } creatableTables = new String[10]; for (int i = 0; i < creatableTables.length; i++) { - creatableTables[i] = String.format("%s%d", createableTablesPrefix, i + 1); + creatableTables[i] = String.format("%s%d%d", createableTablesPrefix, uniqueId, i + 1); } TEST_TABLE_1 = testTables[0]; @@ -100,8 +103,6 @@ public static void setup() throws Exception { Configuration config = createConfiguration(); TableContract service = TableService.create(config); - deleteAllTables(service, testTables); - deleteAllTables(service, creatableTables); createTables(service, testTablesPrefix, testTables); } @@ -135,17 +136,6 @@ private static void deleteTables(TableContract service, String prefix, String[] } } - private static void deleteAllTables(TableContract service, String[] list) throws Exception { - for (String item : list) { - try { - service.deleteTable(item); - } - catch (ServiceException e) { - // Ignore - } - } - } - private static Set queryTables(TableContract service, String prefix) throws Exception { HashSet result = new HashSet(); QueryTablesResult list = service.queryTables(new QueryTablesOptions().setPrefix(prefix)); @@ -387,22 +377,81 @@ public void insertEntityEscapeCharactersWorks() throws Exception { assertNotNull(result.getEntity().getProperty("test4")); String actualTest4 = (String) result.getEntity().getProperty("test4").getValue(); - assertEquals("ꪪ", actualTest4); + assertEquals("\uaaaa", actualTest4); assertNotNull(result.getEntity().getProperty("test5")); String actualTest5 = (String) result.getEntity().getProperty("test5").getValue(); - assertEquals("닢", actualTest5); + assertEquals("\ub2e2", actualTest5); assertNotNull(result.getEntity().getProperty("test6")); String actualTest6 = (String) result.getEntity().getProperty("test6").getValue(); - assertEquals(" 닢", actualTest6); + assertEquals(" \ub2e2", actualTest6); assertNotNull(result.getEntity().getProperty("test7")); String actualTest7 = (String) result.getEntity().getProperty("test7").getValue(); - assertEquals("ok 닢", actualTest7); + assertEquals("ok \ub2e2", actualTest7); + + } + + @Test + public void insertEntityEscapeCharactersRoundTripsFromService() throws Exception { + // Arrange + Configuration config = createConfiguration(); + TableContract service = TableService.create(config); + + String partition = "001"; + String row = "insertEntityEscapeCharactersRoundTripsFromService"; + Entity insertedEntity = new Entity().setPartitionKey(partition).setRowKey(row) + .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") + .setProperty("test8", EdmType.STRING, "\uD840\uDC00") + ; + + service.insertEntity(TEST_TABLE_2, insertedEntity); + + GetEntityResult result = service.getEntity(TEST_TABLE_2, "001", "insertEntityEscapeCharactersRoundTripsFromService"); + assertNotNull(result); + + Entity entity = result.getEntity(); + + assertNotNull(entity.getProperty("test")); + String actualTest1 = (String) entity.getPropertyValue("test"); + assertEquals("", actualTest1); + + assertNotNull(result.getEntity().getProperty("test2")); + String actualTest2 = (String) result.getEntity().getPropertyValue("test2"); + assertEquals("", actualTest2); + + assertNotNull(result.getEntity().getProperty("test3")); + String actualTest3 = (String) result.getEntity().getPropertyValue("test3"); + assertEquals("%", actualTest3); + + assertNotNull(result.getEntity().getProperty("test4")); + String actualTest4 = (String) result.getEntity().getPropertyValue("test4"); + assertEquals("\uaaaa", actualTest4); + + assertNotNull(result.getEntity().getProperty("test5")); + String actualTest5 = (String) result.getEntity().getPropertyValue("test5"); + assertEquals("\ub2e2", actualTest5); + assertNotNull(result.getEntity().getProperty("test6")); + String actualTest6 = (String) result.getEntity().getPropertyValue("test6"); + assertEquals(" \ub2e2", actualTest6); + + assertNotNull(result.getEntity().getProperty("test7")); + String actualTest7 = (String) result.getEntity().getPropertyValue("test7"); + assertEquals("ok \ub2e2", actualTest7); + + String actualTest8 = (String)entity.getPropertyValue("test8"); + assertEquals("\uD840\uDC00", actualTest8); } + @Test public void updateEntityWorks() throws Exception { System.out.println("updateEntityWorks()"); @@ -1201,16 +1250,23 @@ public void settingTimeoutPrefixedFromConfigWorks() throws Exception { 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"); + // Use reflection to pull the state out of the service. + Client channel = (Client) readField(service, "service", "channel"); + Integer connTimeout = (Integer) channel.getProperties().get(ClientConfig.PROPERTY_CONNECT_TIMEOUT); + Integer readTimeout = (Integer) channel.getProperties().get(ClientConfig.PROPERTY_READ_TIMEOUT); + + assertEquals(3, connTimeout.intValue()); + assertEquals(7, readTimeout.intValue()); + } + + private Object readField(Object target, String... fieldNames) throws NoSuchFieldException, IllegalAccessException { + Object value = target; + for (String fieldName : fieldNames) { + java.lang.reflect.Field field = value.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + value = field.get(value); } + return value; } @Test diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableOperationTests.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableOperationTests.java index 3421fcbe2b6f2..cb11cfbfe12df 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableOperationTests.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableOperationTests.java @@ -145,6 +145,7 @@ public void insertOrMerge() throws StorageException { TableResult insertResult = tClient.execute(testSuiteTableName, TableOperation.insertOrMerge(baseEntity)); Assert.assertEquals(insertResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT); + Assert.assertNotNull(insertResult.getEtag()); // Insert or replace Entity - ENTITY EXISTS -> WILL REPLACE tClient.execute(testSuiteTableName, TableOperation.insertOrMerge(secondEntity)); @@ -206,6 +207,7 @@ public void insertOrReplace() throws StorageException { TableResult insertResult = tClient.execute(testSuiteTableName, TableOperation.insertOrReplace(baseEntity)); Assert.assertEquals(insertResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT); + Assert.assertNotNull(insertResult.getEtag()); // Insert or replace Entity - ENTITY EXISTS -> WILL REPLACE tClient.execute(testSuiteTableName, TableOperation.insertOrReplace(secondEntity)); @@ -259,7 +261,10 @@ public void merge() throws StorageException { secondEntity.setRowKey(baseEntity.getRowKey()); secondEntity.setEtag(baseEntity.getEtag()); - tClient.execute(testSuiteTableName, TableOperation.merge(secondEntity)); + TableResult mergeResult = tClient.execute(testSuiteTableName, TableOperation.merge(secondEntity)); + + Assert.assertEquals(mergeResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT); + Assert.assertNotNull(mergeResult.getEtag()); TableResult res2 = tClient.execute(testSuiteTableName, TableOperation.retrieve(secondEntity.getPartitionKey(), secondEntity.getRowKey(), DynamicTableEntity.class)); @@ -456,7 +461,10 @@ public void replace() throws StorageException { // Remove property and update retrievedEntity.getProperties().remove("D"); - tClient.execute(testSuiteTableName, TableOperation.replace(retrievedEntity)); + TableResult replaceResult = tClient.execute(testSuiteTableName, TableOperation.replace(retrievedEntity)); + + Assert.assertEquals(replaceResult.getHttpStatusCode(), HttpURLConnection.HTTP_NO_CONTENT); + Assert.assertNotNull(replaceResult.getEtag()); // Retrieve Entity queryResult = tClient diff --git a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableQueryTests.java b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableQueryTests.java index 7bec262714c07..d8818dddc09c2 100644 --- a/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableQueryTests.java +++ b/microsoft-azure-api/src/test/java/com/microsoft/windowsazure/services/table/client/TableQueryTests.java @@ -334,7 +334,7 @@ public void tableInvalidQuery() throws StorageException, IOException, URISyntaxE } @Test - public void testQueryOnSupportedTypes() throws StorageException { + public void testQueryOnSupportedTypes() throws StorageException, InterruptedException { // Setup TableBatchOperation batch = new TableBatchOperation(); String pk = UUID.randomUUID().toString(); @@ -359,14 +359,8 @@ public void testQueryOnSupportedTypes() throws StorageException { ent.setGuid(UUID.randomUUID()); ent.setString(String.format("%04d", j)); - try { - // Add delay to make times unique - Thread.sleep(100); - } - catch (InterruptedException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + // Add delay to make times unique + Thread.sleep(100); batch.insert(ent); if (j == 50) { middleRef = ent; 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 b5c68c6df8765..80c7ce30738af 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 @@ -176,12 +176,13 @@ public void assertEquality(ComplexEntity other) { Assert.assertEquals(this.getPartitionKey(), other.getPartitionKey()); Assert.assertEquals(this.getRowKey(), other.getRowKey()); - Assert.assertEquals(this.getDateTime(), other.getDateTime()); + assertDateApproxEquals(this.getDateTime(), other.getDateTime(), 100); + Assert.assertEquals(this.getGuid(), other.getGuid()); Assert.assertEquals(this.getString(), other.getString()); - Assert.assertEquals(this.getDouble(), other.getDouble()); - Assert.assertEquals(this.getDoublePrimitive(), other.getDoublePrimitive()); + Assert.assertEquals(this.getDouble(), other.getDouble(), 1.0e-10); + Assert.assertEquals(this.getDoublePrimitive(), other.getDoublePrimitive(), 1.0e-10); Assert.assertEquals(this.getInt32(), other.getInt32()); Assert.assertEquals(this.getIntegerPrimitive(), other.getIntegerPrimitive()); Assert.assertEquals(this.getBool(), other.getBool()); @@ -192,6 +193,18 @@ public void assertEquality(ComplexEntity other) { Assert.assertTrue(Arrays.equals(this.getBinaryPrimitive(), other.getBinaryPrimitive())); } + protected void assertDateApproxEquals(Date expected, Date actual, int deltaInMs) { + if (expected == null || actual == null) { + Assert.assertEquals(expected, actual); + } + else { + long diffInMilliseconds = Math.abs(expected.getTime() - actual.getTime()); + if (diffInMilliseconds > deltaInMs) { + Assert.assertEquals(expected, actual); + } + } + } + /** * @return the binary */ @@ -567,12 +580,6 @@ public static class1 generateRandomEnitity(String pk) { @BeforeClass public static void setup() throws URISyntaxException, StorageException, InvalidKeyException { - - //UNCOMMENT TO USE FIDDLER - System.setProperty("http.proxyHost", "localhost"); - System.setProperty("http.proxyPort", "8888"); - System.setProperty("https.proxyHost", "localhost"); - System.setProperty("https.proxyPort", "8888"); if (USE_DEV_FABRIC) { httpAcc = CloudStorageAccount.getDevelopmentStorageAccount(); } 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 1abb40b2238c1..27b1e28139515 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 @@ -2,6 +2,7 @@ serviceBus.uri=https://%SERVICEBUS_NAMESPACE%.servicebus.windows.net/ serviceBus.wrap.uri=https://%SERVICEBUS_NAMESPACE%-sb.accesscontrol.windows.net/WRAPv0.9 serviceBus.wrap.name=%SERVICEBUS_SERVICEIDENTITY% serviceBus.wrap.password=%SERVICEBUS_SHAREDSECRET% +serviceBus.connection.string=EndPoint=sb://%SERVICEBUS_NAMESPACE%.servicebus.windows.net/;SharedSecretIssuer=%SERVICEBUS_SERVICEIDENTITY%;SharedSecretValue=%SERVICEBUS_SHAREDSECRET% blob.accountName=%BLOB_ACCOUNTNAME% blob.accountKey=%BLOB_ACCOUNTKEY% blob.uri=http://%BLOB_ACCOUNTNAME%.blob.core.windows.net