Commits

Wojciech Seliga committed dfd543d

NONE moving code to com.example.plugins.tutorial.jira package as recommended by Sarah after here tech writer review.

Comments (0)

Files changed (11)

+Hello!
+
+This project is a tutorial for developers learning to write a message handler for JIRA.
+
+You can find the entire tutorial at: https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Writing+a+Custom+Message+%28Mail%29+Handler+for+JIRA
 		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
 	<modelVersion>4.0.0</modelVersion>
-	<groupId>com.atlassian.jira.plugins</groupId>
+	<groupId>com.example.plugins.tutorial.jira</groupId>
 	<artifactId>mail-handler-demo</artifactId>
 	<version>1.0-SNAPSHOT</version>
 
 	<organization>
 		<name>Example Company</name>
-		<url>http://www.example.com/</url>
+		<url></url>
 	</organization>
 
-	<name>mail-handler-demo</name>
-	<description>This is the com.atlassian.jira.plugins:mail-handler-demo plugin for Atlassian JIRA.</description>
+	<name>Mail Handler Demo</name>
+	<description>This plugin demonstrates how to add a custom message handler to Atlassian JIRA</description>
 	<packaging>atlassian-plugin</packaging>
 
 	<dependencies>

src/main/java/com/atlassian/jira/plugins/mailhandlerdemo/DemoHandler.java

-package com.atlassian.jira.plugins.mailhandlerdemo;
-
-import com.atlassian.crowd.embedded.api.User;
-import com.atlassian.jira.issue.Issue;
-import com.atlassian.jira.service.util.handler.MessageHandler;
-import com.atlassian.jira.service.util.handler.MessageHandlerContext;
-import com.atlassian.jira.service.util.handler.MessageHandlerErrorCollector;
-import com.atlassian.jira.service.util.handler.MessageUserProcessor;
-import com.atlassian.mail.MailUtils;
-import org.apache.commons.lang.StringUtils;
-
-import java.util.Map;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-
-public class DemoHandler implements MessageHandler {
-	private String issueKey;
-	private final IssueKeyValidator issueKeyValidator;
-	private final MessageUserProcessor messageUserProcessor;
-	public static final String KEY_ISSUE_KEY = "issueKey";
-
-    // we can use dependency injection here too!
-	public DemoHandler(MessageUserProcessor messageUserProcessor, IssueKeyValidator issueKeyValidator) {
-		this.messageUserProcessor = messageUserProcessor;
-		this.issueKeyValidator = issueKeyValidator;
-	}
-
-	@Override
-	public void init(Map<String, String> params, MessageHandlerErrorCollector monitor) {
-		// getting here issue key configured by the user
-		issueKey = params.get(KEY_ISSUE_KEY);
-		if (StringUtils.isBlank(issueKey)) {
-            // this message will be either logged or displayed to the user (if the handler is tested from web UI)
-			monitor.error("Issue key has not been specified ('" + KEY_ISSUE_KEY + "' parameter). This handler will not work correctly.");
-		}
-		issueKeyValidator.validateIssue(issueKey, monitor);
-	}
-
-	@Override
-	public boolean handleMessage(Message message, MessageHandlerContext context) throws MessagingException {
-        // let's again validate the issue key - meanwhile issue could have been deleted, closed, etc..
-		final Issue issue = issueKeyValidator.validateIssue(issueKey, context.getMonitor());
-        if (issue == null) {
-            return false; // returning false means that we were unable to handle this message. It may be either
-            // forwarded to specified address or left in the mail queue (if forwarding not enabled)
-        }
-        // this is a small util method JIRA API provides for us, let's use it.
-		final User sender = messageUserProcessor.getAuthorFromSender(message);
-		if (sender == null) {
-			context.getMonitor().error("Message sender(s) '" + StringUtils.join(MailUtils.getSenders(message), ",")
-					+ "' do not have corresponding users in JIRA. Message will be ignored");
-			return false;
-		}
-		final String body = MailUtils.getBody(message);
-		final StringBuilder commentBody = new StringBuilder(message.getSubject());
-		if (body != null) {
-			commentBody.append("\n").append(StringUtils.abbreviate(body, 100000)); // let trim too long bodies
-		}
-        // thanks to using passed context we don't need to worry about normal run vs. test run - our call
-        // will be dispatched accordingly
-		context.createComment(issue, sender, commentBody.toString(), false);
-		return true; // returning true means that we have handled the message successfully. It means it will be deleted next.
-	}
-}

