/** * Populates the object from the XMLStreamReader * * @param xmlr the XMLStreamReader to read from * @throws XMLStreamException if there is an error parsing the stream * @throws ParseException if there is an error in parsing a date * @throws URISyntaxException if the uri is invalid */ protected static BlobContainerAttributes readBlobContainerAttributes(final XMLStreamReader xmlr) throws XMLStreamException, ParseException, URISyntaxException { int eventType = xmlr.getEventType(); final BlobContainerAttributes attributes = new BlobContainerAttributes(); while (xmlr.hasNext()) { eventType = xmlr.next(); final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT) { if (name.equals(BlobConstants.PROPERTIES)) { attributes.setProperties(BlobDeserializationHelper.readBlobContainerProperties(xmlr)); xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.PROPERTIES); } else if (name.equals(Constants.URL_ELEMENT)) { attributes.setUri(new URI(Utility.readElementFromXMLReader(xmlr, Constants.URL_ELEMENT))); } else if (name.equals(Constants.NAME_ELEMENT)) { attributes.setName(Utility.readElementFromXMLReader(xmlr, Constants.NAME_ELEMENT)); } else if (name.equals(Constants.METADATA_ELEMENT)) { // parse metadata attributes.setMetadata(DeserializationHelper.parseMetadateFromXML(xmlr)); xmlr.require(XMLStreamConstants.END_ELEMENT, null, Constants.METADATA_ELEMENT); } } else if (eventType == XMLStreamConstants.END_ELEMENT && name.equals(BlobConstants.CONTAINER_ELEMENT)) { break; } } return attributes; }
/** * Reserved for internal use. Perform a merge operation on the specified table, using the * specified {@link TableRequestOptions} and {@link OperationContext}. * * <p>This method will invoke the Merge Entity REST API to execute this table operation, using the * Table service endpoint and storage account credentials in the {@link CloudTableClient} object. * * @param client A {@link CloudTableClient} instance specifying the Table service endpoint, * storage account credentials, and any additional query parameters. * @param tableName A <code>String</code> containing the name of the table. * @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 TableResult} containing the results of executing the operation. * @throws StorageException if an error occurs in the storage operation. */ private TableResult performMerge( final CloudTableClient client, final String tableName, final TableRequestOptions options, final OperationContext opContext) throws StorageException { Utility.assertNotNullOrEmpty("Merge requires a valid ETag", this.getEntity().getEtag()); Utility.assertNotNullOrEmpty( "Merge requires a valid PartitionKey", this.getEntity().getPartitionKey()); Utility.assertNotNullOrEmpty("Merge requires a valid RowKey", this.getEntity().getRowKey()); final StorageOperation<CloudTableClient, TableOperation, TableResult> impl = new StorageOperation<CloudTableClient, TableOperation, TableResult>(options) { @Override public TableResult execute( final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { final HttpURLConnection request = TableRequest.merge( client.getTransformedEndPoint(opContext), tableName, generateRequestIdentity(false, null, false), operation.getEntity().getEtag(), options.getTimeoutIntervalInMs(), null, options, opContext); client.getCredentials().signRequestLite(request, -1L, opContext); AtomPubParser.writeSingleEntityToStream( operation.getEntity(), false, request.getOutputStream(), opContext); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND || this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { throw TableServiceException.generateTableServiceException( false, this.getResult(), operation, request.getErrorStream()); } if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NO_CONTENT) { return operation.parseResponse( null, this.getResult().getStatusCode(), request.getHeaderField(TableConstants.HeaderConstants.ETAG), opContext); } else { throw TableServiceException.generateTableServiceException( true, this.getResult(), operation, request.getErrorStream()); } } }; return ExecutionEngine.executeWithRetry( client, this, impl, options.getRetryPolicyFactory(), opContext); }
/** * Reserved for internal use. Generates the request identity, consisting of the specified entry * name, or the PartitionKey and RowKey pair from the operation, to identify the operation target. * * @param isSingleIndexEntry Pass <code>true</code> to use the specified <code>entryName</code> * parameter, or <code>false</code> to use PartitionKey and RowKey values from the operation * as the request identity. * @param entryName The entry name to use as the request identity if the <code>isSingleIndexEntry * </code> parameter is <code>true</code>. * @param encodeKeys Pass <code>true</code> to url encode the partition & row keys * @return A <code>String</code> containing the formatted request identity string. * @throws StorageException If a storage service error occurred. */ protected String generateRequestIdentity( boolean isSingleIndexEntry, final String entryName, boolean encodeKeys) throws StorageException { if (isSingleIndexEntry) { return String.format("'%s'", entryName); } if (this.opType == TableOperationType.INSERT) { return Constants.EMPTY_STRING; } else { String pk = null; String rk = null; if (this.opType == TableOperationType.RETRIEVE) { final QueryTableOperation qOp = (QueryTableOperation) this; pk = qOp.getPartitionKey(); rk = qOp.getRowKey(); } else { pk = this.getEntity().getPartitionKey(); rk = this.getEntity().getRowKey(); } return String.format( "%s='%s',%s='%s'", TableConstants.PARTITION_KEY, encodeKeys ? Utility.safeEncode(pk) : pk, TableConstants.ROW_KEY, encodeKeys ? Utility.safeEncode(rk) : rk); } }
/** * Reads PageRanges from the XMLStreamReader, reader must be at Start element of PageRangeElement * * @param xmlr the XMLStreamReader to read from * @return the PageRange from the stream. * @throws XMLStreamException if there is an error parsing the stream * @throws ParseException if there is an error in parsing a date * @throws URISyntaxException if the uri is invalid * @throws StorageException */ public static ArrayList<PageRange> readPageRanges(final XMLStreamReader xmlr) throws XMLStreamException, StorageException { int eventType = xmlr.getEventType(); final ArrayList<PageRange> retRanges = new ArrayList<PageRange>(); xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.PAGE_RANGE_ELEMENT); // check if there are more events in the input stream while (xmlr.hasNext() && BlobConstants.PAGE_RANGE_ELEMENT.equals(xmlr.getName().toString())) { long startOffset = -1; long endOffset = -1; // Read a Page Range while (xmlr.hasNext()) { eventType = xmlr.next(); final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT) { if (name.equals(BlobConstants.START_ELEMENT)) { final String sizeString = Utility.readElementFromXMLReader(xmlr, BlobConstants.START_ELEMENT); startOffset = Long.parseLong(sizeString); } else if (name.equals(Constants.END_ELEMENT)) { final String sizeString = Utility.readElementFromXMLReader(xmlr, Constants.END_ELEMENT); endOffset = Long.parseLong(sizeString); } else { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } } else if (eventType == XMLStreamConstants.END_ELEMENT) { if (startOffset == -1 || endOffset == -1) { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } final PageRange pageRef = new PageRange(startOffset, endOffset); retRanges.add(pageRef); break; } } eventType = xmlr.next(); } return retRanges; }
/** * Parses the input stream containing the response body of the list queues request result and * populates the class data. * * @param serviceClient A {@link CloudQueueClient} object associated with the storage service. * @throws XMLStreamException If the input stream cannot be read or parsed as a list queues * response. * @throws StorageException */ public void parseResponse(final CloudQueueClient serviceClient) throws XMLStreamException, StorageException { final XMLStreamReader xmlr = Utility.createXMLStreamReaderFromStream(this.streamRef); String tempParseString = null; // Start document int eventType = xmlr.getEventType(); xmlr.require(XMLStreamConstants.START_DOCUMENT, null, null); // 1. get enumerationResults Header eventType = xmlr.next(); xmlr.require(XMLStreamConstants.START_ELEMENT, null, "EnumerationResults"); // check if there are more events in the input stream while (xmlr.hasNext()) { eventType = xmlr.next(); if (eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT) { final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT && name.equals(Constants.MAX_RESULTS_ELEMENT)) { tempParseString = Utility.readElementFromXMLReader(xmlr, Constants.MAX_RESULTS_ELEMENT); this.maxResults = Integer.parseInt(tempParseString); } else if (eventType == XMLStreamConstants.START_ELEMENT && name.equals(Constants.MARKER_ELEMENT)) { this.marker = Utility.readElementFromXMLReader(xmlr, Constants.MARKER_ELEMENT); } else if (eventType == XMLStreamConstants.START_ELEMENT && name.equals(Constants.NEXT_MARKER_ELEMENT)) { this.nextMarker = Utility.readElementFromXMLReader(xmlr, Constants.NEXT_MARKER_ELEMENT); } else if (eventType == XMLStreamConstants.START_ELEMENT && name.equals(Constants.PREFIX_ELEMENT)) { this.prefix = Utility.readElementFromXMLReader(xmlr, Constants.PREFIX_ELEMENT); } else if (eventType == XMLStreamConstants.START_ELEMENT && name.equals(QueueConstants.QUEUES_ELEMENT)) { try { this.queues = QueueDeserializationHelper.readQueues(xmlr, serviceClient); } catch (final URISyntaxException e) { throw new XMLStreamException(e); } catch (final ParseException e) { throw new XMLStreamException(e); } xmlr.require(XMLStreamConstants.END_ELEMENT, null, QueueConstants.QUEUES_ELEMENT); // eventType = xmlr.next(); } else if (eventType == XMLStreamConstants.END_ELEMENT && "EnumerationResults".equals(name)) { break; } } } this.isParsed = true; }
/** * Reserved for internal use. Execute this table operation on the specified table, using the * specified {@link TableRequestOptions} and {@link OperationContext}. * * <p>This method will invoke the Storage Service REST API to execute this table operation, using * the Table service endpoint and storage account credentials in the {@link CloudTableClient} * object. * * @param client A {@link CloudTableClient} instance specifying the Table service endpoint, * storage account credentials, and any additional query parameters. * @param tableName A <code>String</code> containing the name of the table. * @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 TableResult} containing the results of executing the operation. * @throws StorageException if an error occurs in the storage operation. */ protected TableResult execute( final CloudTableClient client, final String tableName, TableRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new TableRequestOptions(); } opContext.initialize(); options.applyDefaults(client); Utility.assertNotNullOrEmpty("TableName", tableName); if (this.getOperationType() == TableOperationType.INSERT || this.getOperationType() == TableOperationType.INSERT_OR_MERGE || this.getOperationType() == TableOperationType.INSERT_OR_REPLACE) { return this.performInsert(client, tableName, options, opContext); } else if (this.getOperationType() == TableOperationType.DELETE) { return this.performDelete(client, tableName, options, opContext); } else if (this.getOperationType() == TableOperationType.MERGE) { return this.performMerge(client, tableName, options, opContext); } else if (this.getOperationType() == TableOperationType.REPLACE) { return this.performUpdate(client, tableName, options, opContext); } else if (this.getOperationType() == TableOperationType.RETRIEVE) { return ((QueryTableOperation) this).performRetrieve(client, tableName, options, opContext); } else { throw new IllegalArgumentException("Unknown table operation"); } }
/** * Reads BlobItems from the XMLStreamReader, reader must be at Start element of BlobsElement * * @param xmlr the XMLStreamReader to read from * @param searchMode the block search mode * @return BlockEntry from the stream. * @throws XMLStreamException if there is an error parsing the stream * @throws ParseException if there is an error in parsing a date * @throws URISyntaxException if the uri is invalid * @throws StorageException */ public static ArrayList<BlockEntry> readBlobBlocks( final XMLStreamReader xmlr, final BlockSearchMode searchMode) throws XMLStreamException, StorageException { int eventType = xmlr.getEventType(); final ArrayList<BlockEntry> retBlocks = new ArrayList<BlockEntry>(); xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.BLOCK_ELEMENT); // check if there are more events in the input stream while (xmlr.hasNext() && BlobConstants.BLOCK_ELEMENT.equals(xmlr.getName().toString())) { String blockName = null; long blockSize = -1; // Read a block while (xmlr.hasNext()) { eventType = xmlr.next(); final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT) { if (name.equals(Constants.NAME_ELEMENT)) { blockName = Utility.readElementFromXMLReader(xmlr, Constants.NAME_ELEMENT); } else if (name.equals(BlobConstants.SIZE_ELEMENT)) { final String sizeString = Utility.readElementFromXMLReader(xmlr, BlobConstants.SIZE_ELEMENT); blockSize = Long.parseLong(sizeString); } else { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } } else if (eventType == XMLStreamConstants.END_ELEMENT) { final BlockEntry newBlock = new BlockEntry(blockName, searchMode); newBlock.setSize(blockSize); retBlocks.add(newBlock); break; } } eventType = xmlr.next(); } return retBlocks; }
/** * Uploads a new configuration of service properties to the storage service, using the specified * request options and operation context. This includes Metrics and Logging Configuration. * * @param properties The {@link ServiceProperties} to upload. * @param options A {@link RequestOptions} object that specifies any additional options for the * request. Specifying <code>null</code> will use the default request options from the * associated service client ( {@link CloudBlobClient}{@link CloudQueueClient}). * @param opContext An {@link OperationContext} object that represents the context for the current * operation. This object is used to track requests to the storage service, and to provide * additional runtime information about the operation. * @throws StorageException If a storage service error occurred during the operation. */ @DoesServiceRequest @Override public void uploadServiceProperties( final ServiceProperties properties, final RequestOptions options, final OperationContext opContext) throws StorageException { if (!Utility.isNullOrEmpty(properties.getDefaultServiceVersion())) { throw new IllegalArgumentException( "DefaultServiceVersion can only be set for the Blob service and the request must be made using the 2011-08-18 version"); } super.uploadServiceProperties(properties, options, opContext); }
/** * Gets a result segment containing a collection of queues from the storage service with the * specified parameters. * * @param prefix A <code>String</code> containing the queue name prefix to filter the results * with. * @param detailsIncluded A {@link QueueListingDetails} value that indicates whether queue * metadata will be returned. * @param maxResults The maximum number of queue results to retrieve. * @param continuationToken A {@link ResultContinuation} object that represents a continuation * token returned by a previous listing operation. * @param options A {@link QueueRequestOptions} object that specifies any additional options for * the request. Specifying <code>null</code> will use the default request options from the * associated service client ( {@link CloudQueue}). * @param taskReference A {@link StorageOperation} reference to the encapsulating task. * @param opContext An {@link OperationContext} object that represents the context for the current * operation. This object is used to track requests to the storage service, and to provide * additional runtime information about the operation. * @return A {@link ResultSegment} of {@link CloudQueue} objects that contains a segment of the * iterable collection of {@link CloudQueue} objects that represent the requested queues in * the storage service. * @throws IOException * @throws URISyntaxException If the URI is not valid. * @throws XMLStreamException * @throws InvalidKeyException * @throws StorageException If a storage service error occurred during the operation. */ @DoesServiceRequest ResultSegment<CloudQueue> listQueuesCore( final String prefix, final QueueListingDetails detailsIncluded, final int maxResults, final ResultContinuation continuationToken, final RequestOptions options, final StorageOperation<CloudQueueClient, Void, ResultSegment<CloudQueue>> taskReference, final OperationContext opContext) throws IOException, URISyntaxException, XMLStreamException, InvalidKeyException, StorageException { Utility.assertContinuationType(continuationToken, ResultContinuationType.QUEUE); final ListingContext listingContext = new ListingContext(prefix, maxResults); listingContext.setMarker(continuationToken != null ? continuationToken.getNextMarker() : null); final HttpURLConnection listQueueRequest = QueueRequest.list( this.getEndpoint(), options.getTimeoutIntervalInMs(), listingContext, detailsIncluded, opContext); this.getCredentials().signRequest(listQueueRequest, -1L); taskReference.setResult(ExecutionEngine.processRequest(listQueueRequest, opContext)); if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { taskReference.setNonExceptionedRetryableFailure(true); return null; } final ListQueuesResponse response = new ListQueuesResponse(listQueueRequest.getInputStream()); response.parseResponse(this); ResultContinuation newToken = null; if (response.getNextMarker() != null) { newToken = new ResultContinuation(); newToken.setNextMarker(response.getNextMarker()); newToken.setContinuationType(ResultContinuationType.QUEUE); } final ResultSegment<CloudQueue> resSegment = new ResultSegment<CloudQueue>(response.getQueues(this), maxResults, newToken); return resSegment; }
/** * Populates the CloudBlobDirectory from an XMLStreamReader, reader must be at Start element of * BlobPrefix * * @param xmlr the XMLStreamReader to read from * @param serviceClient the CloudBlobClient associated with the objects. * @param container the container associated with the objects. * @return a CloudBlobDirectory parsed from the stream. * @throws XMLStreamException if there is an error parsing the stream * @throws ParseException if there is an error in parsing a date * @throws URISyntaxException if the uri is invalid * @throws StorageException */ protected static CloudBlobDirectory readDirectory( final XMLStreamReader xmlr, final CloudBlobClient serviceClient, final CloudBlobContainer container) throws XMLStreamException, ParseException, URISyntaxException, StorageException { xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.BLOB_PREFIX_ELEMENT); // Move to Name element xmlr.next(); xmlr.require(XMLStreamConstants.START_ELEMENT, null, Constants.NAME_ELEMENT); final String prefixName = Utility.readElementFromXMLReader(xmlr, Constants.NAME_ELEMENT); // Move from End name element to end prefix element xmlr.next(); xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.BLOB_PREFIX_ELEMENT); return container.getDirectoryReference(prefixName); }
/** * Gets a result segment of an iterable collection of queues whose names begin with the specified * prefix for this queue, using the specified listing details options, request options, and * operation context. * * @param prefix A <code>String</code> that represents the prefix of the queue name to match. * @param detailsIncluded A {@link QueueListingDetails} value that indicates whether queue * metadata will be returned. * @param maxResults The maximum number of queue results to retrieve. * @param continuationToken A {@link ResultContinuation} object that represents a continuation * token returned by a previous listing operation. * @param options A {@link QueueRequestOptions} object that specifies any additional options for * the request. Specifying <code>null</code> will use the default request options from the * associated service client ( {@link CloudQueue}). * @param opContext An {@link OperationContext} object that represents the context for the current * operation. This object is used to track requests to the storage service, and to provide * additional runtime information about the operation. * @return A {@link ResultSegment} of {@link CloudQueue} objects that contains a segment of the * iterable collection of {@link CloudQueue} objects that represent the requested queues in * the storage service. * @throws StorageException If a storage service error occurred during the operation. */ @DoesServiceRequest public ResultSegment<CloudQueue> listQueuesSegmented( final String prefix, final QueueListingDetails detailsIncluded, final int maxResults, final ResultContinuation continuationToken, QueueRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new QueueRequestOptions(); } opContext.initialize(); options.applyDefaults(this); Utility.assertContinuationType(continuationToken, ResultContinuationType.QUEUE); final StorageOperation<CloudQueueClient, Void, ResultSegment<CloudQueue>> impl = new StorageOperation<CloudQueueClient, Void, ResultSegment<CloudQueue>>(options) { @Override public ResultSegment<CloudQueue> execute( final CloudQueueClient client, final Void dontCare, final OperationContext opContext) throws Exception { return CloudQueueClient.this.listQueuesCore( prefix, detailsIncluded, maxResults, continuationToken, this.getRequestOptions(), this, opContext); } }; return ExecutionEngine.executeWithRetry( this, null, impl, options.getRetryPolicyFactory(), opContext); }
/** * Writes a Block List and returns the corresponding UTF8 bytes. * * @param blockList the Iterable of BlockEntry to write * @param opContext a tracking object for the request * @return a byte array of the UTF8 bytes representing the serialized block list. * @throws XMLStreamException if there is an error writing the block list. * @throws StorageException */ public static byte[] writeBlockListToStream( final Iterable<BlockEntry> blockList, final OperationContext opContext) throws XMLStreamException, StorageException { final StringWriter outWriter = new StringWriter(); final XMLOutputFactory xmlOutFactoryInst = XMLOutputFactory.newInstance(); final XMLStreamWriter xmlw = xmlOutFactoryInst.createXMLStreamWriter(outWriter); // default is UTF8 xmlw.writeStartDocument(); xmlw.writeStartElement(BlobConstants.BLOCK_LIST_ELEMENT); for (final BlockEntry block : blockList) { if (block.searchMode == BlockSearchMode.COMMITTED) { xmlw.writeStartElement(BlobConstants.COMMITTED_ELEMENT); } else if (block.searchMode == BlockSearchMode.UNCOMMITTED) { xmlw.writeStartElement(BlobConstants.UNCOMMITTED_ELEMENT); } else if (block.searchMode == BlockSearchMode.LATEST) { xmlw.writeStartElement(BlobConstants.LATEST_ELEMENT); } xmlw.writeCharacters(block.getId()); xmlw.writeEndElement(); } // end BlockListElement xmlw.writeEndElement(); // end doc xmlw.writeEndDocument(); try { return outWriter.toString().getBytes("UTF8"); } catch (final UnsupportedEncodingException e) { throw Utility.generateNewUnexpectedStorageException(e); } }
/** * Populates the object from the XMLStreamReader, reader must be at Start element of Properties * * @param xmlr the XMLStreamReader object * @throws XMLStreamException if there is a parsing exception * @throws ParseException if a date value is not correctly encoded */ protected static BlobContainerProperties readBlobContainerProperties(final XMLStreamReader xmlr) throws XMLStreamException, ParseException { xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.PROPERTIES); int eventType = xmlr.getEventType(); final BlobContainerProperties properties = new BlobContainerProperties(); while (xmlr.hasNext()) { eventType = xmlr.next(); final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT) { if (name.equals(Constants.LAST_MODIFIED_ELEMENT)) { properties.setLastModified( Utility.parseRFC1123DateFromStringInGMT( Utility.readElementFromXMLReader(xmlr, Constants.LAST_MODIFIED_ELEMENT))); } else if (name.equals(Constants.ETAG_ELEMENT)) { properties.setEtag(Utility.readElementFromXMLReader(xmlr, Constants.ETAG_ELEMENT)); } else if (name.equals(Constants.LEASE_STATUS_ELEMENT)) { properties.setLeaseStatus( LeaseStatus.parse( Utility.readElementFromXMLReader(xmlr, Constants.LEASE_STATUS_ELEMENT))); } else if (name.equals(Constants.LEASE_STATE_ELEMENT)) { properties.setLeaseState( LeaseState.parse( Utility.readElementFromXMLReader(xmlr, Constants.LEASE_STATE_ELEMENT))); } else if (name.equals(Constants.LEASE_DURATION_ELEMENT)) { properties.setLeaseDuration( LeaseDuration.parse( Utility.readElementFromXMLReader(xmlr, Constants.LEASE_DURATION_ELEMENT))); } } else { // expect end of properties xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.PROPERTIES); break; } } return properties; }
/** * A static factory method returning a {@link TableOperation} instance to replace the specified * entity in Windows Azure storage, or insert it if it does not exist. To execute this {@link * TableOperation} on a given table, call the {@link CloudTableClient#execute(String, * TableOperation)} method on a {@link CloudTableClient} instance with the table name and the * {@link TableOperation} as arguments. * * @param entity The object instance implementing {@link TableEntity} to associate with the * operation. * @return A new {@link TableOperation} instance for inserting or replacing the table entity. */ public static TableOperation insertOrReplace(final TableEntity entity) { Utility.assertNotNull("Entity", entity); return new TableOperation(entity, TableOperationType.INSERT_OR_REPLACE); }
/** * A static factory method returning a {@link TableOperation} instance to merge the specified * entity into Windows Azure storage, or insert it if it does not exist. To execute this {@link * TableOperation} on a given table, call the {@link CloudTableClient#execute(String, * TableOperation)} method on a {@link CloudTableClient} instance with the table name and the * {@link TableOperation} as arguments. * * @param entity The object instance implementing {@link TableEntity} to associate with the * operation. * @return A new {@link TableOperation} instance for inserting or merging the table entity. */ public static TableOperation insertOrMerge(final TableEntity entity) { Utility.assertNotNull("Entity", entity); return new TableOperation(entity, TableOperationType.INSERT_OR_MERGE); }
/** * A static factory method returning a {@link TableOperation} instance to delete the specified * entity from Windows Azure storage. To execute this {@link TableOperation} on a given table, * call the {@link CloudTableClient#execute(String, TableOperation)} method on a {@link * CloudTableClient} instance with the table name and the {@link TableOperation} as arguments. * * @param entity The object instance implementing {@link TableEntity} to associate with the * operation. * @return A new {@link TableOperation} instance to insert the table entity. */ public static TableOperation delete(final TableEntity entity) { Utility.assertNotNull("Entity", entity); Utility.assertNotNullOrEmpty("Entity Etag", entity.getEtag()); return new TableOperation(entity, TableOperationType.DELETE); }
/** * Reserved for internal use. Performs an insert operation on the specified table, using the * specified {@link TableRequestOptions} and {@link OperationContext}. * * <p>This method will invoke the Insert Entity REST API to execute this table operation, using * the Table service endpoint and storage account credentials in the {@link CloudTableClient} * object. * * @param client A {@link CloudTableClient} instance specifying the Table service endpoint, * storage account credentials, and any additional query parameters. * @param tableName A <code>String</code> containing the name of the table. * @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 TableResult} containing the results of executing the operation. * @throws StorageException if an error occurs in the storage operation. */ private TableResult performInsert( final CloudTableClient client, final String tableName, final TableRequestOptions options, final OperationContext opContext) throws StorageException { final boolean isTableEntry = TableConstants.TABLES_SERVICE_TABLES_NAME.equals(tableName); final String tableIdentity = isTableEntry ? this.getEntity() .writeEntity(opContext) .get(TableConstants.TABLE_NAME) .getValueAsString() : null; // Upserts need row key and partition key if (!isTableEntry && this.opType != TableOperationType.INSERT) { Utility.assertNotNullOrEmpty( "Upserts require a valid PartitionKey", this.getEntity().getPartitionKey()); Utility.assertNotNullOrEmpty("Upserts require a valid RowKey", this.getEntity().getRowKey()); } final StorageOperation<CloudTableClient, TableOperation, TableResult> impl = new StorageOperation<CloudTableClient, TableOperation, TableResult>(options) { @Override public TableResult execute( final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { final HttpURLConnection request = TableRequest.insert( client.getTransformedEndPoint(opContext), tableName, generateRequestIdentity(isTableEntry, tableIdentity, false), operation.opType != TableOperationType.INSERT ? operation.getEntity().getEtag() : null, operation.opType.getUpdateType(), options.getTimeoutIntervalInMs(), null, options, opContext); client.getCredentials().signRequestLite(request, -1L, opContext); AtomPubParser.writeSingleEntityToStream( operation.getEntity(), isTableEntry, request.getOutputStream(), opContext); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (operation.opType == TableOperationType.INSERT) { if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { throw TableServiceException.generateTableServiceException( false, this.getResult(), operation, request.getErrorStream()); } if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { throw TableServiceException.generateTableServiceException( true, this.getResult(), operation, request.getErrorStream()); } InputStream inStream = request.getInputStream(); TableResult res = null; try { final XMLStreamReader xmlr = Utility.createXMLStreamReaderFromStream(inStream); res = operation.parseResponse( xmlr, this.getResult().getStatusCode(), null, opContext); } finally { inStream.close(); } return res; } else { if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NO_CONTENT) { return operation.parseResponse( null, this.getResult().getStatusCode(), request.getHeaderField(TableConstants.HeaderConstants.ETAG), opContext); } else { throw TableServiceException.generateTableServiceException( true, this.getResult(), operation, request.getErrorStream()); } } } }; return ExecutionEngine.executeWithRetry( client, this, impl, options.getRetryPolicyFactory(), opContext); }
/** * Populates the object from the XMLStreamReader, reader must be at Start element of Properties * * @param xmlr the XMLStreamReader object * @return the BlobProperties that was read. * @throws XMLStreamException if there is a parsing exception * @throws ParseException if a date value is not correctly encoded * @throws StorageException * @throws URISyntaxException */ protected static BlobProperties readBlobProperties(final XMLStreamReader xmlr) throws XMLStreamException, ParseException, StorageException, URISyntaxException { xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.PROPERTIES); int eventType = xmlr.getEventType(); final BlobProperties properties = new BlobProperties(); while (xmlr.hasNext()) { eventType = xmlr.next(); final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT) { if (name.equals(Constants.LAST_MODIFIED_ELEMENT)) { properties.setLastModified( Utility.parseRFC1123DateFromStringInGMT( Utility.readElementFromXMLReader(xmlr, Constants.LAST_MODIFIED_ELEMENT))); } else if (name.equals(Constants.ETAG_ELEMENT)) { properties.setEtag(Utility.readElementFromXMLReader(xmlr, Constants.ETAG_ELEMENT)); } else if (name.equals(Constants.HeaderConstants.CONTENT_LENGTH)) { final String tempString = Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CONTENT_LENGTH); properties.setLength(Long.parseLong(tempString)); } else if (name.equals(Constants.HeaderConstants.CONTENT_TYPE)) { properties.setContentType( Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CONTENT_TYPE)); } else if (name.equals(Constants.HeaderConstants.CONTENT_ENCODING)) { properties.setContentEncoding( Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CONTENT_ENCODING)); } else if (name.equals(Constants.HeaderConstants.CONTENT_LANGUAGE)) { properties.setContentLanguage( Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CONTENT_LANGUAGE)); } else if (name.equals(Constants.HeaderConstants.CONTENT_MD5)) { properties.setContentMD5( Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CONTENT_MD5)); } else if (name.equals(Constants.HeaderConstants.CACHE_CONTROL)) { properties.setCacheControl( Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CACHE_CONTROL)); } else if (name.equals(Constants.HeaderConstants.CACHE_CONTROL)) { properties.setCacheControl( Utility.readElementFromXMLReader(xmlr, Constants.HeaderConstants.CACHE_CONTROL)); } else if (name.equals(BlobConstants.SEQUENCE_NUMBER)) { Utility.readElementFromXMLReader(xmlr, BlobConstants.SEQUENCE_NUMBER); } else if (name.equals(BlobConstants.BLOB_TYPE_ELEMENT)) { final String tempString = Utility.readElementFromXMLReader(xmlr, BlobConstants.BLOB_TYPE_ELEMENT); if (tempString.equals(BlobConstants.BLOCK_BLOB_VALUE)) { properties.setBlobType(BlobType.BLOCK_BLOB); } else if (tempString.equals(BlobConstants.PAGE_BLOB_VALUE)) { properties.setBlobType(BlobType.PAGE_BLOB); } else { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } } else if (name.equals(Constants.LEASE_STATUS_ELEMENT)) { final String tempString = Utility.readElementFromXMLReader(xmlr, Constants.LEASE_STATUS_ELEMENT); if (tempString.equals(Constants.LOCKED_VALUE.toLowerCase())) { properties.setLeaseStatus(LeaseStatus.LOCKED); } else if (tempString.equals(Constants.UNLOCKED_VALUE.toLowerCase())) { properties.setLeaseStatus(LeaseStatus.UNLOCKED); } else { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } } else if (name.equals(Constants.LEASE_STATE_ELEMENT)) { properties.setLeaseState( LeaseState.parse( Utility.readElementFromXMLReader(xmlr, Constants.LEASE_STATE_ELEMENT))); } else if (name.equals(Constants.LEASE_DURATION_ELEMENT)) { properties.setLeaseDuration( LeaseDuration.parse( Utility.readElementFromXMLReader(xmlr, Constants.LEASE_DURATION_ELEMENT))); } } else if (eventType == XMLStreamConstants.END_ELEMENT) { // expect end of properties xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.PROPERTIES); break; } } return properties; }
/** * Reserved for internal use. Performs a delete operation on the specified table, using the * specified {@link TableRequestOptions} and {@link OperationContext}. * * <p>This method will invoke the <a * href="http://msdn.microsoft.com/en-us/library/windowsazure/dd135727.aspx">Delete Entity</a> * REST API to execute this table operation, using the Table service endpoint and storage account * credentials in the {@link CloudTableClient} object. * * @param client A {@link CloudTableClient} instance specifying the Table service endpoint, * storage account credentials, and any additional query parameters. * @param tableName A <code>String</code> containing the name of the table. * @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 TableResult} containing the results of executing the operation. * @throws StorageException if an error occurs in the storage operation. */ private TableResult performDelete( final CloudTableClient client, final String tableName, final TableRequestOptions options, final OperationContext opContext) throws StorageException { final boolean isTableEntry = TableConstants.TABLES_SERVICE_TABLES_NAME.equals(tableName); final String tableIdentity = isTableEntry ? this.getEntity() .writeEntity(opContext) .get(TableConstants.TABLE_NAME) .getValueAsString() : null; if (!isTableEntry) { Utility.assertNotNullOrEmpty("Delete requires a valid ETag", this.getEntity().getEtag()); Utility.assertNotNullOrEmpty( "Delete requires a valid PartitionKey", this.getEntity().getPartitionKey()); Utility.assertNotNullOrEmpty("Delete requires a valid RowKey", this.getEntity().getRowKey()); } final StorageOperation<CloudTableClient, TableOperation, TableResult> impl = new StorageOperation<CloudTableClient, TableOperation, TableResult>(options) { @Override public TableResult execute( final CloudTableClient client, final TableOperation operation, final OperationContext opContext) throws Exception { final HttpURLConnection request = TableRequest.delete( client.getTransformedEndPoint(opContext), tableName, generateRequestIdentity(isTableEntry, tableIdentity, false), operation.getEntity().getEtag(), options.getTimeoutIntervalInMs(), null, options, opContext); client.getCredentials().signRequestLite(request, -1L, opContext); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND || this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { throw TableServiceException.generateTableServiceException( false, this.getResult(), operation, request.getErrorStream()); } if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_NO_CONTENT) { throw TableServiceException.generateTableServiceException( true, this.getResult(), operation, request.getErrorStream()); } return operation.parseResponse(null, this.getResult().getStatusCode(), null, opContext); } }; return ExecutionEngine.executeWithRetry( client, this, impl, options.getRetryPolicyFactory(), opContext); }
/** * A static factory method returning a {@link TableOperation} instance to replace the specified * table entity. To execute this {@link TableOperation} on a given table, call the {@link * CloudTableClient#execute(String, TableOperation)} method on a {@link CloudTableClient} instance * with the table name and the {@link TableOperation} as arguments. * * @param entity The object instance implementing {@link TableEntity} to associate with the * operation. * @return A new {@link TableOperation} instance for replacing the table entity. */ public static TableOperation replace(final TableEntity entity) { Utility.assertNotNullOrEmpty("Entity Etag", entity.getEtag()); return new TableOperation(entity, TableOperationType.REPLACE); }
/** * Gets a {@link CloudQueue} object that represents the storage service queue for the specified * address. * * @param queueAddress A <code>String</code> that represents the name of the queue, or the * absolute URI to the queue. * @return A {@link CloudQueue} object that represents a reference to the queue. * @throws URISyntaxException If the resource URI is invalid. * @throws StorageException If a storage service error occurred during the operation. */ public CloudQueue getQueueReference(final String queueAddress) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("queueAddress", queueAddress); return new CloudQueue(queueAddress, this); }
/** * Reserved for internal use. Populates the blob from an XMLStreamReader, reader must be at Start * element of Blob * * @param xmlr the XMLStreamReader to read from * @param serviceClient the CloudBlobClient associated with the objects. * @throws XMLStreamException if there is an error parsing the stream * @throws ParseException if there is an error in parsing a date * @throws URISyntaxException if the uri is invalid * @throws StorageException */ protected static CloudBlob readBlob( final XMLStreamReader xmlr, final CloudBlobClient serviceClient, final CloudBlobContainer container) throws XMLStreamException, ParseException, URISyntaxException, StorageException { xmlr.require(XMLStreamConstants.START_ELEMENT, null, BlobConstants.BLOB_ELEMENT); String blobName = Constants.EMPTY_STRING; String snapshotID = null; String urlString = null; HashMap<String, String> metadata = null; BlobProperties properties = null; CopyState copyState = null; int eventType = xmlr.getEventType(); // check if there are more events in the input stream while (xmlr.hasNext()) { eventType = xmlr.next(); final String name = xmlr.getName().toString(); if (eventType == XMLStreamConstants.START_ELEMENT) { if (name.equals(Constants.URL_ELEMENT)) { urlString = Utility.readElementFromXMLReader(xmlr, Constants.URL_ELEMENT); } else if (name.equals(BlobConstants.SNAPSHOT_ELEMENT)) { snapshotID = Utility.readElementFromXMLReader(xmlr, BlobConstants.SNAPSHOT_ELEMENT); } else if (name.equals(Constants.NAME_ELEMENT)) { blobName = Utility.readElementFromXMLReader(xmlr, Constants.NAME_ELEMENT); } else if (name.equals(BlobConstants.PROPERTIES)) { properties = BlobDeserializationHelper.readBlobProperties(xmlr); xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.PROPERTIES); } else if (name.equals(Constants.METADATA_ELEMENT)) { metadata = DeserializationHelper.parseMetadateFromXML(xmlr); xmlr.require(XMLStreamConstants.END_ELEMENT, null, Constants.METADATA_ELEMENT); } else if (name.equals(Constants.COPY_ID_ELEMENT)) { if (copyState == null) { copyState = new CopyState(); } copyState.setCopyId(Utility.readElementFromXMLReader(xmlr, Constants.COPY_ID_ELEMENT)); } else if (name.equals(Constants.COPY_COMPLETION_TIME_ELEMENT)) { if (copyState == null) { copyState = new CopyState(); } copyState.setCompletionTime( Utility.parseRFC1123DateFromStringInGMT( Utility.readElementFromXMLReader(xmlr, Constants.COPY_COMPLETION_TIME_ELEMENT))); } else if (name.equals(Constants.COPY_STATUS_ELEMENT)) { if (copyState == null) { copyState = new CopyState(); } copyState.setStatus( CopyStatus.parse( Utility.readElementFromXMLReader(xmlr, Constants.COPY_STATUS_ELEMENT))); } else if (name.equals(Constants.COPY_SOURCE_ELEMENT)) { if (copyState == null) { copyState = new CopyState(); } copyState.setSource( new URI(Utility.readElementFromXMLReader(xmlr, Constants.COPY_SOURCE_ELEMENT))); } else if (name.equals(Constants.COPY_PROGRESS_ELEMENT)) { if (copyState == null) { copyState = new CopyState(); } final String tempString = Utility.readElementFromXMLReader(xmlr, Constants.COPY_PROGRESS_ELEMENT); String[] progressSequence = tempString.split("/"); copyState.setBytesCopied(Long.parseLong(progressSequence[0])); copyState.setTotalBytes(Long.parseLong(progressSequence[1])); } else if (name.equals(Constants.COPY_STATUS_DESCRIPTION_ELEMENT)) { if (copyState == null) { copyState = new CopyState(); } copyState.setStatusDescription( Utility.readElementFromXMLReader(xmlr, Constants.COPY_STATUS_DESCRIPTION_ELEMENT)); } } else if (eventType == XMLStreamConstants.END_ELEMENT && name.equals(BlobConstants.BLOB_ELEMENT)) { break; } } xmlr.require(XMLStreamConstants.END_ELEMENT, null, BlobConstants.BLOB_ELEMENT); // Assemble and return if (properties != null) { CloudBlob retBlob = null; final int blobNameSectionIndex = urlString.lastIndexOf("/".concat(blobName)); final URI baseUri = new URI(urlString.substring(0, blobNameSectionIndex + 1)); String query = null; if (blobNameSectionIndex + 1 + blobName.length() < urlString.length()) { // Snapshot blob URI // example:http://<yourstorageaccount>.blob.core.windows.net/<yourcontainer>/<yourblobname>?snapshot=2009-12-03T15%3a26%3a19.4466877Z query = urlString.substring(blobNameSectionIndex + 1 + blobName.length() + 1); } final URI blobURI = new URI( baseUri.getScheme(), baseUri.getAuthority(), baseUri.getRawPath().concat(blobName), query, null); if (properties.getBlobType() == BlobType.BLOCK_BLOB) { retBlob = new CloudBlockBlob(blobURI, serviceClient, container); } else if (properties.getBlobType() == BlobType.PAGE_BLOB) { retBlob = new CloudPageBlob(blobURI, serviceClient, container); } else { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } retBlob.uri = blobURI; retBlob.snapshotID = snapshotID; retBlob.properties = properties; retBlob.metadata = metadata; retBlob.copyState = copyState; return retBlob; } else { throw new StorageException( StorageErrorCodeStrings.INVALID_XML_DOCUMENT, "The response received is invalid or improperly formatted.", Constants.HeaderConstants.HTTP_UNUSED_306, null, null); } }
/** * Constructs a HttpURLConnection to list blobs. Sign with no length specified. * * @param uri The absolute URI to the blob * @param timeout The server timeout interval * @param listingContext A set of parameters for the listing operation. * @param blobOptions the options to use for the request. * @param opContext a tracking object for the request * @return a HttpURLConnection configured for the operation. * @throws IOException if there is an error opening the connection * @throws URISyntaxException if the resource URI is invalid * @throws StorageException an exception representing any error which occurred during the * operation. * @throws IllegalArgumentException */ public static HttpURLConnection list( final URI uri, final int timeout, final BlobListingContext listingContext, final BlobRequestOptions blobOptions, final OperationContext opContext) throws URISyntaxException, IOException, StorageException { final UriQueryBuilder builder = ContainerRequest.getContainerUriQueryBuilder(); builder.add("comp", "list"); if (listingContext != null) { if (!Utility.isNullOrEmpty(listingContext.getPrefix())) { builder.add("prefix", listingContext.getPrefix()); } if (!Utility.isNullOrEmpty(listingContext.getDelimiter())) { builder.add("delimiter", listingContext.getDelimiter()); } if (!Utility.isNullOrEmpty(listingContext.getMarker())) { builder.add("marker", listingContext.getMarker()); } if (listingContext.getMaxResults() != null && listingContext.getMaxResults() > 0) { builder.add("maxresults", listingContext.getMaxResults().toString()); } if (listingContext.getListingDetails().size() > 0) { final StringBuilder sb = new StringBuilder(); boolean started = false; if (listingContext.getListingDetails().contains(BlobListingDetails.SNAPSHOTS)) { if (!started) { started = true; } else { sb.append(","); } sb.append("snapshots"); } if (listingContext.getListingDetails().contains(BlobListingDetails.UNCOMMITTED_BLOBS)) { if (!started) { started = true; } else { sb.append(","); } sb.append("uncommittedblobs"); } if (listingContext.getListingDetails().contains(BlobListingDetails.METADATA)) { if (!started) { started = true; } else { sb.append(","); } sb.append("metadata"); } builder.add("include", sb.toString()); } } final HttpURLConnection request = BlobRequest.createURLConnection(uri, timeout, builder, blobOptions, opContext); request.setRequestMethod("GET"); return request; }