Ian Grunert (Atlassian) avatar Ian Grunert (Atlassian) committed ba42c7b

Handling the happy path, and the authentication required path.

Comments (0)

Files changed (2)

       <version>1.8.5</version>
       <scope>test</scope>
     </dependency>
+      <dependency>
+          <groupId>javax.servlet</groupId>
+          <artifactId>servlet-api</artifactId>
+          <version>2.5</version>
+      </dependency>
   </dependencies>
   <properties>
     <amps.version>3.7</amps.version>

src/main/java/com/example/plugins/tutorial/jira/tabpanels/ConfluenceSpaceTabPanel.java

 import com.atlassian.jira.issue.Issue;
 import com.atlassian.jira.issue.tabpanels.GenericMessageAction;
 import com.atlassian.jira.plugin.issuetabpanel.AbstractIssueTabPanel;
+import com.atlassian.jira.plugin.issuetabpanel.IssueAction;
 import com.atlassian.jira.plugin.issuetabpanel.IssueTabPanel;
+import com.atlassian.jira.util.http.JiraUrl;
+import com.atlassian.jira.web.ExecutingHttpRequest;
 import com.atlassian.sal.api.net.Request;
 import com.atlassian.sal.api.net.Response;
 import com.atlassian.sal.api.net.ResponseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+import webwork.action.ServletActionContext;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
         String confluenceContentType = "page";
         final String spaceKey = entityLink.getKey();
 
-        // Create a request to Confluence's REST API looking for our issue
-        ApplicationLinkRequest request = null;
         try
         {
-            request = requestFactory.createRequest(Request.MethodType.GET, "/rest/prototype/1/search?query=" + query + "&spaceKey=" + spaceKey + "&type=" + confluenceContentType);
+            // Create a request to Confluence's REST API looking for our issue
+            ApplicationLinkRequest request = requestFactory.createRequest(Request.MethodType.GET, "/rest/prototype/1/search?query=" + query + "&spaceKey=" + spaceKey + "&type=" + confluenceContentType);
             String responseBody = request.execute(new ApplicationLinkResponseHandler<String>()
             {
                 public String credentialsRequired(final Response response) throws ResponseException
                 }
             });
 
+// Parse the resulting REST response
+            Document document = parseResponse(responseBody);
+            NodeList results = document.getDocumentElement().getChildNodes();
 
-        } catch (CredentialsRequiredException e)
+            // List of items we will be showing in the tab panel.
+            List<IssueAction> issueActions = new ArrayList<IssueAction>();
+
+            for (int j = 0; j < results.getLength(); j++)
+            {
+                NodeList links = results.item(j).getChildNodes();
+                for (int i = 0; i < links.getLength(); i++)
+                {
+                    Node linkNode = links.item(i);
+                    if ("link".equals(linkNode.getNodeName()))
+                    {
+                        NamedNodeMap attributes = linkNode.getAttributes();
+                        Node type = attributes.getNamedItem("type");
+                        if (type != null && "text/html".equals(type.getNodeValue()))
+                        {
+                            Node href = attributes.getNamedItem("href");
+                            URI uriToConfluencePage = URI.create(href.getNodeValue());
+                            // TODO Should abstract this out into it's own IssueAction and use a templating language for this HTML generation
+                            // To avoid nasty HTML building within Java
+                            // This is beyond the scope of the tutorial, and is left as an exercise for the reader
+                            IssueAction searchResult = new GenericMessageAction(String.format("Reference to Issue found in Confluence page <a target=\"_new\" href=%s>%s</a>", uriToConfluencePage.toString()));
+                            issueActions.add(searchResult);
+                        }
+                    }
+                }
+            }
+            return issueActions;
+        }
+        catch (CredentialsRequiredException e)
+        {
+            // Authorisation needs to be given to access Confluence as this user via UAL
+            // TODO Should abstract this out into it's own IssueAction and use a templating language for this HTML generation
+            // To avoid nasty HTML building within Java
+            // This is beyond the scope of the tutorial, and is left as an exercise for the reader
+            final HttpServletRequest req = ExecutingHttpRequest.get();
+            URI authorisationURI = e.getAuthorisationURI(URI.create(JiraUrl.constructBaseUrl(req) + "/browse/" + issue.getKey()));
+            String message = "You have to authorise this operation first. <a target=\"_new\" href=%s>Please click here and login into the remote application.</a>";
+            IssueAction credentialsRequired = new GenericMessageAction(String.format(message, authorisationURI));
+            return Collections.singletonList(credentialsRequired);
+        }
+        catch (ResponseException e)
         {
             throw new RuntimeException(e);
-        } catch (ResponseException e)
+        }
+        catch (ParserConfigurationException e)
+        {
+            throw new RuntimeException(e);
+        }
+        catch (SAXException e)
+        {
+            throw new RuntimeException(e);
+        }
+        catch (IOException e)
         {
             throw new RuntimeException(e);
         }
-
-        return Collections.singletonList(new GenericMessageAction("This is a message brought to you by the Confluence Space Tab Panel"));
     }
 
     public boolean showPanel(Issue issue, User remoteUser)
     {
         return true;
     }
+
+    private Document parseResponse(String body) throws ParserConfigurationException, IOException, SAXException
+    {
+        // Build a Document for this response for us to walk
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        InputStream is = new ByteArrayInputStream(body.getBytes("UTF-8"));
+        return db.parse(is);
+    }
 }
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.