Commits

Cheryl Jerozal committed 19bfb93

initial commit in this repo

  • Participants

Comments (0)

Files changed (8)

+Hello!
+
+This project is a tutorial for developers learning to write gadgets for JIRA.
+
+You can find the entire tutorial at:
+
+https://developer.atlassian.com/display/JIRADEV/Plugin+Tutorial+-+Writing+Gadgets+for+JIRA
+<?xml version="1.0" encoding="UTF-8"?>
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         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.plugins.tutorial</groupId>
+    <artifactId>jira-gadget-tutorial-plugin</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <name>jira-gadget-tutorial-plugin</name>
+    <description>This is the com.atlassian.plugins.tutorial:jira-gadget-tutorial-plugin plugin for Atlassian JIRA.</description>
+    <packaging>atlassian-plugin</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.atlassian.jira</groupId>
+            <artifactId>jira-api</artifactId>
+            <version>${jira.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>jsr311-api</artifactId>
+            <version>1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.xml.bind</groupId>
+            <artifactId>jaxb-api</artifactId>
+            <version>2.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.atlassian.plugins.rest</groupId>
+            <artifactId>atlassian-rest-common</artifactId>
+            <version>1.0.2</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.3</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.atlassian.sal</groupId>
+            <artifactId>sal-api</artifactId>
+            <version>2.1.beta4</version>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.6</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.8.0</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.atlassian.jira</groupId>
+            <artifactId>jira-func-tests</artifactId>
+            <version>${jira.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>net.jcip</groupId>
+            <artifactId>jcip-annotations</artifactId>
+            <version>1.0</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.atlassian.maven.plugins</groupId>
+                <artifactId>maven-jira-plugin</artifactId>
+                <version>3.0</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <productVersion>${jira.version}</productVersion>
+                    <testResourcesVersion>${jira.version}</testResourcesVersion>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.5</source>
+                    <target>1.5</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <properties>
+        <jira.version>5.0-beta3</jira.version>
+    </properties>
+
+</project>

File src/main/java/com/atlassian/plugins/tutorial/ProjectRepresentation.java

+package com.atlassian.plugins.tutorial;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlElement;
+
+import com.atlassian.jira.project.Project;
+
+import net.jcip.annotations.Immutable;
+
+/**
+ * JAXB representation of a project's information. This can be marshalled as
+ * either JSON or XML, depending on what the client asks for.
+ */
+@Immutable
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement
+public class ProjectRepresentation
+{
+    @XmlElement
+    private Long id;
+
+    @XmlElement
+    private String key;
+
+    @XmlElement
+    private String name;
+
+    @XmlElement
+    private String projectUrl;
+
+    @XmlElement
+    private String projectLead;
+    
+    @XmlElement
+    private String description;
+
+    // This private constructor isn't used by any code, but JAXB requires any
+    // representation class to have a no-args constructor.
+    private ProjectRepresentation()
+    {
+        id = null;
+        key = null;
+        name = null;
+        projectUrl = null;
+        projectLead = null;
+        description = null;
+    }
+
+    /**
+     * Initializes the representation's values to those in the specified
+     * {@code Project}.
+     * @param project the project to use for initialization
+     */
+    public ProjectRepresentation(Project project)
+    {
+        this.id = project.getId();
+        this.key = project.getKey();
+        this.name = project.getName();
+        this.projectUrl = project.getUrl();
+        this.projectLead = project.getLead().getDisplayName();
+        this.description = project.getDescription();
+    }
+
+}

File src/main/java/com/atlassian/plugins/tutorial/ProjectsRepresentation.java

+package com.atlassian.plugins.tutorial;
+
+import java.util.Collection;
+import java.util.HashSet;
+
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlElement;
+
+import net.jcip.annotations.Immutable;
+
+/**
+ * JAXB representation of a group of projects.
+ */
+@Immutable
+@SuppressWarnings("UnusedDeclaration")
+@XmlRootElement
+public class ProjectsRepresentation
+{
+    @XmlElement
+    private Collection<ProjectRepresentation> projects;
+
+    // This private constructor isn't used by any code, but JAXB requires any
+    // representation class to have a no-args constructor.
+    private ProjectsRepresentation()
+    {
+        projects = null;
+    }
+
+    /**
+     * Stores the specified {@code Project}s in this representation.
+     * @param projects the projects to store
+     */
+    public ProjectsRepresentation(Iterable<ProjectRepresentation> projects)
+    {
+        this.projects = new HashSet<ProjectRepresentation>();
+        for (ProjectRepresentation representation : projects)
+        {
+            this.projects.add(representation);
+        }
+    }
+}

File src/main/java/com/atlassian/plugins/tutorial/ProjectsResource.java

+package com.atlassian.plugins.tutorial;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.servlet.http.HttpServletRequest;
+
+import com.atlassian.crowd.embedded.api.User;
+import com.atlassian.jira.project.Project;
+import com.atlassian.jira.security.PermissionManager;
+import com.atlassian.jira.security.Permissions;
+import com.atlassian.jira.user.util.UserUtil;
+import com.atlassian.sal.api.user.UserManager;
+import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
+
+/**
+ * REST resource that provides a list of projects in JSON format.
+ */
+@Path("/projects")
+public class ProjectsResource
+{
+    private UserManager userManager;
+    private PermissionManager permissionManager;
+    private UserUtil userUtil;
+
+    /**
+     * Constructor.
+     * @param userManager a SAL object used to find remote usernames in
+     * Atlassian products
+     * @param userUtil a JIRA object to resolve usernames to JIRA's internal
+     * {@code com.opensymphony.os.User} objects
+     * @param permissionManager the JIRA object which manages permissions
+     * for users and projects
+     */
+    public ProjectsResource(UserManager userManager, UserUtil userUtil,
+                            PermissionManager permissionManager)
+    {
+        this.userManager = userManager;
+        this.userUtil = userUtil;
+        this.permissionManager = permissionManager;
+    }
+
+    /**
+     * Returns the list of projects browsable by the user in the specified
+     * request.
+     * @param request the context-injected {@code HttpServletRequest}
+     * @return a {@code Response} with the marshalled projects
+     */
+    @GET
+    @AnonymousAllowed
+    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
+    public Response getProjects(@Context HttpServletRequest request)
+    {
+        // the request was automatically injected with @Context, so
+        // we can use SAL to extract the username from it
+        String username = userManager.getRemoteUsername(request);
+
+        // get the corresponding com.opensymphony.os.User object for
+        // the request
+        User user = userUtil.getUser(username);
+
+        // retrieve all objects for projects this user has permission to browse
+        Collection<Project> projects =
+                permissionManager.getProjectObjects(Permissions.BROWSE, user);
+
+        // convert the project objects to ProjectRepresentations
+        Collection<ProjectRepresentation> projectRepresentations =
+                new LinkedList<ProjectRepresentation>();
+        for (Project project : projects)
+        {
+            projectRepresentations.add(new ProjectRepresentation(project));
+        }
+        ProjectsRepresentation allProjects =
+                new ProjectsRepresentation(projectRepresentations);
+
+        // return the project representations. JAXB will handle the conversion
+        // to XML or JSON.
+        return Response.ok(allProjects).build();
+    }
+}

File src/main/resources/atlassian-plugin.xml

+<atlassian-plugin key="jira-gadget-tutorial-plugin"
+                  name="JIRA Gadget Tutorial Plugin"
+                  pluginsVersion="2">
+    <!-- Contains plugin metadata. -->
+    <plugin-info>
+        <description>A sample plugin showing how to add a gadget to JIRA.</description>
+        <vendor name="Atlassian" url="http://www.atlassian.com"/>
+        <version>1.0</version>
+        <application-version min="4.0"/>
+    </plugin-info>
+
+    <!--
+        Registers the gadget spec as a plugin module. This allows the gadget to
+        appear in the gadget directory and also allows administrators to
+        disable/enable the gadget.
+     -->
+    <gadget key="tutorial-gadget" name="JIRA Tutorial Gadget" location="gadget.xml"/>
+
+    <!-- Makes the gadget Locale messages available for the gadget's use. -->
+    <resource type="download" name="i18n/ALL_ALL.xml" location="i18n/ALL_ALL.xml">
+        <param name="content-type" value="text/xml; charset=UTF-8"/>
+    </resource>
+
+    <!--
+        Automatically finds all JAX-RS resource classes in the plugin and
+        publishes them.
+     -->
+    <rest key="tutorial-gadget-rest-resources" path="/tutorial-gadget" version="1.0">
+        <description>Provides the REST resource for the project list.</description>
+    </rest>
+
+    <!--
+        Imports the SAL UserManager class from JIRA so it can be used by
+        ProjectsResource.
+     -->
+    <component-import key="userManager" interface="com.atlassian.sal.api.user.UserManager"/>
+</atlassian-plugin>

File src/main/resources/gadget.xml

+<?xml version="1.0" encoding="UTF-8" ?>
+<Module>
+    <ModulePrefs title="__MSG_gadget.title__" directory_title="__MSG_gadget.title__" description="__MSG_gadget.description__">
+        <Optional feature="gadget-directory">
+            <Param name="categories">
+                JIRA
+            </Param>
+        </Optional>
+        <Optional feature="atlassian.util" />
+        <Optional feature="auth-refresh" />
+        <Require feature="views" />
+        <Require feature="settitle"/>
+        <Require feature="oauthpopup" />
+        #oauth
+        <Locale messages="__ATLASSIAN_BASE_URL__/download/resources/jira-gadget-tutorial-plugin/i18n/ALL_ALL.xml"/>
+    </ModulePrefs>
+    <Content type="html" view="profile">
+        <![CDATA[
+        #requireResource("com.atlassian.jira.gadgets:common")
+        #requireResource("com.atlassian.gadgets.publisher:ajs-gadgets")
+        #includeResources()
+        
+        <h1>Hello from the Atlassian Gadget Tutorial!</h1>
+
+        <script type="text/javascript">
+            (function () {
+                var gadget = AJS.Gadget({
+                    baseUrl: "__ATLASSIAN_BASE_URL__",
+                    useOauth: "/rest/gadget/1.0/currentUser",
+                    view: {
+                        template: function(args) {
+                            var gadget = this;
+
+                            var projectList = AJS.$("<ul/>");
+
+                            AJS.$(args.projectData.projects).each(function() {
+                                projectList.append(
+                                    AJS.$("<li/>").append(
+                                        AJS.$("<a/>").attr({
+                                            target: "_parent",
+                                            title: gadgets.util.escapeString(this.key),
+                                            href: "__ATLASSIAN_BASE_URL__" + "/browse/" + this.key
+                                        }).text(this.name)        
+                                    )
+                                );
+                            });
+
+                            gadget.getView().html(projectList);
+                        },
+                        args: [{
+                            key: "projectData",
+                            ajaxOptions: function() {
+                                return {
+                                    url: "/rest/tutorial-gadget/1.0/projects.json"
+                                };
+                            }
+                        }]
+                    }
+                });
+            })();
+        </script>
+        ]]>
+    </Content>
+</Module>

File src/main/resources/i18n/ALL_ALL.xml

+<messagebundle>
+    <msg name="gadget.title">Test JIRA Tutorial Gadget</msg>
+    <msg name="gadget.description">A sample gadget to install into JIRA.</msg>
+</messagebundle>