| /* |
| * Copyright (c) 2015 Eike Stepper (Berlin, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.userstorage; |
| |
| import org.eclipse.userstorage.spi.StorageCache; |
| import org.eclipse.userstorage.util.ConflictException; |
| import org.eclipse.userstorage.util.NoServiceException; |
| import org.eclipse.userstorage.util.NotFoundException; |
| import org.eclipse.userstorage.util.ProtocolException; |
| |
| import java.io.DataInput; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Map; |
| |
| /** |
| * Represents a piece of data that a {@link #getStorage() storage} |
| * maintains for the logged-in user under the associated {@link #getKey() key}. |
| * <p> |
| * The actual data can be read from the {@link InputStream} returned by the {@link #getContents() getContents()} method. |
| * It can be written by passing an {@link InputStream} to the {@link #setContents(InputStream) setContents()} method. |
| * <p> |
| * On top of this scalable I/O model a few methods are provided to get or set the blob's contents in |
| * more convenient formats, such as {@link DataInput#readUTF() UTF strings}, integers, or booleans. |
| * <p> |
| * In no case the contents of this blob are kept in memory. If the {@link #getStorage() storage} of this blob was |
| * created with a {@link StorageFactory#create(String, StorageCache) storage cache} |
| * the contents are possibly served from that cache. In any case all read and write access contacts the remote service |
| * behind storage's service, even if only to validate that a possibly cached version of the contents is still up-to-date, |
| * see {@link #getETag()}. |
| * <p> |
| * |
| * @author Eike Stepper |
| * @noextend This interface is not intended to be extended by clients. |
| * @noimplement This interface is not intended to be implemented by clients. |
| */ |
| public interface IBlob |
| { |
| /** |
| * Returns the storage of this blob. |
| * |
| * @return the storage of this blob, never <code>null</code>. |
| */ |
| public IStorage getStorage(); |
| |
| /** |
| * Returns the key of this blob. |
| * |
| * @return the key of this blob, never <code>null</code>. |
| */ |
| public String getKey(); |
| |
| /** |
| * Returns an immutable {@link Map} of the properties of this blob. |
| * <p> |
| * The properties represent arbitrary meta data about this blob that the service provider decides to provide. |
| * The only property that service providers are required to provide is the {@link #getETag() ETag} property. |
| * <p> |
| * The properties map is only updated during any of the getContents() or setContents() methods. |
| * If the {@link #getStorage() storage} of this blob was |
| * created with a {@link StorageFactory#create(String, StorageCache) storage cache} |
| * the properties are possibly served from that cache. |
| * <p> |
| * |
| * @return an immutable {@link Map} of the properties of this blob, never <code>null</code>.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #getETag() |
| * @see #getContents() |
| * @see #setContents(InputStream) |
| */ |
| public Map<String, String> getProperties() throws IllegalStateException; |
| |
| /** |
| * Returns the ETag of this blob. |
| * <p> |
| * The ETag of a blob is an opaque but unique value that the service provider assigns to a particular version |
| * (of the contents) of the blob. This value serves two purposes: |
| * <p> |
| * <ul> |
| * <li> If the {@link #getStorage() storage} of this blob was created with a |
| * {@link StorageFactory#create(String, StorageCache) storage cache} |
| * and the cache contains the current version of this blob |
| * all getContents() methods use the ETag to prevent the server from sending the blob's contents again. |
| * The cached contents are returned instead. |
| * <li> All setContents() methods use the ETag (if it is known) to prevent the server from storing conflicting |
| * changes. A conflicting change is updating a blob with new contents that is based on an out-dated ETag. |
| * </ul> |
| * <p> |
| * |
| * @return the ETag of this blob, or <code>null</code> if the ETag of this blob is currently not known.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #setETag(String) |
| */ |
| public String getETag() throws IllegalStateException; |
| |
| /** |
| * Sets the ETag of this blob. |
| * <p> |
| * The ETag of a blob is an opaque but unique value that the service provider assigns to a particular version |
| * (of the contents) of the blob. This value serves two purposes: |
| * <p> |
| * <ul> |
| * <li> If the {@link #getStorage() storage} of this blob was created with a |
| * {@link StorageFactory#create(String, StorageCache) storage cache} |
| * and the cache contains the current version of this blob |
| * all getContents() methods use the ETag to prevent the server from sending the blob's contents again. |
| * The cached contents are returned instead. |
| * <li> All setContents() methods use the ETag (if it is known) to prevent the server from storing conflicting |
| * changes. A conflicting change is updating a blob with new contents that is based on an out-dated ETag. |
| * </ul> |
| * <p> |
| * If the {@link #getStorage() storage} of this blob was created with a |
| * {@link StorageFactory#create(String, StorageCache) storage cache} |
| * and the new ETag is different from the cached ETag the cached blob is deleted locally. |
| * <p> |
| * |
| * @param eTag the new ETag of this blob, or <code>null</code> to reset the ETag.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #getETag() |
| */ |
| public void setETag(String eTag) throws IllegalStateException; |
| |
| /** |
| * Returns an {@link InputStream} that represents the current contents of this blob. |
| * <p> |
| * This method always contacts the server. |
| * <p> |
| * If the {@link #getStorage() storage} of this blob was created with a |
| * {@link StorageFactory#create(String, StorageCache) storage cache} |
| * and the cache contains the current version of this blob (i.e., the blob's ETag is up-to-date) |
| * the server will not send the blob's contents again. The cached contents are returned instead. |
| * If the cache does not contain the current version of this blob (i.e., the blob's ETag is out-of-date) |
| * the current remote contents are downloaded, cached, and returned by this method. |
| * <p> |
| * <b>Important note:</b> |
| * <p> |
| * The new contents will only be cached if (caching is enabled and) the |
| * returned input stream is fully read and closed. |
| * <p> |
| * |
| * @return an {@link InputStream} that represents the current contents of this blob, never <code>null</code>.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws NotFoundException if this blob does not exist on the server.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #setContents(InputStream) |
| * @see #getETag() |
| */ |
| public InputStream getContents() throws IOException, NoServiceException, NotFoundException, IllegalStateException; |
| |
| /** |
| * Sets an {@link InputStream} that represents the new contents of this blob. |
| * <p> |
| * This method always contacts the server. |
| * <p> |
| * If this blob has an ETag it will be used to detect and avoid conflicts on the server side. |
| * The ETag of this blob can be {@link #setETag(String) set} to <code>null</code> if server-side conflict detection is not desired. |
| * Server-side conflicts are indicated by throwing a {@link ConflictException}. |
| * <p> |
| * If the {@link #getStorage() storage} of this blob was created with a |
| * {@link StorageFactory#create(String, StorageCache) storage cache} |
| * and the server successfully updated the blob (i.e., the blob's ETag was up-to-date) |
| * the cache will be updated with the new version of the contents. |
| * <p> |
| * |
| * @param in an {@link InputStream} that represents the new contents of this blob.<p> |
| * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws ConflictException if the server detected a conflict and did not update the blob.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #getContents() |
| * @see #setETag(String) |
| */ |
| public boolean setContents(InputStream in) throws IOException, NoServiceException, ConflictException, IllegalStateException; |
| |
| /** |
| * Returns a {@link String} that represents the current contents of this blob. |
| * <p> |
| * This method is a convenient wrapper around the {@link #getContents()} method. |
| * It assumes that the binary contents of this blob represent a UTF-8 encoded text value. |
| * If this assumption is wrong (and this method can not detect this case) the results are unpredictable. |
| * Otherwise the semantics of this method are identical to the ones of {@link #getContents()}. |
| * <p> |
| * |
| * @return a {@link String} that represents the current contents of this blob, never <code>null</code>.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws NotFoundException if this blob does not exist on the server.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #getContents() |
| */ |
| public String getContentsUTF() throws IOException, NoServiceException, IllegalStateException, NotFoundException; |
| |
| /** |
| * Sets a {@link String} that represents the new contents of this blob. |
| * <p> |
| * This method is a convenient wrapper around the {@link #setContents(InputStream)} method. |
| * The semantics of this method are identical to the ones of {@link #setContents(InputStream)}. |
| * <p> |
| * |
| * @param value a {@link String} that represents the new contents of this blob.<p> |
| * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws ConflictException if the server detected a conflict and did not update the blob.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #setContents(InputStream) |
| */ |
| public boolean setContentsUTF(String value) throws IOException, NoServiceException, ConflictException, IllegalStateException; |
| |
| /** |
| * Returns a primitive int value that represents the current contents of this blob. |
| * <p> |
| * This method is a convenient wrapper around the {@link #getContents()} method. |
| * It assumes that the binary contents of this blob represent a UTF-8 encoded integer value. |
| * If this assumption is wrong (and this method can not detect this case) the results are unpredictable. |
| * Otherwise the semantics of this method are identical to the ones of {@link #getContents()}. |
| * <p> |
| * |
| * @return a primitive int value that represents the current contents of this blob.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws NotFoundException if this blob does not exist on the server.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #getContents() |
| */ |
| public int getContentsInt() throws IOException, NoServiceException, NotFoundException, IllegalStateException, NumberFormatException; |
| |
| /** |
| * Sets a a primitive int value that represents the new contents of this blob. |
| * <p> |
| * This method is a convenient wrapper around the {@link #setContents(InputStream)} method. |
| * The semantics of this method are identical to the ones of {@link #setContents(InputStream)}. |
| * <p> |
| * |
| * @param value a a primitive int value that represents the new contents of this blob.<p> |
| * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws ConflictException if the server detected a conflict and did not update the blob.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #setContents(InputStream) |
| */ |
| public boolean setContentsInt(int value) throws IOException, NoServiceException, ConflictException, IllegalStateException; |
| |
| /** |
| * Returns a primitive boolean value that represents the current contents of this blob. |
| * <p> |
| * This method is a convenient wrapper around the {@link #getContents()} method. |
| * It assumes that the binary contents of this blob represent a UTF-8 encoded boolean value. |
| * If this assumption is wrong (and this method can not detect this case) the results are unpredictable. |
| * Otherwise the semantics of this method are identical to the ones of {@link #getContents()}. |
| * <p> |
| * |
| * @return a primitive boolean value that represents the current contents of this blob.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws NotFoundException if this blob does not exist on the server.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #getContents() |
| */ |
| public boolean getContentsBoolean() throws IOException, NoServiceException, NotFoundException, IllegalStateException; |
| |
| /** |
| * Sets a a primitive boolean value that represents the new contents of this blob. |
| * <p> |
| * This method is a convenient wrapper around the {@link #setContents(InputStream)} method. |
| * The semantics of this method are identical to the ones of {@link #setContents(InputStream)}. |
| * <p> |
| * |
| * @param value a a primitive boolean value that represents the new contents of this blob.<p> |
| * @return <code>true</code> if a new blob was created, <code>false</code> if an existing blob was updated.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws ConflictException if the server detected a conflict and did not update the blob.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #setContents(InputStream) |
| */ |
| public boolean setContentsBoolean(boolean value) throws IOException, NoServiceException, ConflictException, IllegalStateException; |
| |
| /** |
| * Deletes this blob. |
| * <p> |
| * This method always contacts the server. |
| * <p> |
| * If this blob has an ETag it will be used to detect and avoid conflicts on the server side. |
| * The ETag of this blob can be {@link #setETag(String) set} to <code>null</code> if server-side conflict detection is not desired. |
| * Server-side conflicts are indicated by throwing a {@link ConflictException}. |
| * <p> |
| * If the {@link #getStorage() storage} of this blob was created with a |
| * {@link StorageFactory#create(String, StorageCache) storage cache} |
| * and the server successfully deleted the blob (i.e., the blob's ETag was up-to-date) |
| * the cache will be deleted, too. |
| * <p> |
| * |
| * @return <code>true</code> if this blob was successfully deleted from the server, <code>false</code> if it did not exist.<p> |
| * @throws IOException if remote I/O was unsuccessful. A {@link ProtocolException} may contain more information about protocol-specific problems.<p> |
| * @throws NoServiceException if the {@link #getStorage() storage} of this blob has no {@link IStorageService service} assigned.<p> |
| * @throws ConflictException if the server detected a conflict and did not update the blob.<p> |
| * @throws IllegalStateException if this blob is {@link #isDisposed() disposed}.<p> |
| * |
| * @see #setETag(String) |
| */ |
| public boolean delete() throws IOException, NoServiceException, ConflictException, IllegalStateException; |
| |
| /** |
| * Returns <code>true</code> if this blob is disposed, <code>false</code> otherwise. |
| * <p> |
| * The only way for a blob to become disposed is when the storage of the {@link IStorage storage} of that blob |
| * is changed after that blob was created. Applications must call {@link IStorage#getBlob(String) getBlob()} to acquire |
| * a new, valid blob instance in that case. |
| * <p> |
| * |
| * @see IStorage#getBlob(String) getBlob() |
| */ |
| public boolean isDisposed(); |
| } |