com.atlassian.jira.issue.attachment
Class DualAttachmentStore

java.lang.Object
  extended by com.atlassian.jira.issue.attachment.DualAttachmentStore
All Implemented Interfaces:
AttachmentStore

public class DualAttachmentStore
extends Object
implements AttachmentStore

AttachmentStore implementation that wraps around two AttachmentStores (a file system implementation, and a remote Blobstore implementation), and handles delegating to them appropriately given dark feature flags.

Since:
v6.3

Nested Class Summary
 
Nested classes/interfaces inherited from interface com.atlassian.jira.issue.attachment.AttachmentStore
AttachmentStore.AttachmentAdapter
 
Field Summary
static String FS_ONLY
           
static String FS_PRIMARY
           
static String REMOTE_ONLY
           
static String REMOTE_PRIMARY
           
 
Constructor Summary
DualAttachmentStore(FileSystemAttachmentStore fileSystem, RemoteAttachmentStore remote, FeatureManager featureManager, AttachmentDirectoryAccessor directoryAccessor, ThumbnailAccessor thumbnailAccessor)
           
 
Method Summary
 void checkValidAttachmentDirectory(Issue issue)
          Checks that the Attachment directory of the given issue is right to go - writable, accessible etc.
 void checkValidTemporaryAttachmentDirectory()
          Checks that the temporary directory for attachment uploads is right to go - writable, accessible etc.
 com.atlassian.util.concurrent.Promise<Void> deleteAttachment(Attachment attachment)
          Delete the specified attachment.
 com.atlassian.util.concurrent.Promise<Void> deleteAttachmentContainerForIssue(Issue issue)
          Delete the container for attachments for a given issue.
 com.atlassian.fugue.Option<ErrorCollection> errors()
          Health status for this component.
<A> com.atlassian.util.concurrent.Promise<A>
getAttachment(Attachment metaData, com.atlassian.util.concurrent.Function<InputStream,A> inputStreamProcessor)
          Retrieve data for a given attachment.
 File getAttachmentDirectory(Issue issue)
          Returns the physical directory of the attachments for the given issue.
 File getAttachmentDirectory(Issue issue, boolean createDirectory)
          Returns the physical directory of the attachments for the given issue.
 File getAttachmentDirectory(String issueKey)
           
 File getAttachmentDirectory(String attachmentDirectory, String projectKey, String issueKey)
          Get the attachment directory for the given attachment base directory, project key, and issue key.
 File getAttachmentFile(Attachment attachment)
          Returns the physical File for the given Attachment.
 File getAttachmentFile(AttachmentStore.AttachmentAdapter adapter, File attachmentDir)
          This is intended for cases where you want more control over where the attachment actually lives and you just want something to handle the look up logic for the various possible filenames an attachment can have.
 File getAttachmentFile(Issue issue, Attachment attachment)
          Returns the physical File for the given Attachment.
 File getLegacyThumbnailFile(Attachment attachment)
          Returns the old legacy file name for thumbnails.
 File getTemporaryAttachmentDirectory()
           
 File getThumbnailDirectory(Issue issue)
          Returns the physical directory of the thumbnails for the given issue, creating if necessary.
 File getThumbnailFile(Attachment attachment)
          Just like the attachments themselves, thumbnails can succumb to file system encoding problems.
 File getThumbnailFile(Issue issue, Attachment attachment)
          Returns the file handle for the given attachment's thumbnail.
 com.atlassian.util.concurrent.Promise<Void> move(Attachment metaData, String newIssueKey)
          Moves an attachment from its current issue under a new one
 com.atlassian.util.concurrent.Promise<Attachment> putAttachment(Attachment metadata, File source)
          Store attachment data for a given attachment.
 com.atlassian.util.concurrent.Promise<Attachment> putAttachment(Attachment metadata, InputStream source)
          Store attachment data for a given attachment.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

FS_ONLY

public static final String FS_ONLY
See Also:
Constant Field Values

REMOTE_ONLY

public static final String REMOTE_ONLY
See Also:
Constant Field Values

FS_PRIMARY

public static final String FS_PRIMARY
See Also:
Constant Field Values

REMOTE_PRIMARY

public static final String REMOTE_PRIMARY
See Also:
Constant Field Values
Constructor Detail

DualAttachmentStore

public DualAttachmentStore(@Nonnull
                           FileSystemAttachmentStore fileSystem,
                           @Nonnull
                           RemoteAttachmentStore remote,
                           @Nonnull
                           FeatureManager featureManager,
                           @Nonnull
                           AttachmentDirectoryAccessor directoryAccessor,
                           @Nonnull
                           ThumbnailAccessor thumbnailAccessor)
Method Detail

getThumbnailDirectory

@Nonnull
public File getThumbnailDirectory(@Nonnull
                                          Issue issue)
Description copied from interface: AttachmentStore
Returns the physical directory of the thumbnails for the given issue, creating if necessary.