src/main/java/com/atlassian/jira/plugins/mailhandlerdemo/EditDemoHandlerDetailsWebAction.java

-package com.atlassian.jira.plugins.mailhandlerdemo;
-
-import com.atlassian.configurable.ObjectConfigurationException;
-import com.atlassian.jira.plugins.mail.webwork.AbstractEditHandlerDetailsWebAction;
-import com.atlassian.jira.service.JiraServiceContainer;
-import com.atlassian.jira.service.services.file.AbstractMessageHandlingService;
-import com.atlassian.jira.service.util.ServiceUtils;
-import com.atlassian.jira.util.collect.MapBuilder;
-import com.atlassian.plugin.PluginAccessor;
-
-import java.util.Map;
-
-public class EditDemoHandlerDetailsWebAction extends AbstractEditHandlerDetailsWebAction {
-	private final IssueKeyValidator issueKeyValidator;
-
-	public EditDemoHandlerDetailsWebAction(PluginAccessor pluginAccessor, IssueKeyValidator issueKeyValidator) {
-		super(pluginAccessor);
-		this.issueKeyValidator = issueKeyValidator;
-	}
-
-	private String issueKey;
-
-	public String getIssueKey() {
-		return issueKey;
-	}
-
-    public void setIssueKey(String issueKey) {
-        this.issueKey = issueKey;
-    }
-
-    // this method is called to let us populate our variables (or action state) with current handler settings
-    // managed by associated service (file or mail).
-	@Override
-	protected void copyServiceSettings(JiraServiceContainer jiraServiceContainer) throws ObjectConfigurationException {
-		final String params = jiraServiceContainer.getProperty(AbstractMessageHandlingService.KEY_HANDLER_PARAMS);
-		final Map<String, String> parameterMap = ServiceUtils.getParameterMap(params);
-		issueKey = parameterMap.get(DemoHandler.KEY_ISSUE_KEY);
-	}
-
-
-	@Override
-	protected Map<String, String> getHandlerParams() {
-		return MapBuilder.build(DemoHandler.KEY_ISSUE_KEY, issueKey);
-	}
-
-
-	@Override
-	protected void doValidation() {
-		if (configuration == null) {
-			return; // short-circuit in case we lost session, goes directly to doExecute which redirects user
-		}
-		super.doValidation();
-		issueKeyValidator.validateIssue(issueKey, new WebWorkErrorCollector());
-	}
-
-
-}

src/main/java/com/atlassian/jira/plugins/mailhandlerdemo/IssueKeyValidator.java

-package com.atlassian.jira.plugins.mailhandlerdemo;
-
-import com.atlassian.jira.issue.Issue;
-import com.atlassian.jira.issue.IssueManager;
-import com.atlassian.jira.service.util.handler.MessageHandlerErrorCollector;
-import org.apache.commons.lang.StringUtils;
-
-public class IssueKeyValidator
-{
-	private final IssueManager issueManager;
-
-	public IssueKeyValidator(IssueManager issueManager) {
-		this.issueManager = issueManager;
-	}
-
-	public Issue validateIssue(String issueKey, MessageHandlerErrorCollector collector) {
-		if (StringUtils.isBlank(issueKey)) {
-			collector.error("Issue key has to be defined. Found '" + issueKey + "'" );
-			return null;
-		}
-
-		final Issue issue = issueManager.getIssueObject(issueKey);
-		if (issue == null) {
-			collector.error("Cannot add a comment from mail to issue '" + issueKey + "'. The issue does not exist.");
-			return null;
-		}
-		if (!issueManager.isEditable(issue)) {
-			collector.error("Cannot add a comment from mail to issue '" + issueKey + "'. The issue is not editable.");
-			return null;
-		}
-		return issue;
-	}
-
-}

src/main/java/com/example/plugins/tutorial/jira/mailhandlerdemo/DemoHandler.java

