@NotThreadSafe @PublicSpi public class JiraWebActionSupport extends JiraActionSupport implements ErrorCollection, AuthorizationSupport, HttpServletVariables
When adding to this class, be sure that what you are adding is used by a large number of actions - otherwise add it to a sub class of this.
Modifier and Type | Class and Description |
---|---|
static class |
JiraWebActionSupport.MessageType
Represents a type of message that the browser will display after the next page load.
|
ErrorCollection.Reason
I18nHelper.BeanFactory
Modifier and Type | Field and Description |
---|---|
static String |
ISSUE_NOT_FOUND_RESULT |
static String |
PERMISSION_VIOLATION_RESULT |
protected javax.servlet.http.HttpServletRequest |
request
Deprecated.
since 6.0 - use
getHttpRequest() instead. |
static String |
RETURN_URL_PARAMETER |
protected Collection |
savedFilters |
log
Constructor and Description |
---|
JiraWebActionSupport() |
Modifier and Type | Method and Description |
---|---|
void |
addError(String field,
String message,
ErrorCollection.Reason reason)
Add a field-specific error message.
|
void |
addErrorCollection(ErrorCollection errors)
Populate this ErrorCollection with general and field-specific errors.
|
void |
addErrorMessage(String message,
ErrorCollection.Reason reason)
Add error message relating to system state (not field-specific), and a reason.
|
protected void |
addErrorMessageByKeyIfAbsent(String errorMsgKey) |
protected void |
addErrorMessageIfAbsent(String errorMsg) |
protected void |
addMessageToResponse(String msg,
String type,
boolean closeable,
String target)
This will populate the the custom Atlassian header with the details of a pop-up message.
|
void |
addReason(ErrorCollection.Reason reason)
Add a reason why the function has not been performed.
|
void |
addReasons(Set<ErrorCollection.Reason> reasons)
Add reasons why the function has not been performed.
|
protected String |
forceRedirect(String redirect)
This method will force a server redirect, with no security checks.
|
String |
getAdministratorContactLink()
Get the link, with Internationalised text for contacting the administrators of JIRA.
|
ApplicationProperties |
getApplicationProperties() |
protected AuthorizationSupport |
getAuthorizationSupport() |
String |
getConglomerateCookieValue(String cookieName,
String key)
Retrieve the value from a conglomerate Cookie from the request.
|
ConstantsManager |
getConstantsManager() |
String |
getDateFormat() |
String |
getDateTimeFormat() |
DateTimeFormatter |
getDateTimeFormatter()
Returns a DateTimeFormatter that can be used to format times and dates in the user's time zone using
DateTimeStyle.RELATIVE . |
String |
getDescTranslation(org.ofbiz.core.entity.GenericValue issueConstantGV)
Deprecated.
Use
ConstantsManager instead. Since v6.0. |
String |
getDescTranslation(IssueConstant issueConstant)
Deprecated.
Use
ConstantsManager instead. Since v6.0. |
DateTimeFormatter |
getDmyDateFormatter()
Returns a DateTimeFormatter that can be used to format dates in the user's time zone using
DateTimeStyle.DATE . |
String |
getEmptyResponse()
Returns an empty response code (204)
|
Collection<String> |
getErrorMessages()
Get all non field-specific error messages.
|
Map<String,String> |
getErrors()
Get all field-specific errors.
|
Field |
getField(String id) |
Collection<String> |
getFlushedErrorMessages()
Get error messages, then get rid of them.
|
protected GlobalPermissionManager |
getGlobalPermissionManager() |
Hint |
getHint(String context) |
protected HintManager |
getHintManager() |
javax.servlet.http.HttpServletRequest |
getHttpRequest() |
javax.servlet.http.HttpServletResponse |
getHttpResponse() |
javax.servlet.http.HttpSession |
getHttpSession() |
JiraContactHelper |
getJiraContactHelper() |
JiraServiceContext |
getJiraServiceContext()
Provides a service context with the current user which contains this action as its
ErrorCollection . |
String |
getLanguage() |
ApplicationUser |
getLoggedInApplicationUser()
Deprecated.
Use
getLoggedInUser() . Since v7.0 |
ApplicationUser |
getLoggedInUser() |
String |
getNameTranslation(org.ofbiz.core.entity.GenericValue issueConstantGV)
Deprecated.
Use
ConstantsManager instead. Since v6.0. |
String |
getNameTranslation(IssueConstant issueConstant)
Deprecated.
Use
ConstantsManager instead. Since v6.0. |
OutlookDate |
getOutlookDate()
Deprecated.
Use
getDateTimeFormatter() instead. Since v5.0. |
protected PermissionManager |
getPermissionManager() |
ProjectManager |
getProjectManager() |
Hint |
getRandomHint() |
Set<ErrorCollection.Reason> |
getReasons()
A set of well known reasons why the function has not been performed.
|
String |
getRedirect(String defaultUrl)
Redirects to the value of
getReturnUrl() , falling back to defaultUrl if the returnUrl is
not set. |
String |
getRedirect(String defaultUrl,
boolean allowUnsafeRedirect)
Redirects to the value of
getReturnUrl() , falling back to defaultUrl if the returnUrl is
not set. |
protected RedirectSanitiser |
getRedirectSanitiser()
Returns a RedirectSanitiser implementation.
|
String |
getReturnUrl() |
String |
getReturnUrlForCancelLink()
The cancel links should not included the selectedIssueId, otherwise when returning to the issue navigator an
issue updated notification will be shown.
|
List<String> |
getSearchSortDescriptions(SearchRequest searchRequest) |
Project |
getSelectedProject()
Gets the last viewed project that the user visited and still has permission to see.
|
Project |
getSelectedProjectObject()
Gets the last viewed project that the user visited and still has permission to see.
|
String |
getServerId() |
javax.servlet.ServletContext |
getServletContext() |
String |
getTimeFormat() |
UriValidator |
getUriValidator() |
String |
getUserFullName(String username) |
UserManager |
getUserManager() |
protected UserProjectHistoryManager |
getUserProjectHistoryManager() |
VersionManager |
getVersionManager() |
String |
getWebworkStack()
For debugging JSPs; prints the webwork stack.
|
String |
getWebworkStack(String selected)
For debugging JSPs; prints the webwork stack, highlighting the specified node.
|
String |
getXsrfToken() |
protected boolean |
hasErrorMessage(String errorMsg) |
protected boolean |
hasErrorMessageByKey(String errorMsgKey) |
boolean |
hasGlobalPermission(GlobalPermissionKey globalPermissionKey)
Returns true if the logged in user has the given global permission.
|
boolean |
hasGlobalPermission(String permissionKey)
Returns true if the logged in user has the given global permission.
|
boolean |
hasIssuePermission(int permissionsId,
Issue issue)
Returns true if the logged in user has the given permission type on the given Issue.
|
boolean |
hasIssuePermission(ProjectPermissionKey projectPermissionKey,
Issue issue)
Returns true if the logged in user has the given permission on the given Issue.
|
boolean |
hasIssuePermission(String permissionKey,
Issue issue)
Returns true if the logged in user has the given permission type on the given Issue.
|
boolean |
hasPermission(int permissionsId)
Deprecated.
Use
hasGlobalPermission(com.atlassian.jira.permission.GlobalPermissionKey) instead. Since v6.4. |
boolean |
hasProjectPermission(int permissionsId,
Project project)
Deprecated.
|
boolean |
hasProjectPermission(ProjectPermissionKey projectPermissionKey,
Project project)
Returns true if the logged in user has the given permission on the given project.
|
String |
htmlEncode(String encodeMe)
Convenience instance method to call static utility from webwork EL.
|
protected String |
insertContextPath(String url)
Prepends the context path to the URL if it begins with a forward slash (this is commonly used for redirects
within a JIRA instance).
|
boolean |
isInlineDialogMode()
This returns true if the action has been invoked as an inline dialog.
|
boolean |
isSystemAdministrator() |
boolean |
isUserExists(String username)
Deprecated.
Use
isUserExistsByName(String) or isUserExistsByKey(String) instead, as appropriate. Since v6.0. |
boolean |
isUserExistsByKey(String userkey) |
boolean |
isUserExistsByName(String username) |
String |
returnComplete() |
String |
returnComplete(String url) |
protected String |
returnCompleteWithInlineRedirect(String url)
This will return success response with body containing url to redirect.
|
protected String |
returnCompleteWithInlineRedirectAndMsg(String url,
String msg,
JiraWebActionSupport.MessageType type,
boolean closeable,
String target)
This will redirect like
returnCompleteWithInlineRedirect(String) , and will also populate the response
with the details of a pop-up message to be displayed on the redirected page. |
protected String |
returnCompleteWithInlineRedirectAndMsg(String url,
String msg,
String type,
boolean closeable,
String target)
Deprecated.
since 5.1. Use
returnCompleteWithInlineRedirectAndMsg(String, String, MessageType, boolean, String)
instead. |
protected String |
returnMsgToUser(String url,
String msg,
JiraWebActionSupport.MessageType type,
boolean closeable,
String target)
This will redirect like
returnComplete() , and will also populate the response
with the details of a pop-up message to be displayed on the redirected page. |
protected String |
returnMsgToUser(String url,
String msg,
String type,
boolean closeable,
String target)
Deprecated.
since 5.1. Use
returnMsgToUser(String, String, MessageType, boolean, String) instead. |
void |
setConglomerateCookieValue(String cookieName,
String key,
String value)
Set the value key/value pair in a conglomerate Cookie.
|
void |
setInline(boolean inline)
This is the web parameter setter for invoking an action as an inline dialog
|
void |
setReasons(Set<ErrorCollection.Reason> reasons)
Set reasons why the function has not been performed.
|
void |
setReturnUrl(String returnUrl) |
void |
setSelectedProjectId(Long id) |
protected void |
tagMauEventWithApplication(MauApplicationKey applicationKey) |
protected void |
tagMauEventWithProject(Project project) |
String |
urlEncode(String encode)
Encodes the given string into
application/x-www-form-urlencoded format, using the JIRA encoding scheme to
obtain the bytes for unsafe characters. |
addErrorMessages, addErrorMessages, addErrors, addIllegalArgumentException, execute, getActionName, getComponentInstanceOfType, getDefaultResourceBundle, getI18nHelper, getKeysForPrefix, getLocale, getOfBizDelegator, getResourceBundle, getResult, getText, getText, getText, getText, getText, getText, getText, getText, getText, getText, getText, getText, getText, getText, getUnescapedText, getUntransformedRawText, getUserPreferences, hasAnyErrors, isIndexing, isKeyDefined, removeKeyOrAddError
addError, addErrorMessage, doDefault, doExecute, doValidation, getCommandName, getHasErrorMessages, getHasErrors, getPropertyEditorMessage, getTexts, getTexts, getTimezone, invalidInput, invokeCommand, isCommand, setCommand, setErrorMessages, setErrors, validate
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
addError, addErrorMessage, addErrorMessages, addErrors, hasAnyErrors, setErrorMessages
public static final String RETURN_URL_PARAMETER
public static final String PERMISSION_VIOLATION_RESULT
public static final String ISSUE_NOT_FOUND_RESULT
protected javax.servlet.http.HttpServletRequest request
getHttpRequest()
instead.HttpServletVariables.getHttpRequest()
protected Collection savedFilters
@IncompatibleReturnType(since="7.0", was="com.atlassian.crowd.embedded.api.User") public ApplicationUser getLoggedInUser()
@Deprecated public ApplicationUser getLoggedInApplicationUser()
getLoggedInUser()
. Since v7.0public String getXsrfToken()
public javax.servlet.http.HttpServletRequest getHttpRequest()
getHttpRequest
in interface HttpServletVariables
HttpServletRequest
in playHttpServletVariables.getHttpRequest()
public javax.servlet.http.HttpSession getHttpSession()
getHttpSession
in interface HttpServletVariables
HttpSession
in playHttpServletVariables.getHttpSession()
public javax.servlet.http.HttpServletResponse getHttpResponse()
getHttpResponse
in interface HttpServletVariables
HttpServletResponse
in playHttpServletVariables.getHttpResponse()
public javax.servlet.ServletContext getServletContext()
getServletContext
in interface HttpServletVariables
ServletContext
of the JIRA web applicationHttpServletVariables.getServletContext()
public ApplicationProperties getApplicationProperties()
getApplicationProperties
in class JiraActionSupport
public UriValidator getUriValidator()
protected GlobalPermissionManager getGlobalPermissionManager()
protected PermissionManager getPermissionManager()
protected UserProjectHistoryManager getUserProjectHistoryManager()
public ConstantsManager getConstantsManager()
public ProjectManager getProjectManager()
public VersionManager getVersionManager()
@Deprecated public OutlookDate getOutlookDate()
getDateTimeFormatter()
instead. Since v5.0.public DateTimeFormatter getDateTimeFormatter()
DateTimeStyle.RELATIVE
.public DateTimeFormatter getDmyDateFormatter()
DateTimeStyle.DATE
.public JiraContactHelper getJiraContactHelper()
public UserManager getUserManager()
public String getAdministratorContactLink()
JiraContactHelper#getAdministratorContactLinkHtml(String, com.atlassian.jira.util.I18nHelper)}
protected final HintManager getHintManager()
protected AuthorizationSupport getAuthorizationSupport()
public String getRedirect(String defaultUrl)
getReturnUrl()
, falling back to defaultUrl
if the returnUrl
is
not set. This method clears the returnUrl
. If there are errors, this method returns "ERROR".
If the URL starts with '/' it is interpreted as context-relative.
RedirectSanitiser.makeSafeRedirectUrl(String)
. Use getRedirect(String, boolean)
to allow unsafe
redirects for URLs that do not contain possibly malicious user input.defaultUrl
- default URL to redirect togetRedirect(String, boolean)
public String getRedirect(String defaultUrl, boolean allowUnsafeRedirect)
getReturnUrl()
, falling back to defaultUrl
if the returnUrl
is
not set. This method clears the returnUrl
. If there are errors, this method returns "ERROR". If the URL
starts with '/' it is interpreted as context-relative.
If allowUnsafeRedirect
is true, this method will not perform validation on the value of returnUrl
or defaultUrl
. This can introduce serious security problems, so use with care. In particular, you
should only use use this method if defaultUrl
has already been sanitised (via whitelisting).
defaultUrl
- default URL to redirect toallowUnsafeRedirect
- whether to allow unsafe redirects (e.g. javascript:
or off-site URLs).forceRedirect(String)
protected String forceRedirect(String redirect)
getRedirect(String)
, which checks that
the redirect URL is safe.redirect
- redirect URLAction.NONE
. It'll just redirect to where you've specifiedgetRedirect(String)
public boolean hasPermission(int permissionsId)
hasGlobalPermission(com.atlassian.jira.permission.GlobalPermissionKey)
instead. Since v6.4.hasPermission
in interface AuthorizationSupport
permissionsId
- the permission typepublic boolean hasGlobalPermission(GlobalPermissionKey globalPermissionKey)
AuthorizationSupport
This method is intended to be used in Java code. If you are using JSP / Velocity / Soy Templates, it is
probably easier to call AuthorizationSupport.hasGlobalPermission(String)
instead.
hasGlobalPermission
in interface AuthorizationSupport
globalPermissionKey
- the permission to checkAuthorizationSupport.hasGlobalPermission(String)
public boolean hasGlobalPermission(String permissionKey)
AuthorizationSupport
This method is intended to be used in JSP / Velocity / Soy Templates. If you are using Java directly, it is
recommended to call AuthorizationSupport.hasGlobalPermission(com.atlassian.jira.permission.GlobalPermissionKey)
instead.
Note that this method takes a Global Permission Key, which is a different value to the old "permission name"
that some previous methods would accept - see GlobalPermissionKey
for correct values of the system
permissions.
hasGlobalPermission
in interface AuthorizationSupport
permissionKey
- the permission to checkAuthorizationSupport.hasGlobalPermission(com.atlassian.jira.permission.GlobalPermissionKey)
public boolean hasIssuePermission(String permissionKey, Issue issue)
AuthorizationSupport
This method is intended for use in Velocity templates / JSPs etc. Within Java code you should prefer the method that takes a ProjectPermissionKey.
Note that this method takes a Permission Key, which is a different value to the old "permission name" that
some previous methods would accept - see ProjectPermissions
for correct
values of the system permissions.
hasIssuePermission
in interface AuthorizationSupport
permissionKey
- the permission key as a Stringissue
- the IssueAuthorizationSupport.hasIssuePermission(com.atlassian.jira.security.plugin.ProjectPermissionKey, com.atlassian.jira.issue.Issue)
public boolean hasIssuePermission(int permissionsId, Issue issue)
AuthorizationSupport
hasIssuePermission
in interface AuthorizationSupport
permissionsId
- the permission typeissue
- the Issuepublic boolean hasIssuePermission(ProjectPermissionKey projectPermissionKey, Issue issue)
AuthorizationSupport
hasIssuePermission
in interface AuthorizationSupport
projectPermissionKey
- the permission to checkissue
- the IssueAuthorizationSupport.hasIssuePermission(String, com.atlassian.jira.issue.Issue)
public boolean hasProjectPermission(int permissionsId, Project project)
hasProjectPermission(com.atlassian.jira.security.plugin.ProjectPermissionKey, com.atlassian.jira.project.Project)
instead. Since v6.4.hasProjectPermission
in interface AuthorizationSupport
permissionsId
- the permission typeproject
- the Projectpublic boolean hasProjectPermission(ProjectPermissionKey projectPermissionKey, Project project)
AuthorizationSupport
hasProjectPermission
in interface AuthorizationSupport
projectPermissionKey
- the permission to checkproject
- the projectpublic boolean isSystemAdministrator()
@Deprecated public boolean isUserExists(String username)
isUserExistsByName(String)
or isUserExistsByKey(String)
instead, as appropriate. Since v6.0.isUserExistsByName(String)
username
- the username to checktrue
if the username is associated with an existing user; false
otherwisepublic boolean isUserExistsByName(String username)
public boolean isUserExistsByKey(String userkey)
public void addErrorCollection(ErrorCollection errors)
ErrorCollection
addErrorCollection
in interface ErrorCollection
errors
- ErrorCollection whose errors/messages we obtain.public void addError(String field, String message, ErrorCollection.Reason reason)
ErrorCollection
addError
in interface ErrorCollection
field
- Field name, eg. "assignee"message
- Error message.reason
- Reason for the error.public void addErrorMessage(String message, ErrorCollection.Reason reason)
ErrorCollection
addErrorMessage
in interface ErrorCollection
message
- Error message.reason
- Reason for the error.public void addReason(ErrorCollection.Reason reason)
ErrorCollection
addReason
in interface ErrorCollection
reason
- a well known reasons why the function has not been performed.public void addReasons(Set<ErrorCollection.Reason> reasons)
ErrorCollection
addReasons
in interface ErrorCollection
reasons
- a set of well known reasons why the function has not been performed.public void setReasons(Set<ErrorCollection.Reason> reasons)
ErrorCollection
setReasons
in interface ErrorCollection
reasons
- a set of well known reasons why the function has not been performed.public Set<ErrorCollection.Reason> getReasons()
ErrorCollection
getReasons
in interface ErrorCollection
public List<String> getSearchSortDescriptions(SearchRequest searchRequest)
public String getNameTranslation(org.ofbiz.core.entity.GenericValue issueConstantGV)
ConstantsManager
instead. Since v6.0.public String getNameTranslation(IssueConstant issueConstant)
ConstantsManager
instead. Since v6.0.public String getDescTranslation(org.ofbiz.core.entity.GenericValue issueConstantGV)
ConstantsManager
instead. Since v6.0.public String getDescTranslation(IssueConstant issueConstant)
ConstantsManager
instead. Since v6.0.public String getReturnUrl()
public String getReturnUrlForCancelLink()
public void setReturnUrl(String returnUrl)
public Collection<String> getFlushedErrorMessages()
ErrorCollection
getFlushedErrorMessages
in interface ErrorCollection
public String getLanguage() throws IOException
IOException
public Project getSelectedProject()
UserProjectHistoryManager.getCurrentProject(int, ApplicationUser)
public Project getSelectedProjectObject()
getSelectedProject()
UserProjectHistoryManager.getCurrentProject(int, ApplicationUser)
public void setSelectedProjectId(Long id)
public String getDateFormat()
public String getDateTimeFormat()
public String getTimeFormat()
public String getWebworkStack(String selected)
selected
- selected value in the webwork stackpublic String getWebworkStack()
public String getServerId()
public JiraServiceContext getJiraServiceContext()
ErrorCollection
.public String htmlEncode(String encodeMe)
encodeMe
- a String to be HTML encoded.public String urlEncode(String encode)
application/x-www-form-urlencoded
format, using the JIRA encoding scheme to
obtain the bytes for unsafe characters.encode
- the String to encodeURLEncoder.encode(String, String)
public boolean isInlineDialogMode()
public void setInline(boolean inline)
inline
- true if the action should act as an inline dialogpublic String returnComplete()
public String getEmptyResponse()
protected final String returnCompleteWithInlineRedirect(String url)
url
- URL to redirect toprotected String returnCompleteWithInlineRedirectAndMsg(String url, String msg, JiraWebActionSupport.MessageType type, boolean closeable, @Nullable String target)
returnCompleteWithInlineRedirect(String)
, and will also populate the response
with the details of a pop-up message to be displayed on the redirected page. An appropriately configured client
side control should perform the displaying of the message.url
- URL to redirect tomsg
- message HTMLtype
- type of message.closeable
- if true, message pop-up has an 'X' button, otherwise pop-up fades away automaticallytarget
- the target to prepend the message pop-up to. If null, the message is shown in a global spotprotected String returnCompleteWithInlineRedirectAndMsg(String url, String msg, String type, boolean closeable, @Nullable String target)
returnCompleteWithInlineRedirectAndMsg(String, String, MessageType, boolean, String)
instead.returnCompleteWithInlineRedirect(String)
, and will also populate the response
with the details of a pop-up message to be displayed on the redirected page. An appropriately configured client
side control should perform the displaying of the message.url
- URL to redirect tomsg
- message HTMLtype
- type of message, see JIRA.Messages.Typescloseable
- if true, message pop-up has an 'X' button, otherwise pop-up fades away automaticallytarget
- the target to prepend the message pop-up to. If null, the message is shown in a global spot@Deprecated protected String returnMsgToUser(String url, String msg, String type, boolean closeable, @Nullable String target)
returnMsgToUser(String, String, MessageType, boolean, String)
instead.returnComplete()
, and will also populate the response
with the details of a pop-up message to be displayed on the redirected page. An appropriately configured client
side control should perform the displaying of the message.url
- URL to redirect to. Not used in dialogsmsg
- message HTMLtype
- type of message, see JIRA.Messages.Typescloseable
- if true, message pop-up has an 'X' button, otherwise pop-up fades away automaticallytarget
- the target to prepend the message pop-up to. If null, the message is shown in a global spotprotected String returnMsgToUser(String url, String msg, JiraWebActionSupport.MessageType type, boolean closeable, @Nullable String target)
returnComplete()
, and will also populate the response
with the details of a pop-up message to be displayed on the redirected page. An appropriately configured client
side control should perform the displaying of the message.url
- URL to redirect to. Not used in dialogsmsg
- message HTMLtype
- type of messagecloseable
- if true, message pop-up has an 'X' button, otherwise pop-up fades away automaticallytarget
- the target to prepend the message pop-up to. If null, the message is shown in a global spotprotected String insertContextPath(String url)
url
- a String containing a URLprotected void addMessageToResponse(String msg, String type, boolean closeable, String target)
msg
- message HTMLtype
- type of message, see JIRA.Messages.Typescloseable
- if true, message pop-up has an 'X' button, otherwise pop-up fades away automaticallytarget
- the target to prepend the message pop-up to. If null, the message is shown in a global spot.protected final boolean hasErrorMessage(String errorMsg)
protected final boolean hasErrorMessageByKey(String errorMsgKey)
protected final void addErrorMessageIfAbsent(String errorMsg)
protected final void addErrorMessageByKeyIfAbsent(String errorMsgKey)
protected void tagMauEventWithApplication(@Nonnull MauApplicationKey applicationKey)
protected void tagMauEventWithProject(Project project)
public final Hint getRandomHint()
public String getConglomerateCookieValue(String cookieName, String key)
cookieName
- The name of the conglomerate cookiekey
- The key of the valuepublic void setConglomerateCookieValue(String cookieName, String key, String value)
cookieName
- The name of the conglomerate cookiekey
- The key of the valuevalue
- The value@Nonnull protected final RedirectSanitiser getRedirectSanitiser()
public Collection<String> getErrorMessages()
ErrorCollection
getErrorMessages
in interface ErrorCollection
getErrorMessages
in class webwork.action.ActionSupport
public Map<String,String> getErrors()
ErrorCollection
getErrors
in interface ErrorCollection
getErrors
in class webwork.action.ActionSupport
Copyright © 2002-2016 Atlassian. All Rights Reserved.