diff --git a/ChangeLog.txt b/ChangeLog.txt index 2c15b781280a..bfa94c50772d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,13 @@ +2013.05.27 Version 0.4.3 +* Added support for updating existing Queue/Topic/Subscription for Service Bus +* Added support for message lock renewal to support long running message processing for Service Bus +* Added new properties to Queue/Topic/Subscription/Rule for Service Bus +* Added support for rebinding content key for Media Services + +2013.04.16 Version 0.4.2 +* Fixed a bunch of GB18030 encoding issues +* Fixed a service bus issue when the locale is not UTC + 2013.03.12 Version 0.4.1 * Added "Azure-SDK-For-Java/" To User-Agent HTTP header * Added connection string support for Service Bus diff --git a/README.md b/README.md index a8805eb2e326..f12d7aa79956 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,41 @@ #Windows Azure SDK for Java -This SDK allows you to build Windows Azure applications in Java that allow -you to take advantage of Azure scalable cloud computing resources: table and blob -storage, messaging through Service Bus. - -For documentation please see the [Windows Azure Java Developer Center](http://www.windowsazure.com/en-us/develop/java/) +This project provides a client library in Java that makes it easy to consume Windows Azure services. For documentation please see the [Windows Azure Java Developer Center](http://www.windowsazure.com/en-us/develop/java/). #Features -* Blob - * Create/Read/Update/Delete Blobs -* Queue - * Create/Delete Queues - * Insert/Peek Queue Messages - * Advanced Queue Operations -* Media Services - * Upload Media Files to Media Services - * Change the encoding on uploaded Media Services - * Provide streaming or download access to uploaded/transformed Media Files + +* Storage + * Blob + * Create/Read/Update/Delete containers + * Create/Read/Update/Delete blobs + * Queue + * Create/Delete Queues + * Insert/Peek Queue Messages + * Advanced Queue Operations + * Table + * Create/Read/Update/Delete tables + * Create/Read/Update/Delete entities + * Batch operation * Service Bus - * Use either the Queue or Topic/Subscription Model + * Queues + * Create/Read/Update/Delete queues + * Send/Receive/Unlock/Delete messages + * Renew message lock + * Topics + * Create/Read/Update/Delete topics + * Create/Read/Update/Delete subscriptions + * Create/Read/Update/Delete rules + * Send/Receive/Unlock/Delete messages + * Renew message lock +* Media Services + * Create/Read/Update/Delete access policies + * Create/Read/Update/Delete asset files + * Create/Read/Update/Delete assets + * Create/Read/Update/Delete/Rebind content keys + * Create/Read/Update/Cancel/Delete jobs * Service Runtime - * Retrieve information about the state of your Azure Compute instances -* Table - * Manage Tables - * Table Entity Operations - * Entity Group Transactions (Batch) + * Retrieve information about the state of your Azure Compute instances + #Getting Started @@ -42,11 +53,13 @@ To get the source code of the SDK via git just type: To get the binaries of this library as distributed by Microsoft, ready for use within your project you can also have them installed by the Java package manager Maven. - - com.microsoft.windowsazure - microsoft-windowsazure-api - 0.4.2 - +```xml + + com.microsoft.windowsazure + microsoft-windowsazure-api + 0.4.2 + +``` ##Minimum Requirements @@ -61,67 +74,62 @@ account. To host your Java code in Windows Azure, you additionally need to down the full Windows Azure SDK for Java - which includes packaging, emulation, and deployment tools. -##Code Samples +##Code Sample The following is a quick example on how to set up a Azure blob using the API and uploading a file to it. For additional information on using the client libraries to access Azure services see the How To guides listed [here](http://www.windowsazure.com/en-us/develop/java/). +```java +import java.io.*; + +import com.microsoft.windowsazure.services.core.storage.*; +import com.microsoft.windowsazure.services.blob.client.*; + +public class BlobSample { + public static final String storageConnectionString = + "DefaultEndpointsProtocol=http;" + + "AccountName=your_account_name;" + + "AccountKey= your_account_key"; + + public static void main(String[] args) { + try { + CloudStorageAccount account; + CloudBlobClient serviceClient; + CloudBlobContainer container; + CloudBlockBlob blob; + + account = CloudStorageAccount.parse(storageConnectionString); + serviceClient = account.createCloudBlobClient(); + // Container name must be lower case. + container = serviceClient.getContainerReference("blobsample"); + container.createIfNotExist(); + + // Set anonymous access on the container. + BlobContainerPermissions containerPermissions; + containerPermissions = new BlobContainerPermissions(); + container.uploadPermissions(containerPermissions); + + // Upload an image file. + blob = container.getBlockBlobReference("image1.jpg"); + File fileReference = new File("c:\\myimages\\image1.jpg"); + blob.upload(new FileInputStream(fileReference), fileReference.length()); + } catch (FileNotFoundException fileNotFoundException) { + System.out.print("FileNotFoundException encountered: "); + System.out.println(fileNotFoundException.getMessage()); + System.exit(-1); + } catch (StorageException storageException) { + System.out.print("StorageException encountered: "); + System.out.println(storageException.getMessage()); + System.exit(-1); + } catch (Exception e) { + System.out.print("Exception encountered: "); + System.out.println(e.getMessage()); + System.exit(-1); + } - import com.microsoft.windowsazure.services.core.storage.*; - import com.microsoft.windowsazure.services.blob.client.*; - - public class BlobSample { - public static final String storageConnectionString = - "DefaultEndpointsProtocol=http;" + - "AccountName=your_account_name;" + - "AccountKey= your_account_name"; - - public static void main(String[] args) - { - try - { - CloudStorageAccount account; - CloudBlobClient serviceClient; - CloudBlobContainer container; - CloudBlockBlob blob; - - account = CloudStorageAccount.parse(storageConnectionString); - serviceClient = account.createCloudBlobClient(); - // Container name must be lower case. - container = serviceClient.getContainerReference("blobsample"); - container.createIfNotExist(); - - // Set anonymous access on the container. - BlobContainerPermissions containerPermissions; - containerPermissions = new BlobContainerPermissions(); - - // Upload an image file. - blob = container.getBlockBlobReference("image1.jpg"); - File fileReference = new File ("c:\\myimages\\image1.jpg"); - blob.upload(new FileInputStream(fileReference), fileReference.length()); - } - catch (FileNotFoundException fileNotFoundException) - { - System.out.print("FileNotFoundException encountered: "); - System.out.println(fileNotFoundException.getMessage()); - System.exit(-1); - } - catch (StorageException storageException) - { - System.out.print("StorageException encountered: "); - System.out.println(storageException.getMessage()); - System.exit(-1); - } - catch (Exception e) - { - System.out.print("Exception encountered: "); - System.out.println(e.getMessage()); - System.exit(-1); - } - - } } - +} +``` #Need Help? diff --git a/microsoft-azure-api/pom.xml b/microsoft-azure-api/pom.xml index 9c0bb981d0a7..5fc0ac258437 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.2 + 0.4.3 jar Microsoft Windows Azure Client API @@ -143,7 +143,7 @@ org.jvnet.jaxb2.maven2 maven-jaxb2-plugin - 0.8.0 + 0.8.3 generate-sources @@ -154,16 +154,18 @@ true + true + true org.jvnet.jaxb2_commons jaxb2-basics - 0.6.0 + 0.6.4 org.jvnet.jaxb2_commons jaxb2-basics-annotate - 0.6.0 + 0.6.4 diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusContract.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusContract.java index 075f3c748433..537d22623dd0 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusContract.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/ServiceBusContract.java @@ -195,13 +195,13 @@ ReceiveSubscriptionMessageResult receiveSubscriptionMessage(String topicPath, St /** * Creates a queue. * - * @param queue - * A Queue object that represents the queue to create. + * @param queueInfo + * A QueueInfo object that represents the queue to create. * @return A CreateQueueResult object that represents the result. * @throws ServiceException * If a service exception is encountered. */ - CreateQueueResult createQueue(QueueInfo queue) throws ServiceException; + CreateQueueResult createQueue(QueueInfo queueInfo) throws ServiceException; /** * Deletes a queue. diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/EntryModel.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/EntryModel.java index 71f11d9e6e46..e61d84d987e7 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/EntryModel.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/EntryModel.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; 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 index dc0d3da353c8..20bd238789b9 100644 --- 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 @@ -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,18 +15,17 @@ package com.microsoft.windowsazure.services.serviceBus.implementation; -import com.microsoft.windowsazure.services.core.utils.ConnectionStringSyntaxException; - import java.net.URI; import java.net.URISyntaxException; +import com.microsoft.windowsazure.services.core.utils.ConnectionStringSyntaxException; + /** * 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. + * The connection string is looked for first, falling back to separate config values if not found. */ class ServiceBusConnectionSettings { private String uri; @@ -34,10 +33,12 @@ class ServiceBusConnectionSettings { private String wrapName; private String wrapPassword; - public ServiceBusConnectionSettings(String connectionString, String uri, String wrapUri, String wrapName, String wrapPassword) throws ConnectionStringSyntaxException, URISyntaxException { + public ServiceBusConnectionSettings(String connectionString, String uri, String wrapUri, String wrapName, + String wrapPassword) throws ConnectionStringSyntaxException, URISyntaxException { if (connectionString != null) { parseConnectionString(connectionString); - } else { + } + else { this.uri = uri; this.wrapUri = wrapUri; this.wrapName = wrapName; @@ -61,7 +62,8 @@ public String getWrapPassword() { return wrapPassword; } - private boolean parseConnectionString(String connectionString) throws URISyntaxException, ConnectionStringSyntaxException { + private boolean parseConnectionString(String connectionString) throws URISyntaxException, + ConnectionStringSyntaxException { ServiceBusConnectionString cs = new ServiceBusConnectionString(connectionString); setUri(cs); setWrapUri(cs); @@ -79,8 +81,9 @@ private void setWrapUri(ServiceBusConnectionString connectionString) throws URIS URI hostUri = new URI(uri); String namespace = hostUri.getHost().split("\\.")[0]; wrapUri = "https://" + namespace + "-sb.accesscontrol.windows.net/WRAPv0.9"; - } else { - wrapUri = connectionString.getStsEndpoint(); + } + else { + wrapUri = connectionString.getStsEndpoint().replaceAll("\\/$", "") + "/WRAPv0.9"; } } } 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 482d26a74199..c27d177b5d02 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 @@ -267,9 +267,13 @@ public void deleteMessage(BrokeredMessage message) throws ServiceException { } @Override - public CreateQueueResult createQueue(QueueInfo entry) throws ServiceException { - return new CreateQueueResult(getResource().path(entry.getPath()) - .type("application/atom+xml;type=entry;charset=utf-8").put(QueueInfo.class, entry)); + public CreateQueueResult createQueue(QueueInfo queueInfo) throws ServiceException { + Builder webResourceBuilder = getResource().path(queueInfo.getPath()).type( + "application/atom+xml;type=entry;charset=utf-8"); + if ((queueInfo.getForwardTo() != null) && !queueInfo.getForwardTo().isEmpty()) { + webResourceBuilder.header("ServiceBusSupplementaryAuthorization", queueInfo.getForwardTo()); + } + return new CreateQueueResult(webResourceBuilder.put(QueueInfo.class, queueInfo)); } @Override @@ -296,8 +300,12 @@ public ListQueuesResult listQueues(ListQueuesOptions options) throws ServiceExce @Override public QueueInfo updateQueue(QueueInfo queueInfo) throws ServiceException { - return getResource().path(queueInfo.getPath()).type("application/atom+xml;type=entry;charset=utf-8") - .header("If-Match", "*").put(QueueInfo.class, queueInfo); + Builder webResourceBuilder = getResource().path(queueInfo.getPath()) + .type("application/atom+xml;type=entry;charset=utf-8").header("If-Match", "*"); + if ((queueInfo.getForwardTo() != null) && !queueInfo.getForwardTo().isEmpty()) { + webResourceBuilder.header("ServiceBusSupplementaryAuthorization", queueInfo.getForwardTo()); + } + return webResourceBuilder.put(QueueInfo.class, queueInfo); } private WebResource listOptions(AbstractListOptions options, WebResource path) { @@ -307,6 +315,9 @@ private WebResource listOptions(AbstractListOptions options, WebResource path if (options.getSkip() != null) { path = path.queryParam("$skip", options.getSkip().toString()); } + if (options.getFilter() != null) { + path = path.queryParam("$filter", options.getFilter()); + } return path; } @@ -345,10 +356,14 @@ public TopicInfo updateTopic(TopicInfo topicInfo) throws ServiceException { } @Override - public CreateSubscriptionResult createSubscription(String topicPath, SubscriptionInfo subscription) { - return new CreateSubscriptionResult(getResource().path(topicPath).path("subscriptions") - .path(subscription.getName()).type("application/atom+xml;type=entry;charset=utf-8") - .put(SubscriptionInfo.class, subscription)); + public CreateSubscriptionResult createSubscription(String topicPath, SubscriptionInfo subscriptionInfo) { + Builder webResourceBuilder = getResource().path(topicPath).path("subscriptions") + .path(subscriptionInfo.getName()).type("application/atom+xml;type=entry;charset=utf-8"); + if ((subscriptionInfo.getForwardTo() != null) && (!subscriptionInfo.getForwardTo().isEmpty())) { + webResourceBuilder.header("ServiceBusSupplementaryAuthorization", subscriptionInfo.getForwardTo()); + + } + return new CreateSubscriptionResult(webResourceBuilder.put(SubscriptionInfo.class, subscriptionInfo)); } @Override @@ -377,9 +392,13 @@ public ListSubscriptionsResult listSubscriptions(String topicPath, ListSubscript @Override public SubscriptionInfo updateSubscription(String topicName, SubscriptionInfo subscriptionInfo) throws ServiceException { - return getResource().path(topicName).path("subscriptions").path(subscriptionInfo.getName()) - .type("application/atom+xml;type=entry;charset=utf-8").header("If-Match", "*") - .put(SubscriptionInfo.class, subscriptionInfo); + Builder webResourceBuilder = getResource().path(topicName).path("subscriptions") + .path(subscriptionInfo.getName()).type("application/atom+xml;type=entry;charset=utf-8") + .header("If-Match", "*"); + if ((subscriptionInfo.getForwardTo() != null) && !subscriptionInfo.getForwardTo().isEmpty()) { + webResourceBuilder.header("ServiceBusSupplementaryAuthorization", subscriptionInfo.getForwardTo()); + } + return webResourceBuilder.put(SubscriptionInfo.class, subscriptionInfo); } @Override diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapFilter.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapFilter.java index ac3c15b3a7d0..f1d0187a6b21 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapFilter.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/implementation/WrapFilter.java @@ -2,18 +2,19 @@ * 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; +import java.net.URI; import java.net.URISyntaxException; import com.microsoft.windowsazure.services.core.ServiceException; @@ -31,10 +32,23 @@ public WrapFilter(WrapTokenManager tokenManager) { @Override public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { + String accessToken = getWrapToken(cr.getURI()); + cr.getHeaders().add("Authorization", accessToken); - String accessToken; + String secondaryAuthorizationUri = (String) cr.getHeaders().getFirst("ServiceBusSupplementaryAuthorization"); + if ((secondaryAuthorizationUri != null) && (!secondaryAuthorizationUri.isEmpty())) { + String secondaryAccessToken = getWrapToken(URI.create(secondaryAuthorizationUri)); + cr.getHeaders().remove("ServiceBusSupplementaryAuthorization"); + cr.getHeaders().add("ServiceBusSupplementaryAuthorization", secondaryAccessToken); + } + + return this.getNext().handle(cr); + } + + private String getWrapToken(URI uri) { + String result; try { - accessToken = tokenManager.getAccessToken(cr.getURI()); + result = tokenManager.getAccessToken(uri); } catch (ServiceException e) { // must wrap exception because of base class signature @@ -45,8 +59,6 @@ public ClientResponse handle(ClientRequest cr) throws ClientHandlerException { throw new ClientHandlerException(e); } - cr.getHeaders().add("Authorization", "WRAP access_token=\"" + accessToken + "\""); - - return this.getNext().handle(cr); + return "WRAP access_token=\"" + result + "\""; } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/AbstractListOptions.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/AbstractListOptions.java index 5970d10fc96f..d18d87edf874 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/AbstractListOptions.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/AbstractListOptions.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.models; public abstract class AbstractListOptions { Integer skip; Integer top; + String filter; public Integer getSkip() { return skip; @@ -37,4 +38,13 @@ public T setTop(Integer top) { this.top = top; return (T) this; } + + public String getFilter() { + return filter; + } + + public T setFilter(String filter) { + this.filter = filter; + return (T) this; + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/QueueInfo.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/QueueInfo.java index 8cc7a1efde54..d0600c19ec43 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/QueueInfo.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/QueueInfo.java @@ -14,6 +14,7 @@ */ package com.microsoft.windowsazure.services.serviceBus.models; +import java.net.URI; import java.util.Calendar; import javax.ws.rs.core.MediaType; @@ -24,6 +25,7 @@ import com.microsoft.windowsazure.services.serviceBus.implementation.EntityStatus; import com.microsoft.windowsazure.services.serviceBus.implementation.Entry; import com.microsoft.windowsazure.services.serviceBus.implementation.EntryModel; +import com.microsoft.windowsazure.services.serviceBus.implementation.MessageCountDetails; import com.microsoft.windowsazure.services.serviceBus.implementation.PartitioningPolicy; import com.microsoft.windowsazure.services.serviceBus.implementation.QueueDescription; @@ -538,4 +540,68 @@ public QueueInfo setUserMetadata(String userMetadata) { getModel().setUserMetadata(userMetadata); return this; } + + /** + * Gets the message count details. + * + * @return A MessageCountDetails instance that represents the details of the message count. + */ + public MessageCountDetails getCountDetails() { + return getModel().getCountDetails(); + } + + /** + * Sets the URI of the QueueInfo instance. + * + * @param uri + * the URI of the QueueInfo + * + * @return A QueueInfo object that represents the updated queue. + */ + public QueueInfo setUri(URI uri) { + getEntry().setId(uri.toString()); + return this; + } + + /** + * Gets the URI of the QueueInfo instance. + * + * @return A URI representing the QueueInfo. + */ + public URI getUri() { + return URI.create(removeQueryString(getEntry().getId())); + } + + /** + * Removes the query string of the URI. + * + * @param uri + * A raw string representing the URI of queue. + * @return the string + */ + private String removeQueryString(String uri) { + String[] result = uri.split("\\?"); + return result[0]; + } + + /** + * Sets the URI of the entity to forward to. + * + * @param forwardTo + * A String instance representing the URI of the entity to forward message to. + * @return A QueueInfo instance representing the updated queue information. + */ + public QueueInfo setForwardTo(String forwardTo) { + getModel().setForwardTo(forwardTo); + return this; + } + + /** + * Gets a String instance representing entity to forward to. + * + * @return A String instance representing the URI of the instance to forward to. + */ + public String getForwardTo() { + return getModel().getForwardTo(); + } } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/SubscriptionInfo.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/SubscriptionInfo.java index 04263c111503..0df71b38b78f 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/SubscriptionInfo.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/SubscriptionInfo.java @@ -24,6 +24,7 @@ import com.microsoft.windowsazure.services.serviceBus.implementation.EntityStatus; import com.microsoft.windowsazure.services.serviceBus.implementation.Entry; import com.microsoft.windowsazure.services.serviceBus.implementation.EntryModel; +import com.microsoft.windowsazure.services.serviceBus.implementation.MessageCountDetails; import com.microsoft.windowsazure.services.serviceBus.implementation.RuleDescription; import com.microsoft.windowsazure.services.serviceBus.implementation.SubscriptionDescription; @@ -430,4 +431,34 @@ public EntityAvailabilityStatus getEntityAvailabilityStatus() { return getModel().getEntityAvailabilityStatus(); } + /** + * Gets the message count details. + * + * @return A MessageCountDetails instance representing the details of the message count. + */ + public MessageCountDetails getCountDetails() { + return getModel().getCountDetails(); + } + + /** + * Sets the forward to. + * + * @param forwardTo + * A String representing the string to forward to. + * @return the subscription info + */ + public SubscriptionInfo setForwardTo(String forwardTo) { + getModel().setForwardTo(forwardTo); + return this; + } + + /** + * Gets a String representing the URI of the entity to forward to. + * + * @return A String representing the URI of the entity to forward to. + */ + public String getForwardTo() { + return getModel().getForwardTo(); + } + } diff --git a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/TopicInfo.java b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/TopicInfo.java index 627af7f6d05e..d3233b1a8174 100644 --- a/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/TopicInfo.java +++ b/microsoft-azure-api/src/main/java/com/microsoft/windowsazure/services/serviceBus/models/TopicInfo.java @@ -14,6 +14,7 @@ */ package com.microsoft.windowsazure.services.serviceBus.models; +import java.net.URI; import java.util.Calendar; import javax.ws.rs.core.MediaType; @@ -24,6 +25,7 @@ import com.microsoft.windowsazure.services.serviceBus.implementation.EntityStatus; import com.microsoft.windowsazure.services.serviceBus.implementation.Entry; import com.microsoft.windowsazure.services.serviceBus.implementation.EntryModel; +import com.microsoft.windowsazure.services.serviceBus.implementation.MessageCountDetails; import com.microsoft.windowsazure.services.serviceBus.implementation.PartitioningPolicy; import com.microsoft.windowsazure.services.serviceBus.implementation.TopicDescription; @@ -405,6 +407,15 @@ public Integer getSubscriptionCount() { return getModel().getSubscriptionCount(); } + /** + * Gets the message count details. + * + * @return A MessageCountDetails instance representing the details of the message count. + */ + public MessageCountDetails getCountDetails() { + return getModel().getCountDetails(); + } + /** * Sets the auto delete on idle. * @@ -467,4 +478,13 @@ public TopicInfo setEntityAvailabilityStatus(EntityAvailabilityStatus entityAvai public EntityAvailabilityStatus getEntityAvailabilityStatus() { return getModel().getEntityAvailabilityStatus(); } + + /** + * Gets the uri. + * + * @return the uri + */ + public URI getUri() { + return URI.create(getEntry().getId()); + } } diff --git a/microsoft-azure-api/src/main/resources/package-names.xjb b/microsoft-azure-api/src/main/resources/package-names.xjb index 70e0e3714dd7..3befcf2e0bb0 100644 --- a/microsoft-azure-api/src/main/resources/package-names.xjb +++ b/microsoft-azure-api/src/main/resources/package-names.xjb @@ -4,6 +4,11 @@ xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:version="2.0" jaxb:extensionBindingPrefixes="xjc"> + + + + + diff --git a/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2010.10.servicebus.connect.xsd b/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2010.10.servicebus.connect.xsd index 2c8d69df7be6..a544e3ecfadb 100644 --- a/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2010.10.servicebus.connect.xsd +++ b/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2010.10.servicebus.connect.xsd @@ -2,6 +2,7 @@ - + + @@ -115,6 +117,13 @@ + + + + + + + @@ -150,6 +159,13 @@ + + + + + + + @@ -246,6 +262,13 @@ + + + + + + + @@ -274,6 +297,13 @@ + + + + + + + @@ -330,7 +360,7 @@ - + @@ -397,11 +427,17 @@ + + + + + + + - @@ -532,6 +568,13 @@ + + + + + + + diff --git a/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2011.06.servicebus.xsd b/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2011.06.servicebus.xsd new file mode 100644 index 000000000000..b3bf4be77e9f --- /dev/null +++ b/microsoft-azure-api/src/main/resources/schemas.microsoft.com.netservices.2011.06.servicebus.xsd @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + diff --git a/microsoft-azure-api/src/main/resources/servicebus-atom.xsd b/microsoft-azure-api/src/main/resources/servicebus-atom.xsd index b8387023a54b..6b7f6b1eff23 100644 --- a/microsoft-azure-api/src/main/resources/servicebus-atom.xsd +++ b/microsoft-azure-api/src/main/resources/servicebus-atom.xsd @@ -3,6 +3,9 @@ attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.w3.org/2005/Atom" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/"> + @@ -12,7 +15,6 @@ - @@ -20,7 +22,8 @@ - + + 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 c71781c96fe6..bb996eb10b77 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 @@ -272,7 +272,7 @@ public Task.CreateBatchOperation createTaskOptions(String taskName, int inputAss String configuration = null; switch (encoderType) { case WindowsAzureMediaEncoder: - processor = getMediaProcessorIdByName(MEDIA_PROCESSOR_WINDOWS_AZURE_MEDIA_ENCODER, "2.2.0.0"); + processor = getMediaProcessorIdByName(MEDIA_PROCESSOR_WINDOWS_AZURE_MEDIA_ENCODER, "2.3"); // Full list of configurations strings for version 2.1 is at: // http://msdn.microsoft.com/en-us/library/jj129582.aspx configuration = "VC1 Broadband SD 4x3"; 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 aa8c21ec5cbb..02e0cbee1984 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 @@ -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; @@ -21,11 +21,15 @@ import org.junit.BeforeClass; import com.microsoft.windowsazure.services.core.Configuration; +import com.microsoft.windowsazure.services.core.ServiceException; import com.microsoft.windowsazure.services.serviceBus.models.QueueInfo; import com.microsoft.windowsazure.services.serviceBus.models.ReceiveMessageOptions; import com.microsoft.windowsazure.services.serviceBus.models.TopicInfo; public abstract class IntegrationTestBase { + + private ServiceBusContract service; + @BeforeClass public static void initializeSystem() { System.setProperty("http.keepAlive", "false"); @@ -36,7 +40,7 @@ public void initialize() throws Exception { boolean testAlphaExists = false; Configuration config = createConfiguration(); - ServiceBusContract service = ServiceBusService.create(config); + service = ServiceBusService.create(config); for (QueueInfo queue : iterateQueues(service)) { String queueName = queue.getPath(); if (queueName.startsWith("Test") || queueName.startsWith("test")) { @@ -52,15 +56,21 @@ public void initialize() throws Exception { } } } + + removeTopics(); + + if (!testAlphaExists) { + service.createQueue(new QueueInfo("TestAlpha")); + } + } + + protected void removeTopics() throws ServiceException { for (TopicInfo topic : iterateTopics(service)) { String topicName = topic.getPath(); if (topicName.startsWith("Test") || topicName.startsWith("test")) { service.deleteTopic(topicName); } } - if (!testAlphaExists) { - service.createQueue(new QueueInfo("TestAlpha")); - } } @AfterClass 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 221a358acedc..971df258c02c 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 @@ -37,6 +37,8 @@ import com.microsoft.windowsazure.services.serviceBus.implementation.EmptyRuleAction; import com.microsoft.windowsazure.services.serviceBus.implementation.EntityStatus; import com.microsoft.windowsazure.services.serviceBus.implementation.FalseFilter; +import com.microsoft.windowsazure.services.serviceBus.implementation.MessageCountDetails; +import com.microsoft.windowsazure.services.serviceBus.implementation.RuleDescription; import com.microsoft.windowsazure.services.serviceBus.implementation.SqlFilter; import com.microsoft.windowsazure.services.serviceBus.implementation.SqlRuleAction; import com.microsoft.windowsazure.services.serviceBus.implementation.TrueFilter; @@ -45,10 +47,12 @@ import com.microsoft.windowsazure.services.serviceBus.models.ListQueuesResult; import com.microsoft.windowsazure.services.serviceBus.models.ListRulesResult; import com.microsoft.windowsazure.services.serviceBus.models.ListSubscriptionsResult; +import com.microsoft.windowsazure.services.serviceBus.models.ListTopicsOptions; import com.microsoft.windowsazure.services.serviceBus.models.ListTopicsResult; import com.microsoft.windowsazure.services.serviceBus.models.QueueInfo; import com.microsoft.windowsazure.services.serviceBus.models.ReceiveMessageOptions; import com.microsoft.windowsazure.services.serviceBus.models.ReceiveQueueMessageResult; +import com.microsoft.windowsazure.services.serviceBus.models.ReceiveSubscriptionMessageResult; import com.microsoft.windowsazure.services.serviceBus.models.RuleInfo; import com.microsoft.windowsazure.services.serviceBus.models.SubscriptionInfo; import com.microsoft.windowsazure.services.serviceBus.models.TopicInfo; @@ -175,6 +179,88 @@ public void sendMessageWorks() throws Exception { // Assert } + @Test + public void getQueueMessageCountDetails() throws Exception { + // Arrange + String queueName = "testGetQueueMessageCountDetails"; + service.createQueue(new QueueInfo(queueName)); + service.sendQueueMessage(queueName, new BrokeredMessage("Hello World")); + Long expectedActiveMessageCount = 1L; + Long expectedDeadLetterMessageCount = 0L; + Long expectedScheduledMessageCount = 0L; + Long expectedTransferMessageCount = 0L; + Long expectedTransferDeadLetterMessageCount = 0L; + + // Act + QueueInfo queueInfo = service.getQueue(queueName).getValue(); + MessageCountDetails countDetails = queueInfo.getCountDetails(); + + // Assert + assertEquals(true, queueInfo.isSupportOrdering()); + assertNotNull(countDetails); + assertEquals(expectedActiveMessageCount, countDetails.getActiveMessageCount()); + assertEquals(expectedDeadLetterMessageCount, countDetails.getDeadLetterMessageCount()); + assertEquals(expectedScheduledMessageCount, countDetails.getScheduledMessageCount()); + assertEquals(expectedTransferMessageCount, countDetails.getTransferMessageCount()); + assertEquals(expectedTransferDeadLetterMessageCount, countDetails.getTransferDeadLetterMessageCount()); + + } + + @Test + public void getTopicMessageCountDetails() throws Exception { + // Arrange + String topicName = "TestGetTopicMessageCountDetails"; + service.createTopic(new TopicInfo(topicName)).getValue(); + Long expectedActiveMessageCount = 0L; + Long expectedDeadLetterMessageCount = 0L; + Long expectedScheduledMessageCount = 0L; + Long expectedTransferMessageCount = 0L; + Long expectedTransferDeadLetterMessageCount = 0L; + + // Act + TopicInfo topicInfo = service.getTopic(topicName).getValue(); + MessageCountDetails countDetails = topicInfo.getCountDetails(); + + // Assert + assertNotNull(topicInfo); + assertNotNull(countDetails); + assertEquals(expectedActiveMessageCount, countDetails.getActiveMessageCount()); + assertEquals(expectedDeadLetterMessageCount, countDetails.getDeadLetterMessageCount()); + assertEquals(expectedScheduledMessageCount, countDetails.getScheduledMessageCount()); + assertEquals(expectedTransferMessageCount, countDetails.getTransferMessageCount()); + assertEquals(expectedTransferDeadLetterMessageCount, countDetails.getTransferDeadLetterMessageCount()); + + } + + @Test + public void getSubscriptionMessageCountDetails() throws Exception { + // Arrange + String topicName = "TestGetSubscriptionMessageCountDetails"; + String subscriptionName = "TestGetSubscriptionMessageCountDetails"; + service.createTopic(new TopicInfo(topicName)).getValue(); + service.createSubscription(topicName, new SubscriptionInfo(subscriptionName)); + Long expectedActiveMessageCount = 1L; + Long expectedDeadLetterMessageCount = 0L; + Long expectedScheduledMessageCount = 0L; + Long expectedTransferMessageCount = 0L; + Long expectedTransferDeadLetterMessageCount = 0L; + + // Act + service.sendTopicMessage(topicName, new BrokeredMessage("Hello world!")); + SubscriptionInfo subscriptionInfo = service.getSubscription(topicName, subscriptionName).getValue(); + MessageCountDetails countDetails = subscriptionInfo.getCountDetails(); + + // Assert + assertNotNull(subscriptionInfo); + assertNotNull(countDetails); + assertEquals(expectedActiveMessageCount, countDetails.getActiveMessageCount()); + assertEquals(expectedDeadLetterMessageCount, countDetails.getDeadLetterMessageCount()); + assertEquals(expectedScheduledMessageCount, countDetails.getScheduledMessageCount()); + assertEquals(expectedTransferMessageCount, countDetails.getTransferMessageCount()); + assertEquals(expectedTransferDeadLetterMessageCount, countDetails.getTransferDeadLetterMessageCount()); + + } + @Test public void receiveMessageWorks() throws Exception { // Arrange @@ -240,6 +326,177 @@ public void receiveMessageEmptyQueueWorks() throws Exception { assertNull(receiveQueueMessageResult.getValue()); } + @Test + public void receiveQueueForwardToQueueMessageSuccess() throws Exception { + // Arrange + String sourceQueueName = "TestReceiveQueueForwardToQueueMessageSuccessSource"; + String destinationQueueName = "TestReceiveQueueForwardToQueueMessageSuccessDestination"; + QueueInfo destinationQueueInfo = service.createQueue(new QueueInfo(destinationQueueName)).getValue(); + service.createQueue(new QueueInfo(sourceQueueName).setForwardTo(destinationQueueInfo.getUri().toString())) + .getValue(); + + // Act + service.sendQueueMessage(sourceQueueName, new BrokeredMessage("Hello source queue!")); + ReceiveQueueMessageResult receiveQueueMessageResult = service.receiveQueueMessage(destinationQueueName, + RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveQueueMessageResult); + assertNotNull(receiveQueueMessageResult.getValue()); + } + + @Test + public void receiveUpdatedQueueForwardToQueueMessageSuccess() throws Exception { + // Arrange + String sourceQueueName = "TestReceiveUpdatedQueueForwardToQueueMessageSuccessSource"; + String destinationQueueName = "TestReceiveUpdatedQueueForwardToQueueMessageSuccessDestination"; + QueueInfo destinationQueueInfo = service.createQueue(new QueueInfo(destinationQueueName)).getValue(); + QueueInfo sourceQueueInfo = new QueueInfo(sourceQueueName); + service.createQueue(sourceQueueInfo).getValue(); + service.updateQueue(sourceQueueInfo.setForwardTo(destinationQueueInfo.getUri().toString())); + + // Act + service.sendQueueMessage(sourceQueueName, new BrokeredMessage("Hello source queue!")); + ReceiveQueueMessageResult receiveQueueMessageResult = service.receiveQueueMessage(destinationQueueName, + RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveQueueMessageResult); + assertNotNull(receiveQueueMessageResult.getValue()); + } + + @Test + public void receiveSubscriptionForwardToQueueMessageSuccess() throws Exception { + // Arrange + String sourceTopicName = "TestReceiveSubForwardToQueueMessageSuccessSource"; + String sourceSubscriptionName = "TestReceiveSubForwardToQueueMessageSuccessSource"; + String destinationQueueName = "TestReceiveSubForwardToQueueMessageSuccessDestination"; + service.createTopic(new TopicInfo(sourceTopicName)).getValue(); + QueueInfo destinationQueueInfo = service.createQueue(new QueueInfo(destinationQueueName)).getValue(); + service.createSubscription(sourceTopicName, + new SubscriptionInfo(sourceSubscriptionName).setForwardTo(destinationQueueInfo.getUri().toString())); + + // Act + service.sendTopicMessage(sourceTopicName, new BrokeredMessage("Hello source queue!")); + ReceiveQueueMessageResult receiveQueueMessageResult = service.receiveQueueMessage(destinationQueueName, + RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveQueueMessageResult); + assertNotNull(receiveQueueMessageResult.getValue()); + } + + @Test + public void receiveUpdatedSubscriptionForwardToQueueMessageSuccess() throws Exception { + // Arrange + String sourceTopicName = "TestUpdatedReceiveSubForwardToQMessageSuccessSrc"; + String sourceSubscriptionName = "TestUpdatedReceiveSubForwardToQMessageSuccessSrc"; + String destinationQueueName = "TestUpdatedReceiveSubForwardToQMessageSuccessDest"; + service.createTopic(new TopicInfo(sourceTopicName)).getValue(); + QueueInfo destinationQueueInfo = service.createQueue(new QueueInfo(destinationQueueName)).getValue(); + SubscriptionInfo sourceSubscriptionInfo = service.createSubscription(sourceTopicName, + new SubscriptionInfo(sourceSubscriptionName)).getValue(); + service.updateSubscription(sourceTopicName, + sourceSubscriptionInfo.setForwardTo(destinationQueueInfo.getUri().toString())); + // Act + service.sendTopicMessage(sourceTopicName, new BrokeredMessage("Hello source queue!")); + ReceiveQueueMessageResult receiveQueueMessageResult = service.receiveQueueMessage(destinationQueueName, + RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveQueueMessageResult); + assertNotNull(receiveQueueMessageResult.getValue()); + } + + @Test + public void receiveQueueForwardToTopicMessageSuccess() throws Exception { + // Arrange + String sourceQueueName = "TestReceiveQueueForwardToTopicMessageSuccessSource"; + String destinationTopicName = "TestReceiveQueueForwardToTopicMessageSuccessDestination"; + String destinationSubscriptionName = "TestReceiveQueueForwardToTopicMessageSuccessDestination"; + TopicInfo destinationTopicInfo = service.createTopic(new TopicInfo(destinationTopicName)).getValue(); + service.createQueue(new QueueInfo(sourceQueueName).setForwardTo(destinationTopicInfo.getUri().toString())) + .getValue(); + + // Act + service.sendQueueMessage(sourceQueueName, new BrokeredMessage("Hello source queue!")); + ReceiveSubscriptionMessageResult receiveSubscriptionMessageResult = service.receiveSubscriptionMessage( + destinationTopicName, destinationSubscriptionName, RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveSubscriptionMessageResult); + assertNotNull(receiveSubscriptionMessageResult.getValue()); + } + + @Test + public void receiveUpdatedQueueForwardToTopicMessageSuccess() throws Exception { + // Arrange + String sourceQueueName = "TestReceiveUpdatedQueueForwardToTopicMessageSuccessSource"; + String destinationTopicName = "TestReceiveUpdatedQueueForwardToTopicMessageSuccessDestination"; + String destinationSubscriptionName = "TestReceiveUpdatedQueueForwardToTopicMessageSuccessDestination"; + TopicInfo destinationTopicInfo = service.createTopic(new TopicInfo(destinationTopicName)).getValue(); + QueueInfo sourceQueueInfo = new QueueInfo(sourceQueueName); + service.createQueue(sourceQueueInfo).getValue(); + service.updateQueue(sourceQueueInfo.setForwardTo(destinationTopicInfo.getUri().toString())); + + // Act + service.sendQueueMessage(sourceQueueName, new BrokeredMessage("Hello source queue!")); + ReceiveSubscriptionMessageResult receiveSubscriptionMessageResult = service.receiveSubscriptionMessage( + destinationTopicName, destinationSubscriptionName, RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveSubscriptionMessageResult); + assertNotNull(receiveSubscriptionMessageResult.getValue()); + } + + @Test + public void receiveSubscriptionForwardToTopicMessageSuccess() throws Exception { + // Arrange + String sourceTopicName = "TestReceiveSubForwardToTopMessageSuccessSrc"; + String sourceSubscriptionName = "TestReceiveSubForwardToTopMessageSuccessSrc"; + String destinationTopicName = "TestReceiveSubForwardToTopMessageSuccessDest"; + String destinationSubscriptionName = "TestReceiveSubForwardToTopMessageSuccessDest"; + service.createTopic(new TopicInfo(sourceTopicName)).getValue(); + TopicInfo destinationTopicInfo = service.createTopic(new TopicInfo(destinationTopicName)).getValue(); + service.createSubscription(destinationTopicName, new SubscriptionInfo(destinationSubscriptionName)).getValue(); + service.createSubscription(sourceTopicName, + new SubscriptionInfo(sourceSubscriptionName).setForwardTo(destinationTopicInfo.getUri().toString())); + + // Act + service.sendTopicMessage(sourceTopicName, new BrokeredMessage("Hello source queue!")); + ReceiveSubscriptionMessageResult receiveSubscriptionMessageResult = service.receiveSubscriptionMessage( + destinationTopicName, destinationSubscriptionName, RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveSubscriptionMessageResult); + assertNotNull(receiveSubscriptionMessageResult.getValue()); + } + + @Test + public void receiveUpdatedSubscriptionForwardToTopicMessageSuccess() throws Exception { + // Arrange + String sourceTopicName = "TestReceiveSubForwardToTopMessageSuccessSrc"; + String sourceSubscriptionName = "TestReceiveSubForwardToTopMessageSuccessSrc"; + String destinationTopicName = "TestReceiveSubForwardToTopMessageSuccessDest"; + String destinationSubscriptionName = "TestReceiveSubForwardToTopMessageSuccessDest"; + service.createTopic(new TopicInfo(sourceTopicName)).getValue(); + TopicInfo destinationTopicInfo = service.createTopic(new TopicInfo(destinationTopicName)).getValue(); + service.createSubscription(destinationTopicName, new SubscriptionInfo(destinationSubscriptionName)).getValue(); + SubscriptionInfo sourceSubscriptionInfo = service.createSubscription(sourceTopicName, + new SubscriptionInfo(sourceSubscriptionName)).getValue(); + service.updateSubscription(sourceTopicName, + sourceSubscriptionInfo.setForwardTo(destinationTopicInfo.getUri().toString())); + + // Act + service.sendTopicMessage(sourceTopicName, new BrokeredMessage("Hello source queue!")); + ReceiveSubscriptionMessageResult receiveSubscriptionMessageResult = service.receiveSubscriptionMessage( + destinationTopicName, destinationSubscriptionName, RECEIVE_AND_DELETE_5_SECONDS); + + // Assert + assertNotNull(receiveSubscriptionMessageResult); + assertNotNull(receiveSubscriptionMessageResult.getValue()); + } + @Test public void peekLockMessageWorks() throws Exception { // Arrange @@ -387,6 +644,65 @@ public void topicCanBeCreatedListedFetchedAndDeleted() throws ServiceException { assertEquals(listed.getItems().size() - 1, listed2.getItems().size()); } + @Test + public void listTopicsUnderASpecificPath() throws ServiceException { + // Arrange + String topicName = "testPathA/testPathB/listTopicUnderASpecificPath"; + + // Act + TopicInfo topicInfo = service.createTopic(new TopicInfo().setPath(topicName)).getValue(); + ListTopicsResult listTopicResult = service.listTopics(new ListTopicsOptions() + .setFilter("startswith(path, 'testPathA/testPathB') eq true")); + + // Assert + assertNotNull(topicInfo); + assertEquals(1, listTopicResult.getItems().size()); + } + + @Test + public void listTopicsUpdatedInLastFiveMinutes() throws ServiceException { + String topicName = "testListTopicUpdatedInLastFiveMinutes"; + + // Act + TopicInfo topicInfo = service.createTopic(new TopicInfo().setPath(topicName)).getValue(); + ListTopicsResult listTopicResult = service.listTopics(new ListTopicsOptions() + .setFilter("ModifiedAt gt '1/25/2012 3:41:41 PM'")); + + // Assert + assertNotNull(topicInfo); + assertEquals(1, listTopicResult.getItems().size()); + } + + @Test + public void listTopicsAccessedSinceASpecificTime() throws ServiceException { + removeTopics(); + String topicName = "testListTopicAccessedInLastFiveMinutes"; + + // Act + TopicInfo topicInfo = service.createTopic(new TopicInfo().setPath(topicName)).getValue(); + ListTopicsResult listTopicResult = service.listTopics(new ListTopicsOptions() + .setFilter("AccessedAt gt '1/25/2012 3:41:41 PM'")); + + // Assert + assertNotNull(topicInfo); + assertEquals(0, listTopicResult.getItems().size()); + } + + @Test + public void listTopicsCreatedSinceASpecificTime() throws ServiceException { + removeTopics(); + String topicName = "testListTopicCreatedInLastFiveMinutes"; + + // Act + TopicInfo topicInfo = service.createTopic(new TopicInfo().setPath(topicName)).getValue(); + ListTopicsResult listTopicResult = service.listTopics(new ListTopicsOptions() + .setFilter("CreatedAt gt '1/25/2012 3:41:41 PM'")); + + // Assert + assertNotNull(topicInfo); + assertEquals(1, listTopicResult.getItems().size()); + } + @Test public void topicCreatedContainsMetadata() throws ServiceException { // Arrange @@ -469,6 +785,55 @@ public void subscriptionsCanBeCreatedOnTopics() throws Exception { assertNotNull(created.getAutoDeleteOnIdle()); } + @Test + public void createSubscriptionWithCorrelationFilter() throws Exception { + // Arrange + String topicName = "testCreateSubscriptionWithCorrelationFilter"; + String expectedCorrelationId = "sampleCorrelationId"; + String expectedContentType = "sampleContentType"; + String expectedLabel = "sampleLabel"; + String expectedMessageId = "sampleMessageId"; + String expectedSessionId = "sampleSessionId"; + String expectedReplyTo = "sampleReplyTo"; + String expectedTo = "sampleTo"; + service.createTopic(new TopicInfo(topicName)); + CorrelationFilter correlationFilter = new CorrelationFilter(); + correlationFilter.setCorrelationId(expectedCorrelationId); + correlationFilter.setContentType(expectedContentType); + correlationFilter.setLabel(expectedLabel); + correlationFilter.setMessageId(expectedMessageId); + correlationFilter.setReplyTo(expectedReplyTo); + correlationFilter.setSessionId(expectedSessionId); + correlationFilter.setTo(expectedTo); + RuleDescription ruleDescription = new RuleDescription(); + ruleDescription.setFilter(correlationFilter); + + // Act + SubscriptionInfo created = service.createSubscription(topicName, + new SubscriptionInfo("MySubscription").setDefaultRuleDescription(ruleDescription)).getValue(); + + RuleInfo ruleInfo = service.getRule(topicName, "MySubscription", "$Default").getValue(); + CorrelationFilter correlationFilterResult = (CorrelationFilter) ruleInfo.getFilter(); + + // Assert + assertNotNull(created); + assertEquals("MySubscription", created.getName()); + assertEquals(false, created.isRequiresSession()); + assertEquals(true, created.isDeadLetteringOnFilterEvaluationExceptions()); + assertNotNull(created.getCreatedAt()); + assertNotNull(created.getUpdatedAt()); + assertNotNull(created.getAccessedAt()); + assertNotNull(created.getAutoDeleteOnIdle()); + assertNotNull(correlationFilterResult); + assertEquals(expectedCorrelationId, correlationFilterResult.getCorrelationId()); + assertEquals(expectedContentType, correlationFilterResult.getContentType()); + assertEquals(expectedLabel, correlationFilterResult.getLabel()); + assertEquals(expectedMessageId, correlationFilterResult.getMessageId()); + assertEquals(expectedSessionId, correlationFilterResult.getSessionId()); + assertEquals(expectedReplyTo, correlationFilterResult.getReplyTo()); + assertEquals(expectedTo, correlationFilterResult.getTo()); + } + @Test public void subscriptionsCanBeListed() throws Exception { // Arrange