+package com.example.plugins.tutorial.jira.mailhandlerdemo;
+
+import com.atlassian.crowd.embedded.api.User;
+import com.atlassian.jira.issue.Issue;
+import com.atlassian.jira.service.util.handler.MessageHandler;
+import com.atlassian.jira.service.util.handler.MessageHandlerContext;
+import com.atlassian.jira.service.util.handler.MessageHandlerErrorCollector;
+import com.atlassian.jira.service.util.handler.MessageUserProcessor;
+import com.atlassian.mail.MailUtils;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Map;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+
+public class DemoHandler implements MessageHandler {
+	private String issueKey;
+	private final IssueKeyValidator issueKeyValidator;
+	private final MessageUserProcessor messageUserProcessor;
+	public static final String KEY_ISSUE_KEY = "issueKey";
+
+    // we can use dependency injection here too!
+	public DemoHandler(MessageUserProcessor messageUserProcessor, IssueKeyValidator issueKeyValidator) {
+		this.messageUserProcessor = messageUserProcessor;
+		this.issueKeyValidator = issueKeyValidator;
+	}
+
+	@Override
+	public void init(Map<String, String> params, MessageHandlerErrorCollector monitor) {
+		// getting here issue key configured by the user
+		issueKey = params.get(KEY_ISSUE_KEY);
+		if (StringUtils.isBlank(issueKey)) {
+            // this message will be either logged or displayed to the user (if the handler is tested from web UI)
+			monitor.error("Issue key has not been specified ('" + KEY_ISSUE_KEY + "' parameter). This handler will not work correctly.");
+		}
+		issueKeyValidator.validateIssue(issueKey, monitor);
+	}
+
+	@Override
+	public boolean handleMessage(Message message, MessageHandlerContext context) throws MessagingException {
+        // let's again validate the issue key - meanwhile issue could have been deleted, closed, etc..
+		final Issue issue = issueKeyValidator.validateIssue(issueKey, context.getMonitor());
+        if (issue == null) {
+            return false; // returning false means that we were unable to handle this message. It may be either
+            // forwarded to specified address or left in the mail queue (if forwarding not enabled)
+        }
+        // this is a small util method JIRA API provides for us, let's use it.
+		final User sender = messageUserProcessor.getAuthorFromSender(message);
+		if (sender == null) {
+			context.getMonitor().error("Message sender(s) '" + StringUtils.join(MailUtils.getSenders(message), ",")
+					+ "' do not have corresponding users in JIRA. Message will be ignored");
+			return false;
+		}
+		final String body = MailUtils.getBody(message);
+		final StringBuilder commentBody = new StringBuilder(message.getSubject());
+		if (body != null) {
+			commentBody.append("\n").append(StringUtils.abbreviate(body, 100000)); // let trim too long bodies
+		}
+        // thanks to using passed context we don't need to worry about normal run vs. test run - our call
+        // will be dispatched accordingly
+		context.createComment(issue, sender, commentBody.toString(), false);
+		return true; // returning true means that we have handled the message successfully. It means it will be deleted next.
+	}
+}

src/main/java/com/example/plugins/tutorial/jira/mailhandlerdemo/EditDemoHandlerDetailsWebAction.java

+package com.example.plugins.tutorial.jira.mailhandlerdemo;
+
+import com.atlassian.configurable.ObjectConfigurationException;
+import com.atlassian.jira.plugins.mail.webwork.AbstractEditHandlerDetailsWebAction;
+import com.atlassian.jira.service.JiraServiceContainer;
+import com.atlassian.jira.service.services.file.AbstractMessageHandlingService;
+import com.atlassian.jira.service.util.ServiceUtils;
+import com.atlassian.jira.util.collect.MapBuilder;
+import com.atlassian.plugin.PluginAccessor;
+
+import java.util.Map;
+
+public class EditDemoHandlerDetailsWebAction extends AbstractEditHandlerDetailsWebAction {
+	private final IssueKeyValidator issueKeyValidator;
+
+	public EditDemoHandlerDetailsWebAction(PluginAccessor pluginAccessor, IssueKeyValidator issueKeyValidator) {
+		super(pluginAccessor);
+		this.issueKeyValidator = issueKeyValidator;
+	}
+
+	private String issueKey;
+
+	public String getIssueKey() {
+		return issueKey;
+	}
+
+    public void setIssueKey(String issueKey) {
+        this.issueKey = issueKey;
+    }
+
+    // this method is called to let us populate our variables (or action state) with current handler settings
+    // managed by associated service (file or mail).
+	@Override
+	protected void copyServiceSettings(JiraServiceContainer jiraServiceContainer) throws ObjectConfigurationException {
+		final String params = jiraServiceContainer.getProperty(AbstractMessageHandlingService.KEY_HANDLER_PARAMS);
+		final Map<String, String> parameterMap = ServiceUtils.getParameterMap(params);
+		issueKey = parameterMap.get(DemoHandler.KEY_ISSUE_KEY);
+	}
+
+
+	@Override
+	protected Map<String, String> getHandlerParams() {
+		return MapBuilder.build(DemoHandler.KEY_ISSUE_KEY, issueKey);
+	}
+
+
+	@Override
+	protected void doValidation() {
+		if (configuration == null) {
+			return; // short-circuit in case we lost session, goes directly to doExecute which redirects user
+		}
+		super.doValidation();
+		issueKeyValidator.validateIssue(issueKey, new WebWorkErrorCollector());
+	}
+
+
+}