Specified by:
getThumbnailDirectory in interface AttachmentStore
Parameters:
issue - the issue whose thumbnail directory you want
Returns:
the issue's thumbnail directory

getAttachmentDirectory

public File getAttachmentDirectory(@Nonnull
                                   String issueKey)
Specified by:
getAttachmentDirectory in interface AttachmentStore

getAttachmentDirectory

public File getAttachmentDirectory(@Nonnull
                                   Issue issue,
                                   boolean createDirectory)
Description copied from interface: AttachmentStore
Returns the physical directory of the attachments for the given issue. This will create it if necessary.

Specified by:
getAttachmentDirectory in interface AttachmentStore
Parameters:
issue - the issue whose attachment directory you want
createDirectory - If true, and the directory does not currently exist, then the directory is created.
Returns:
the issue's attachment directory

getTemporaryAttachmentDirectory

public File getTemporaryAttachmentDirectory()
Specified by:
getTemporaryAttachmentDirectory in interface AttachmentStore

getAttachmentDirectory

public File getAttachmentDirectory(@Nonnull
                                   Issue issue)
Description copied from interface: AttachmentStore
Returns the physical directory of the attachments for the given issue. This will create it if necessary.

Specified by:
getAttachmentDirectory in interface AttachmentStore
Parameters:
issue - the issue whose attachment directory you want
Returns:
The issue's attachment directory.

getAttachmentDirectory

public File getAttachmentDirectory(String attachmentDirectory,
                                   String projectKey,
                                   String issueKey)
Description copied from interface: AttachmentStore
Get the attachment directory for the given attachment base directory, project key, and issue key.

The idea is to encapsulate all of the path-joinery magic to make future refactoring easier if we ever decide to move away from attachment-base/project-key/issue-ket

Specified by:
getAttachmentDirectory in interface AttachmentStore
Parameters:
attachmentDirectory - base of attachments
projectKey - the project key the issue belongs to
issueKey - the issue key for the issue
Returns:
the directory attachments for this issue live in

checkValidAttachmentDirectory

public void checkValidAttachmentDirectory(Issue issue)
                                   throws AttachmentException
Description copied from interface: AttachmentStore
Checks that the Attachment directory of the given issue is right to go - writable, accessible etc. Will create it if necessary.

Specified by:
checkValidAttachmentDirectory in interface AttachmentStore
Parameters:
issue - the issue whose attachment directory to check.
Throws:
AttachmentException - if the directory is not writable or missing and cannot be created.

checkValidTemporaryAttachmentDirectory

public void checkValidTemporaryAttachmentDirectory()
                                            throws AttachmentException
Description copied from interface: AttachmentStore
Checks that the temporary directory for attachment uploads is right to go - writable, accessible etc.

Specified by:
checkValidTemporaryAttachmentDirectory in interface AttachmentStore
Throws:
AttachmentException - if the directory is not writable or missing and cannot be created.

getAttachmentFile

public File getAttachmentFile(AttachmentStore.AttachmentAdapter adapter,
                              File attachmentDir)
Description copied from interface: AttachmentStore
This is intended for cases where you want more control over where the attachment actually lives and you just want something to handle the look up logic for the various possible filenames an attachment can have.

In practice, this is just used during Project Import

Specified by:
getAttachmentFile in interface AttachmentStore
Parameters:
adapter - it's not an attachment but it acts like one for our purposes.
attachmentDir - the directory the attachments live in. This is different that the system-wide attachment directory. i.e. this would "attachments/MKY/MKY-1" and not just "attachments"
Returns:
the actual attachment

getThumbnailFile

@Nonnull
public File getThumbnailFile(Attachment attachment)
Description copied from interface: AttachmentStore
Just like the attachments themselves, thumbnails can succumb to file system encoding problems. However we are going to regenerate thumbnails by only using the new naming scheme and not the legacy one. We can't do this for attachments, but we can for thumbnails since they are ephemeral objects anyway. http://jira.atlassian.com/browse/JRA-23311

Specified by:
getThumbnailFile in interface AttachmentStore
Parameters:
attachment - the attachment for which to get the thumbnail file
Returns:
a non-null file handle (the file itself might not exist)
See Also:
AttachmentStore.getThumbnailFile(com.atlassian.jira.issue.Issue, Attachment)

getThumbnailFile

@Nonnull
public File getThumbnailFile(@Nonnull
                                     Issue issue,
                                     Attachment attachment)
Description copied from interface: AttachmentStore
Returns the file handle for the given attachment's thumbnail. This method performs better than AttachmentStore.getThumbnailFile(Attachment) if you already have the issue.

Specified by:
getThumbnailFile in interface AttachmentStore
Parameters:
issue - the issue to which the attachment belongs
attachment - the attachment for which to get the thumbnail file
Returns:
a non-null file handle (the file itself might not exist)
See Also:
AttachmentStore.getThumbnailFile(Attachment)

getLegacyThumbnailFile

