![JAR search and dependency download from the Maven repository](/logo.png)
com.microsoft.windowsazure.services.table.client.CloudTableClient Maven / Gradle / Ivy
/**
* 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.table.client;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import javax.xml.stream.XMLStreamException;
import com.microsoft.windowsazure.services.core.storage.DoesServiceRequest;
import com.microsoft.windowsazure.services.core.storage.OperationContext;
import com.microsoft.windowsazure.services.core.storage.ResultContinuation;
import com.microsoft.windowsazure.services.core.storage.ResultContinuationType;
import com.microsoft.windowsazure.services.core.storage.ResultSegment;
import com.microsoft.windowsazure.services.core.storage.ServiceClient;
import com.microsoft.windowsazure.services.core.storage.StorageCredentials;
import com.microsoft.windowsazure.services.core.storage.StorageException;
import com.microsoft.windowsazure.services.core.storage.utils.Utility;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.ExecutionEngine;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.LazySegmentedIterable;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.SegmentedStorageOperation;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.StorageOperation;
import com.microsoft.windowsazure.services.queue.client.CloudQueue;
/**
* Provides a service client for accessing the Windows Azure Table service.
*
* The {@link CloudTableClient} class encapsulates the base URI for the Table service endpoint and the credentials for
* accessing the storage account, and provides methods to create, delete, list, and query tables, as well as methods to
* execute operations and queries on table entities. These methods invoke Storage Service REST API operations to make
* the requests and obtain the results that are returned.
*
* A Table service endpoint is the base URI for Table service resources, including the DNS name of the storage account:
*
*     http://myaccount.table.core.windows.net
* For more information, see the MSDN topic Addressing Table Service Resources.
*
* The credentials can be a combination of the storage account name and a key, or a shared access signature. For more
* information, see the MSDN topic Authenticating Access to Your Storage
* Account.
*
*/
public final class CloudTableClient extends ServiceClient {
/**
* Reserved for internal use. An {@link EntityResolver} that projects table entity data as a String
* containing the table name.
*/
private final EntityResolver tableNameResolver = new EntityResolver() {
@Override
public String resolve(String partitionKey, String rowKey, Date timeStamp,
HashMap properties, String etag) {
return properties.get(TableConstants.TABLE_NAME).getValueAsString();
}
};
/**
* Initializes an instance of the {@link CloudTableClient} class using a Table service endpoint.
*
* A {@link CloudTableClient} initialized with this constructor must have storage account credentials added before
* it can be used to access the Windows Azure storage service.
*
* @param baseUri
* A java.net.URI
that represents the Table service endpoint used to initialize the
* client.
*/
public CloudTableClient(final URI baseUri) {
this(baseUri, null);
this.setTimeoutInMs(TableConstants.TABLE_DEFAULT_TIMEOUT_IN_MS);
}
/**
* Initializes an instance of the {@link CloudTableClient} class using a Table service endpoint and
* storage account credentials.
*
* @param baseUri
* A java.net.URI
object that represents the Table service endpoint used to initialize the
* client.
* @param credentials
* A {@link StorageCredentials} object that represents the storage account credentials for access.
*/
public CloudTableClient(final URI baseUri, StorageCredentials credentials) {
super(baseUri, credentials);
this.setTimeoutInMs(TableConstants.TABLE_DEFAULT_TIMEOUT_IN_MS);
}
/**
* Gets a {@link CloudTable} object that represents the storage service
* queue for the specified address.
*
* @param tableAddress
* A String
that represents the name of the table,
* or the absolute URI to the queue.
*
* @return A {@link CloudQueue} object that represents a reference to the
* table.
*
* @throws URISyntaxException
* If the resource URI is invalid.
* @throws StorageException
* If a storage service error occurred during the operation.
*/
public CloudTable getTableReference(final String tableAddress) throws URISyntaxException, StorageException {
Utility.assertNotNullOrEmpty("tableAddress", tableAddress);
return new CloudTable(tableAddress, this);
}
/**
* Executes the specified batch operation on a table as an atomic operation. A batch operation may contain up to 100
* individual table operations, with the requirement that each operation entity must have same partition key. Only
* one retrieve operation is allowed per batch. Note that the total payload of a batch operation is limited to 4MB.
*
* This method invokes an Entity Group
* Transaction on the REST API to execute the specified batch operation on the table as an atomic unit, using
* the Table service endpoint and storage account credentials of this instance.
*
* @param tableName
* A String
containing the name of the table to execute the operations on.
* @param batch
* The {@link TableBatchOperation} object representing the operations to execute on the table.
*
* @return
* A java.util.ArrayList
of {@link TableResult} that contains the results, in order, of
* each {@link TableOperation} in the {@link TableBatchOperation} on the named table.
*
* @throws StorageException
* if an error occurs accessing the storage service, or the operation fails.
*/
@DoesServiceRequest
public ArrayList execute(final String tableName, final TableBatchOperation batch)
throws StorageException {
return this.execute(tableName, batch, null, null);
}
/**
* Executes the specified batch operation on a table as an atomic operation, using the specified
* {@link TableRequestOptions} and {@link OperationContext}. A batch operation may contain up to 100 individual
* table operations, with the requirement that each operation entity must have same partition key. Only one retrieve
* operation is allowed per batch. Note that the total payload of a batch operation is limited to 4MB.
*
* This method invokes an Entity Group
* Transaction on the REST API to execute the specified batch operation on the table as an atomic unit, using
* the Table service endpoint and storage account credentials of this instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param tableName
* A String
containing the name of the table to execute the operations on.
* @param batch
* The {@link TableBatchOperation} object representing the operations to execute on the table.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A java.util.ArrayList
of {@link TableResult} that contains the results, in order, of
* each {@link TableOperation} in the {@link TableBatchOperation} on the named table.
*
* @throws StorageException
* if an error occurs accessing the storage service, or the operation fails.
*/
@DoesServiceRequest
public ArrayList execute(final String tableName, final TableBatchOperation batch,
TableRequestOptions options, OperationContext opContext) throws StorageException {
Utility.assertNotNull("batch", batch);
if (opContext == null) {
opContext = new OperationContext();
}
if (options == null) {
options = new TableRequestOptions();
}
opContext.initialize();
options.applyDefaults(this);
return batch.execute(this, tableName, options, opContext);
}
/**
* Executes the operation on a table.
*
* This method will invoke the Table
* Service REST API to execute the specified operation on the table, using the Table service endpoint and
* storage account credentials of this instance.
*
* @param tableName
* A String
containing the name of the table to execute the operation on.
* @param operation
* The {@link TableOperation} object representing the operation to execute on the table.
*
* @return
* A {@link TableResult} containing the result of executing the {@link TableOperation} on the table.
*
* @throws StorageException
* if an error occurs accessing the storage service, or the operation fails.
*/
@DoesServiceRequest
public TableResult execute(final String tableName, final TableOperation operation) throws StorageException {
return this.execute(tableName, operation, null, null);
}
/**
* Executes the operation on a table, using the specified {@link TableRequestOptions} and {@link OperationContext}.
*
* This method will invoke the Table
* Service REST API to execute the specified operation on the table, using the Table service endpoint and
* storage account credentials of this instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param tableName
* A String
containing the name of the table to execute the operation on.
* @param operation
* The {@link TableOperation} object representing the operation to execute on the table.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A {@link TableResult} containing the result of executing the {@link TableOperation} on the table.
*
* @throws StorageException
* if an error occurs accessing the storage service, or the operation fails.
*/
@DoesServiceRequest
public TableResult execute(final String tableName, final TableOperation operation,
final TableRequestOptions options, final OperationContext opContext) throws StorageException {
Utility.assertNotNull("operation", operation);
return operation.execute(this, tableName, options, opContext);
}
/**
* Executes a query, applying the specified {@link EntityResolver} to the result.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use.
* @param resolver
* An {@link EntityResolver} instance which creates a projection of the table query result entities into
* the specified type R
.
*
* @return
* A collection implementing the Iterable
interface containing the projection into type
* R
of the results of executing the query.
*/
@DoesServiceRequest
public Iterable execute(final TableQuery> query, final EntityResolver resolver) {
return this.execute(query, resolver, null, null);
}
/**
* Executes a query, applying the specified {@link EntityResolver} to the result, using the
* specified {@link TableRequestOptions} and {@link OperationContext}.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use.
* @param resolver
* An {@link EntityResolver} instance which creates a projection of the table query result entities into
* the specified type R
.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A collection implementing the Iterable
interface containing the projection into type
* R
of the results of executing the query.
*/
@DoesServiceRequest
@SuppressWarnings("unchecked")
public Iterable execute(final TableQuery> query, final EntityResolver resolver,
final TableRequestOptions options, final OperationContext opContext) {
Utility.assertNotNull("query", query);
Utility.assertNotNull("Query requires a valid class type or resolver.", resolver);
return (Iterable) this.generateIteratorForQuery(query, resolver, options, opContext);
}
/**
* Executes a query.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use,
* specialized for a type T implementing {@link TableEntity}.
*
* @return
* A collection implementing the Iterable
interface specialized for type T of the results of
* executing the query.
*/
@DoesServiceRequest
public Iterable execute(final TableQuery query) {
return this.execute(query, null, null);
}
/**
* Executes a query, using the specified {@link TableRequestOptions} and {@link OperationContext}.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use,
* specialized for a type T implementing {@link TableEntity}.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A collection implementing the Iterable
interface specialized for type T of the results of
* executing the query.
*/
@SuppressWarnings("unchecked")
@DoesServiceRequest
public Iterable execute(final TableQuery query, final TableRequestOptions options,
final OperationContext opContext) {
Utility.assertNotNull("query", query);
return (Iterable) this.generateIteratorForQuery(query, null, options, opContext);
}
/**
* Executes a query in segmented mode with the specified {@link ResultContinuation} continuation token,
* applying the {@link EntityResolver} to the result.
* Executing a query with executeSegmented
allows the query to be resumed after returning partial
* results, using information returned by the server in the {@link ResultSegment} object.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use.
* @param resolver
* An {@link EntityResolver} instance which creates a projection of the table query result entities into
* the specified type R
.
* @param continuationToken
* A {@link ResultContinuation} object representing a continuation token from the server when the
* operation returns a partial result. Specify null
on the initial call. Call the
* {@link ResultSegment#getContinuationToken()} method on the result to obtain the
* {@link ResultContinuation} object to use in the next call to resume the query.
*
* @return
* A {@link ResultSegment} containing the projection into type R
of the results of executing
* the query.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the query is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
public ResultSegment executeSegmented(final TableQuery> query, final EntityResolver resolver,
final ResultContinuation continuationToken) throws IOException, URISyntaxException, StorageException {
return this.executeSegmented(query, resolver, continuationToken, null, null);
}
/**
* Executes a query in segmented mode with the specified {@link ResultContinuation} continuation token,
* using the specified {@link TableRequestOptions} and {@link OperationContext}, applying the {@link EntityResolver}
* to the result.
* Executing a query with executeSegmented
allows the query to be resumed after returning partial
* results, using information returned by the server in the {@link ResultSegment} object.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use.
* @param resolver
* An {@link EntityResolver} instance which creates a projection of the table query result entities into
* the specified type R
.
* @param continuationToken
* A {@link ResultContinuation} object representing a continuation token from the server when the
* operation returns a partial result. Specify null
on the initial call. Call the
* {@link ResultSegment#getContinuationToken()} method on the result to obtain the
* {@link ResultContinuation} object to use in the next call to resume the query.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A {@link ResultSegment} containing the projection into type R
of the results of executing
* the query.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the query is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
@SuppressWarnings("unchecked")
public ResultSegment executeSegmented(final TableQuery> query, final EntityResolver resolver,
final ResultContinuation continuationToken, final TableRequestOptions options,
final OperationContext opContext) throws IOException, URISyntaxException, StorageException {
Utility.assertNotNull("Query requires a valid class type or resolver.", resolver);
return (ResultSegment) this
.executeQuerySegmentedImpl(query, resolver, continuationToken, options, opContext);
}
/**
* Executes a query in segmented mode with a {@link ResultContinuation} continuation token.
* Executing a query with executeSegmented
allows the query to be resumed after returning partial
* results, using information returned by the server in the {@link ResultSegment} object.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use,
* specialized for a type T implementing {@link TableEntity}.
* @param continuationToken
* A {@link ResultContinuation} object representing a continuation token from the server when the
* operation returns a partial result. Specify null
on the initial call. Call the
* {@link ResultSegment#getContinuationToken()} method on the result to obtain the
* {@link ResultContinuation} object to use in the next call to resume the query.
*
* @return
* A {@link ResultSegment} specialized for type T of the results of executing the query.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the query is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
public ResultSegment executeSegmented(final TableQuery query,
final ResultContinuation continuationToken) throws IOException, URISyntaxException, StorageException {
return this.executeSegmented(query, continuationToken, null, null);
}
/**
* Executes a query in segmented mode with a {@link ResultContinuation} continuation token,
* using the specified {@link TableRequestOptions} and {@link OperationContext}.
* Executing a query with executeSegmented
allows the query to be resumed after returning partial
* results, using information returned by the server in the {@link ResultSegment} object.
*
* This method will invoke a Query
* Entities operation on the Table
* Service REST API to query the table, using the Table service endpoint and storage account credentials of this
* instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param query
* A {@link TableQuery} instance specifying the table to query and the query parameters to use,
* specialized for a type T implementing {@link TableEntity}.
* @param continuationToken
* A {@link ResultContinuation} object representing a continuation token from the server when the
* operation returns a partial result. Specify null
on the initial call. Call the
* {@link ResultSegment#getContinuationToken()} method on the result to obtain the
* {@link ResultContinuation} object to use in the next call to resume the query.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A {@link ResultSegment} specialized for type T of the results of executing the query.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the query is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
@SuppressWarnings("unchecked")
public ResultSegment executeSegmented(final TableQuery query,
final ResultContinuation continuationToken, final TableRequestOptions options,
final OperationContext opContext) throws IOException, URISyntaxException, StorageException {
Utility.assertNotNull("query", query);
return (ResultSegment) this.executeQuerySegmentedImpl(query, null, continuationToken, options, opContext);
}
/**
* Lists the table names in the storage account.
*
* This method invokes the Query
* Tables REST API to list the table names, using the Table service endpoint and storage account credentials of
* this instance.
*
* @return
* An Iterable
collection of the table names in the storage account.
*/
@DoesServiceRequest
public Iterable listTables() {
return this.listTables(null);
}
/**
* Lists the table names in the storage account that match the specified prefix.
*
* This method invokes the Query
* Tables REST API to list the table names that match the prefix, using the Table service endpoint and storage
* account credentials of this instance.
*
* @param prefix
* A String
containing the prefix to match on table names to return.
*
* @return
* An Iterable
collection of the table names in the storage account that match the specified
* prefix.
*/
@DoesServiceRequest
public Iterable listTables(final String prefix) {
return this.listTables(prefix, null, null);
}
/**
* Lists the table names in the storage account that match the specified prefix, using the specified
* {@link TableRequestOptions} and {@link OperationContext}.
*
* This method invokes the Query
* Tables REST API to list the table names that match the prefix, using the Table service endpoint and storage
* account credentials of this instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param prefix
* A String
containing the prefix to match on table names to return.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* An Iterable
collection of the table names in the storage account that match the specified
* prefix.
*/
@DoesServiceRequest
public Iterable listTables(final String prefix, final TableRequestOptions options,
final OperationContext opContext) {
return this.execute(this.generateListTablesQuery(prefix), this.tableNameResolver, options, opContext);
}
/**
* Lists the table names in the storage account in segmented mode. This method allows listing of tables to be
* resumed after returning a partial set of results, using information returned by the server in the
* {@link ResultSegment} object.
*
* This method invokes the Query
* Tables REST API to list the table names, using the Table service endpoint and storage account credentials of
* this instance.
*
* @return
* A {@link ResultSegment} of String
objects containing table names in the storage account.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the operation is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
public ResultSegment listTablesSegmented() throws IOException, URISyntaxException, StorageException {
return this.listTablesSegmented(null);
}
/**
* Lists the table names in the storage account that match the specified prefix in segmented mode. This method
* allows listing of tables to be resumed after returning a partial set of results, using information returned by
* the server in the {@link ResultSegment} object.
*
* This method invokes the Query
* Tables REST API to list the table names that match the prefix, using the Table service endpoint and storage
* account credentials of this instance.
*
* @param prefix
* A String
containing the prefix to match on table names to return.
*
* @return
* A {@link ResultSegment} of String
objects containing table names matching the prefix in the
* storage account.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the operation is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
public ResultSegment listTablesSegmented(final String prefix) throws IOException, URISyntaxException,
StorageException {
return this.listTablesSegmented(prefix, null, null, null, null);
}
/**
* Lists up to the specified maximum of the table names in the storage account that match the specified prefix in a
* resumable mode with the specified {@link ResultContinuation} continuation token, using the specified
* {@link TableRequestOptions} and {@link OperationContext}. This method allows listing of tables to be resumed
* after returning a page of results, using information returned by the server in the {@link ResultSegment} object.
*
* This method invokes the Query
* Tables REST API to list the table names that match the prefix, using the Table service endpoint and storage
* account credentials of this instance.
*
* Use the {@link TableRequestOptions} to override execution options such as the timeout or retry policy for the
* operation.
*
* @param prefix
* A String
containing the prefix to match on table names to return.
* @param maxResults
* The maximum number of table names to return in the {@link ResultSegment}. If this parameter is null,
* the query will list up to the maximum 1,000 results.
* @param continuationToken
* A {@link ResultContinuation} object representing a continuation token from the server when the
* operation returns a partial result. Specify null
on the initial call. Call the
* {@link ResultSegment#getContinuationToken()} method on the result to obtain the
* {@link ResultContinuation} object to use in the next call to resume the query.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
*
* @return
* A {@link ResultSegment} of String
objects containing table names in the storage account.
*
* @throws IOException
* if an IO error occurred during the operation.
* @throws URISyntaxException
* if the URI generated for the operation is invalid.
* @throws StorageException
* if a storage service error occurred during the operation.
*/
@DoesServiceRequest
public ResultSegment listTablesSegmented(final String prefix, final Integer maxResults,
final ResultContinuation continuationToken, final TableRequestOptions options,
final OperationContext opContext) throws IOException, URISyntaxException, StorageException {
return this.executeSegmented(this.generateListTablesQuery(prefix).take(maxResults), this.tableNameResolver,
continuationToken, options, opContext);
}
/**
* Reserved for internal use. Generates a query to list table names with the given prefix.
*
* @param prefix
* A String
containing the prefix to match on table names to return.
* @return
* A {@link TableQuery} instance for listing table names with the specified prefix.
*/
private TableQuery generateListTablesQuery(final String prefix) {
TableQuery listQuery = TableQuery. from(
TableConstants.TABLES_SERVICE_TABLES_NAME, TableServiceEntity.class);
if (!Utility.isNullOrEmpty(prefix)) {
// Append Max char to end '{' is 1 + 'z' in AsciiTable > uppperBound = prefix + '{'
final String prefixFilter = String.format("(%s ge '%s') and (%s lt '%s{')", TableConstants.TABLE_NAME,
prefix, TableConstants.TABLE_NAME, prefix);
listQuery = listQuery.where(prefixFilter);
}
return listQuery;
}
/**
* Reserved for internal use. Implements the REST API call at the core of a segmented table query
* operation.
*
* @param queryToExecute
* The {@link TableQuery} to execute.
* @param resolver
* An {@link EntityResolver} instance to use to project the result entity as an instance of type
* R
. Pass null
to return the results as the table entity type.
* @param continuationToken
* The {@link ResultContinuation} to pass with the operation to resume a query, if any. Pass
* null
for an initial query.
* @param taskReference
* A reference to the {@link StorageOperation} implementing the segmented operation.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation.
* @param opContext
* An {@link OperationContext} object for tracking the current operation.
* @return
* A {@link ResultSegment} containing a collection of the query results specialized for the
* {@link TableEntity} or {@link EntityResolver} type returned by the query.
* @throws StorageException
* if a Storage service error occurs.
* @throws IOException
* if an IO error occurs.
* @throws URISyntaxException
* if the URI generated for the query is invalid.
* @throws XMLStreamException
* if an error occurs accessing the XMLStreamReader
.
* @throws ParseException
* if an error occurs in parsing the response.
* @throws InstantiationException
* if an error occurs in object construction.
* @throws IllegalAccessException
* if an error occurs in reflection on an object type.
* @throws InvalidKeyException
* if the key for an entity is invalid.
*/
@SuppressWarnings("unchecked")
protected ResultSegment> executeQuerySegmentedCore(final TableQuery queryToExecute,
final EntityResolver resolver, final ResultContinuation continuationToken,
final StorageOperation, ?, ?> taskReference, final TableRequestOptions options,
final OperationContext opContext) throws StorageException, IOException, URISyntaxException,
XMLStreamException, ParseException, InstantiationException, IllegalAccessException, InvalidKeyException {
if (resolver == null) {
Utility.assertNotNull("Query requires a valid class type or resolver.", queryToExecute.getClazzType());
}
final HttpURLConnection queryRequest = TableRequest.query(this.getTransformedEndPoint(opContext),
queryToExecute.getSourceTableName(), null/* identity */, options.getTimeoutIntervalInMs(),
queryToExecute.generateQueryBuilder(), continuationToken, options, opContext);
this.getCredentials().signRequestLite(queryRequest, -1L, opContext);
ExecutionEngine.processRequest(queryRequest, opContext, taskReference.getResult());
if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) {
throw TableServiceException.generateTableServiceException(true, taskReference.getResult(), null,
queryRequest.getErrorStream());
}
ODataPayload clazzResponse = null;
ODataPayload resolvedResponse = null;
InputStream inStream = queryRequest.getInputStream();
try {
if (resolver == null) {
clazzResponse = (ODataPayload) AtomPubParser.parseResponse(inStream, queryToExecute.getClazzType(),
null, opContext);
}
else {
resolvedResponse = (ODataPayload) AtomPubParser.parseResponse(inStream,
queryToExecute.getClazzType(), resolver, opContext);
}
}
finally {
inStream.close();
}
final ResultContinuation nextToken = TableResponse.getTableContinuationFromResponse(queryRequest);
if (resolver == null) {
return new ResultSegment(clazzResponse.results,
queryToExecute.getTakeCount() == null ? clazzResponse.results.size()
: queryToExecute.getTakeCount(), nextToken);
}
else {
return new ResultSegment(resolvedResponse.results,
queryToExecute.getTakeCount() == null ? resolvedResponse.results.size()
: queryToExecute.getTakeCount(), nextToken);
}
}
/**
* Reserved for internal use. Executes a segmented query operation using the specified retry and timeout policies.
*
* @param queryToExecute
* The {@link TableQuery} to execute.
* @param resolver
* An {@link EntityResolver} instance which creates a projection of the table query result entities into
* the specified type R
. Pass null
to return the results as the table entity
* type.
* @param continuationToken
* The {@link ResultContinuation} to pass with the operation to resume a query, if any. Pass
* null
for an initial query.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
* @return
* A {@link ResultSegment} containing a collection of the query results specialized for the
* {@link TableEntity} or {@link EntityResolver} type returned by the query.
* @throws StorageException
* if a Storage service error occurs.
*/
protected ResultSegment> executeQuerySegmentedImpl(final TableQuery queryToExecute,
final EntityResolver resolver, final ResultContinuation continuationToken, TableRequestOptions options,
OperationContext opContext) throws StorageException {
if (opContext == null) {
opContext = new OperationContext();
}
if (options == null) {
options = new TableRequestOptions();
}
opContext.initialize();
options.applyDefaults(this);
Utility.assertContinuationType(continuationToken, ResultContinuationType.TABLE);
final StorageOperation, ResultSegment>> impl = new StorageOperation, ResultSegment>>(
options) {
@Override
public ResultSegment> execute(final CloudTableClient client, final TableQuery queryRef,
final OperationContext opContext) throws Exception {
return CloudTableClient.this.executeQuerySegmentedCore(queryRef, resolver, continuationToken, this,
(TableRequestOptions) this.getRequestOptions(), opContext);
}
};
return ExecutionEngine.executeWithRetry(this, queryToExecute, impl, options.getRetryPolicyFactory(), opContext);
}
protected final URI getTransformedEndPoint(final OperationContext opContext) throws URISyntaxException,
StorageException {
if (this.getCredentials().doCredentialsNeedTransformUri()) {
if (this.getEndpoint().isAbsolute()) {
return this.getCredentials().transformUri(this.getEndpoint(), opContext);
}
else {
final StorageException ex = Utility.generateNewUnexpectedStorageException(null);
ex.getExtendedErrorInformation().setErrorMessage("Table Object relative URIs not supported.");
throw ex;
}
}
else {
return this.getEndpoint();
}
}
/**
* Reserved for internal use. Generates an iterator for a segmented query operation.
*
* @param queryRef
* The {@link TableQuery} to execute.
* @param resolver
* An {@link EntityResolver} instance which creates a projection of the table query result entities into
* the specified type R
. Pass null
to return the results as the table entity
* type.
* @param options
* A {@link TableRequestOptions} object that specifies execution options such as retry policy and timeout
* settings for the operation. Specify null
to use the request options specified on the
* {@link CloudTableClient}.
* @param opContext
* An {@link OperationContext} object for tracking the current operation. Specify null
to
* safely ignore operation context.
* @return
* An instance of Iterable
specialized for the {@link TableEntity} or {@link EntityResolver}
* type returned by the query.
*/
protected Iterable> generateIteratorForQuery(final TableQuery queryRef,
final EntityResolver resolver, TableRequestOptions options, OperationContext opContext) {
if (opContext == null) {
opContext = new OperationContext();
}
if (options == null) {
options = new TableRequestOptions();
}
opContext.initialize();
options.applyDefaults(this);
if (resolver == null) {
final SegmentedStorageOperation, ResultSegment> impl = new SegmentedStorageOperation, ResultSegment>(
options, null) {
@Override
public ResultSegment execute(final CloudTableClient client, final TableQuery queryToExecute,
final OperationContext opContext) throws Exception {
@SuppressWarnings("unchecked")
final ResultSegment result = (ResultSegment) CloudTableClient.this.executeQuerySegmentedCore(
queryToExecute, null, this.getToken(), this,
(TableRequestOptions) this.getRequestOptions(), opContext);
// Note, setting the token on the SegmentedStorageOperation is
// key, this is how the iterator will share the token across executions
if (result != null) {
this.setToken(result.getContinuationToken());
}
return result;
}
};
return new LazySegmentedIterable, T>(impl, this, queryRef,
options.getRetryPolicyFactory(), opContext);
}
else {
final SegmentedStorageOperation, ResultSegment> impl = new SegmentedStorageOperation, ResultSegment>(
options, null) {
@Override
public ResultSegment execute(final CloudTableClient client, final TableQuery queryToExecute,
final OperationContext opContext) throws Exception {
@SuppressWarnings("unchecked")
final ResultSegment result = (ResultSegment) CloudTableClient.this.executeQuerySegmentedCore(
queryToExecute, resolver, this.getToken(), this,
(TableRequestOptions) this.getRequestOptions(), opContext);
// Note, setting the token on the SegmentedStorageOperation is
// key, this is how the iterator will share the token across executions
if (result != null) {
this.setToken(result.getContinuationToken());
}
return result;
}
};
return new LazySegmentedIterable, R>(impl, this, queryRef,
options.getRetryPolicyFactory(), opContext);
}
}
}