/** * 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.azure.storage.analytics; import java.io.IOException; import java.net.URISyntaxException; import java.text.ParseException; import java.util.Iterator; import java.util.NoSuchElementException; import com.microsoft.azure.storage.StorageException; import com.microsoft.azure.storage.blob.CloudBlockBlob; import com.microsoft.azure.storage.blob.ListBlobItem; import com.microsoft.azure.storage.core.SR; /** * RESERVED FOR INTERNAL USE. Provides an overlay on the LogBlobIterator class for enumerating Storage Analytics * log records. This handles the logic for the listLogRecords() methods found in the * <code>CloudAnalyticsClient<code> class. */ class LogRecordIterator implements Iterator<LogRecord> { /** * Holds the iterator from which we get log blobs. */ private final Iterator<ListBlobItem> logBlobIterator; /** * Holds the StreamReader for the current blob. */ private LogRecordStreamReader reader; /** * Holds the current LogRecord. */ private LogRecord pendingLogRecord; /** * Flag to indicate whether there's a current record pending. */ private boolean isLogRecordPending = false; /** * Constructs a new iterator using an underlying LogBlobIterator. * * @param logBlobIterator * @throws StorageException */ public LogRecordIterator(final Iterator<ListBlobItem> logBlobIterator) { this.logBlobIterator = logBlobIterator; } @Override public boolean hasNext() { if (this.isLogRecordPending) { // Already have a log record cached. return true; } try { if (this.reader == null || this.reader.isEndOfFile()) { // This reader is not usable if (this.logBlobIterator.hasNext()) { // Valid $logs blobs still pending if (this.reader != null) { // If this isn't our first time, clean up the previous reader. this.reader.close(); } CloudBlockBlob nextBlob = (CloudBlockBlob) this.logBlobIterator.next(); this.reader = new LogRecordStreamReader(nextBlob.openInputStream()); return this.hasNext(); } else { // We are out of $logs blobs altogether. return false; } } else { // We still have log records in this $logs blob's reader. this.pendingLogRecord = new LogRecord(this.reader); this.isLogRecordPending = true; return true; } } catch (IOException e) { final NoSuchElementException ex = new NoSuchElementException(SR.ENUMERATION_ERROR); ex.initCause(e); throw ex; } catch (StorageException e) { final NoSuchElementException ex = new NoSuchElementException(SR.ENUMERATION_ERROR); ex.initCause(e); throw ex; } catch (ParseException e) { final NoSuchElementException ex = new NoSuchElementException(SR.ENUMERATION_ERROR); ex.initCause(e); throw ex; } catch (URISyntaxException e) { final NoSuchElementException ex = new NoSuchElementException(SR.ENUMERATION_ERROR); ex.initCause(e); throw ex; } } @Override public LogRecord next() { if (this.isLogRecordPending) { // Log record already cached. this.isLogRecordPending = false; return this.pendingLogRecord; } if (this.hasNext()) { // Cache the next log record and try again. return this.next(); } else { throw new NoSuchElementException(SR.ITERATOR_EMPTY); } } @Override public void remove() { // Remove not supported. throw new UnsupportedOperationException(); } }