public File getLegacyThumbnailFile(Attachment attachment)
Description copied from interface: AttachmentStore
Returns the old legacy file name for thumbnails. http://jira.atlassian.com/browse/JRA-23311

Specified by:
getLegacyThumbnailFile in interface AttachmentStore
Parameters:
attachment - the attachment in play
Returns:
the full legacy thumbnail file name

getAttachmentFile

public File getAttachmentFile(Issue issue,
                              Attachment attachment)
                       throws DataAccessException
Description copied from interface: AttachmentStore
Returns the physical File for the given Attachment. This method performs better as it does not need to look up the issue object.

Specified by:
getAttachmentFile in interface AttachmentStore
Parameters:
issue - the issue the attachment belongs to.
attachment - the attachment.
Returns:
the file.
Throws:
DataAccessException - on failure getting required attachment info.

getAttachmentFile

public File getAttachmentFile(Attachment attachment)
                       throws DataAccessException
Description copied from interface: AttachmentStore
Returns the physical File for the given Attachment. If you are calling this on multiple attachments for the same issue, consider using the overriden method that passes in the issue. Else, this goes to the database for each call.

Specified by:
getAttachmentFile in interface AttachmentStore
Parameters:
attachment - the attachment.
Returns:
the file.
Throws:
DataAccessException - on failure getting required attachment info.

putAttachment

public com.atlassian.util.concurrent.Promise<Attachment> putAttachment(Attachment metadata,
                                                                       InputStream source)
Description copied from interface: AttachmentStore
Store attachment data for a given attachment.

Specified by:
putAttachment in interface AttachmentStore
Parameters:
metadata - attachment metadata, used to determine the logical key under which to store the attachment data
source - source data. The attachment store will close this stream when it has completed. The stream will be closed once the operation is complete.
Returns:
A promise of an attachment that performs the 'put' operation once the promise is claimed. The promise will contain an AttachmentRuntimeException in case of error.

putAttachment

public com.atlassian.util.concurrent.Promise<Attachment> putAttachment(Attachment metadata,
                                                                       File source)
Description copied from interface: AttachmentStore
Store attachment data for a given attachment.

Specified by:
putAttachment in interface AttachmentStore
Parameters:
metadata - attachment metadata, used to determine the logical key under which to store the attachment data
source - source data. It is assumed that the file will exist during the attachment process (i.e. relatively long lived).
Returns:
A promise of an attachment that performs the 'put' operation once the promise is claimed.

getAttachment

public <A> com.atlassian.util.concurrent.Promise<A> getAttachment(Attachment metaData,
                                                                  com.atlassian.util.concurrent.Function<InputStream,A> inputStreamProcessor)
Description copied from interface: AttachmentStore
Retrieve data for a given attachment.

Specified by:
getAttachment in interface AttachmentStore
Type Parameters:
A - The class that the inputStreamProcessor returns when run.
Parameters:
metaData - attachment metadata, used to determine the logical key under which to store the attachment data
inputStreamProcessor - Function that processes the attachment data.
Returns:
A promise of an object that represented the processed attachment data (i.e. from running the inputStreamProcessor over the attachment data). The promise will contain an AttachmentRuntimeException in case of error.

move

public com.atlassian.util.concurrent.Promise<Void> move(Attachment metaData,
                                                        String newIssueKey)
Description copied from interface: AttachmentStore
Moves an attachment from its current issue under a new one

Specified by:
move in interface AttachmentStore
Parameters:
metaData - attachment metadata, used to determine the logical key of the attachment to be moved.
newIssueKey - the key of the new issue under which the attachment will reside.
Returns:
a promise that will be completed when the operation is complete. It will contain an AttachmentRuntimeException in case of error.

deleteAttachment

public com.atlassian.util.concurrent.Promise<Void> deleteAttachment(@Nonnull
                                                                    Attachment attachment)
Description copied from interface: AttachmentStore
Delete the specified attachment.

Specified by:
deleteAttachment in interface AttachmentStore
Returns:
a promise that will contain an AttachmentCleanupException in case of error.

deleteAttachmentContainerForIssue

public com.atlassian.util.concurrent.Promise<Void> deleteAttachmentContainerForIssue(@Nonnull
                                                                                     Issue issue)
Description copied from interface: AttachmentStore
Delete the container for attachments for a given issue. For file systems, this means the attachment directory for that issue.

Specified by:
deleteAttachmentContainerForIssue in interface AttachmentStore
Parameters:
issue - The issue to delete attachments for.
Returns:
A promise that will contain a AttachmentCleanupException if there is a problem deleting the attachment directory.

errors

public com.atlassian.fugue.Option<ErrorCollection> errors()
Description copied from interface: AttachmentStore
Health status for this component. Specifically the errors that cause the attachment subsystem to fail.

Specified by:
errors in interface AttachmentStore
Returns:
An option of an error collection that contains error messages if there are any issues. The option will be none if there are no errors.


Copyright © 2002-2014 Atlassian. All Rights Reserved.