src/main/java/com/example/plugins/tutorial/jira/mailhandlerdemo/IssueKeyValidator.java

+package com.example.plugins.tutorial.jira.mailhandlerdemo;
+
+import com.atlassian.jira.issue.Issue;
+import com.atlassian.jira.issue.IssueManager;
+import com.atlassian.jira.service.util.handler.MessageHandlerErrorCollector;
+import org.apache.commons.lang.StringUtils;
+
+public class IssueKeyValidator
+{
+	private final IssueManager issueManager;
+
+	public IssueKeyValidator(IssueManager issueManager) {
+		this.issueManager = issueManager;
+	}
+
+	public Issue validateIssue(String issueKey, MessageHandlerErrorCollector collector) {
+		if (StringUtils.isBlank(issueKey)) {
+			collector.error("Issue key has to be defined. Found '" + issueKey + "'" );
+			return null;
+		}
+
+		final Issue issue = issueManager.getIssueObject(issueKey);
+		if (issue == null) {
+			collector.error("Cannot add a comment from mail to issue '" + issueKey + "'. The issue does not exist.");
+			return null;
+		}
+		if (!issueManager.isEditable(issue)) {
+			collector.error("Cannot add a comment from mail to issue '" + issueKey + "'. The issue is not editable.");
+			return null;
+		}
+		return issue;
+	}
+
+}

src/main/resources/atlassian-plugin.xml

         <version>${project.version}</version>
         <vendor name="${project.organization.name}" url="${project.organization.url}"/>
     </plugin-info>
-    <resource type="i18n" name="i18n" location="com.atlassian.jira.plugins.mailhandlerdemo.messages"/>
-    <component key="issue-key-validator" class="com.atlassian.jira.plugins.mailhandlerdemo.IssueKeyValidator"/>
+    <resource type="i18n" name="i18n" location="com.example.plugins.tutorial.jira.mailhandlerdemo.messages"/>
+    <component key="issue-key-validator" class="com.example.plugins.tutorial.jira.mailhandlerdemo.IssueKeyValidator"/>
 
     <message-handler i18n-name-key="demohandler.name"
-            key="demoHandler" class="com.atlassian.jira.plugins.mailhandlerdemo.DemoHandler"
+            key="demoHandler" class="com.example.plugins.tutorial.jira.mailhandlerdemo.DemoHandler"
             add-edit-url="/secure/admin/EditDemoHandlerDetails!default.jspa"
             weight="0"/>
 
     <webwork1 key="actions" name="Actions" class="java.lang.Object">
         <actions>
-            <action name="com.atlassian.jira.plugins.mailhandlerdemo.EditDemoHandlerDetailsWebAction"
+            <action name="com.example.plugins.tutorial.jira.mailhandlerdemo.EditDemoHandlerDetailsWebAction"
                     alias="EditDemoHandlerDetails"
                     roles-required="admin">
                 <view name="input">/view/editDemoHandlerDetails.vm</view>

src/main/resources/com/atlassian/jira/plugins/mailhandlerdemo/messages.properties

-demohandler.name=My Demo Mail Handler
-demohandler.issue.key=Issue Key

src/main/resources/com/example/plugins/tutorial/jira/mailhandlerdemo/messages.properties

+demohandler.name=My Demo Mail Handler
+demohandler.issue.key=Issue Key
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.