/LoadSampleData.groovy
Groovy | 438 lines | 346 code | 58 blank | 34 comment | 82 complexity | df460855035196beba784cbd3ad1369b MD5 | raw file
- import com.atlassian.jira.ComponentManager
- import com.atlassian.plugin.PluginAccessor
- import org.springframework.beans.factory.support.*
- import com.atlassian.plugin.osgi.container.OsgiContainerManager
- import org.springframework.context.ApplicationContext
- import org.osgi.framework.Constants
- import com.atlassian.jira.project.ProjectManager
- import com.atlassian.jira.bc.project.ProjectService
- import com.atlassian.jira.bc.project.ProjectService.DeleteProjectValidationResult
- import com.atlassian.jira.util.SimpleErrorCollection
- import org.joda.time.DateTime
- import org.joda.time.Period
- import org.codehaus.jackson.JsonParser
- import org.codehaus.jackson.JsonFactory
- import org.codehaus.jackson.node.ObjectNode
- import org.codehaus.jackson.JsonParser.Feature
- import org.codehaus.jackson.map.ObjectMapper
- import org.apache.commons.httpclient.HttpClient;
- import org.apache.commons.httpclient.methods.GetMethod;
- def componentManager = ComponentManager.getInstance()
- def jiraAuthenticationContext = componentManager.getJiraAuthenticationContext()
- def issueManager = componentManager.getIssueManager()
- def customFieldManager = componentManager.getCustomFieldManager();
- def constantsManager = componentManager.getConstantsManager();
- def user = jiraAuthenticationContext.getUser()
- /*
- * Import options section. Most of these can be overriden with entries in the ghsample -> options
- * object of the JSON
- */
- // Project key to be be put as ${projectKey} in the Velocity template handed to JIM for import
- //
- // If the JSON already includes a project key and name, those will NOT be overridden
- def projectKey = "SCT";
- def projectName = "Scrum Sample";
- // Delete the projectKey project if it exists
- def deleteProjectIfExists = 1;
- // Delete any sprints attached to the issues in an existing project being deleted
- def deleteIssueSprintsIfProjectExists = 1;
- // File to import
- def url = "https://bitbucket.org/nmuldoon/greenhopper-sample-data/raw/master/pomodoroall.json"
- OsgiContainerManager osgiContainerManager = ComponentManager.getComponentInstanceOfType(OsgiContainerManager.class);
- ProjectService projectService = ComponentManager.getComponent(ProjectService.class);
- ProjectManager projectManager = componentManager.getProjectManager();
- def greenhopperContext = GetApplicationContext("com.pyxis.greenhopper.jira");
- if (!greenhopperContext)
- {
- println "Could not find GreenHopper";
- return "NoGreenHopper";
- }
- def sprintManager = greenhopperContext.getBean("sprintManagerImpl");
- PluginAccessor pluginAccessor = componentManager.getPluginAccessor();
- Class sampleDataImporterClass = pluginAccessor.getClassLoader().findClass("com.atlassian.jira.plugins.importer.sample.SampleDataImporter");
- if (!sampleDataImporterClass)
- {
- println "Could not find importer";
- return "No JIM";
- }
- def sampleDataImporter = componentManager.getOSGiComponentInstanceOfType(sampleDataImporterClass);
- if (!sampleDataImporter)
- {
- println "Could not find importer";
- return "No Sample Importer";
- }
- println "Got importer";
- // Grab the JSON file when requested
- def getResponseText(url) {
- def get = new GetMethod(url)
- new HttpClient().executeMethod(get)
- BufferedInputStream bis = new BufferedInputStream(get.getResponseBodyAsStream())
- return bis.getText('UTF-8')
- }
- // Read the JSON input file
- def json
- try {
- json = getResponseText(url);
- } catch (FileNotFoundException) {
- println "File "+url+" not found";
- return "No " + url;
- }
- println "Got JSON";
- // Parse the JSON (stripping the comments in the process)
- ObjectMapper mapper = new ObjectMapper();
- mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
- def jsonNode = mapper.readTree(json);
- println "Parsed JSON";
- // Initialize our velocity template variables
- Map velocityMap = new HashMap();
- // Work out which project we will be importing to
- def jsonProjectKey = jsonNode.path("projects").path(0).path("key").getTextValue();
- if (jsonProjectKey != null && !jsonProjectKey.equals('${projectKey}'))
- {
- println "Project key is included in the JSON, key is " + jsonProjectKey;
- projectKey = jsonProjectKey;
- }
- def jsonProjectName = jsonNode.path("projects").path(0).path("name").getTextValue();
- if (jsonProjectName != null && !jsonProjectName.equals('${projectName}'))
- {
- println "Project name is included in the JSON, name is " + jsonProjectName;
- projectName = jsonProjectName;
- }
- // Get the currenttime that we will use for Sprint creation. We actually add
- // 30 seconds to everything so that the Sprint objects show the Sprint started
- // AFTER the issues joined the Sprint
- def currentTime = DateTime.now().plusSeconds(30);
- // Parse the GreenHopper metadata information from the JSON if it's there
- def ghsampleNode = jsonNode.get("ghsample");
- if (ghsampleNode != null)
- {
- println "Parsing GreenHopper Sample Data information block";
- // Read the options
- def optionsNode = ghsampleNode.get("options");
- if (optionsNode != null && optionsNode.isObject())
- {
- def valueNode = optionsNode.get("deleteProjectIfExists");
- if (valueNode != null)
- {
- deleteProjectIfExists = valueNode.getIntValue();
- println "Option deleteProjectIfExists set to " + deleteProjectIfExists;
- }
-
- valueNode = optionsNode.get("deleteIssueSprintsIfProjectExists");
- if (valueNode != null)
- {
- deleteIssueSprintsIfProjectExists = valueNode.getIntValue();
- println "Option deleteIssueSprintsIfProjectExists set to " + deleteIssueSprintsIfProjectExists;
- }
- }
- // Get the status ids we need to put in to the velocity template
- def statusesNode = ghsampleNode.get("statuses");
- if (statusesNode != null)
- {
- println "Parsing statuses";
- for (statusVar in statusesNode.getFieldNames())
- {
- def statusName = statusesNode.get(statusVar);
- statusVar = statusVar.replaceFirst('^\\$\\{(.*)\\}$', '$1');
- println " " + statusVar + " = " + statusName;
- def status = constantsManager.getStatusByName(statusName.getValueAsText());
- if (!status)
- {
- println "Error: Could not find status " + statusName;
- return "No Status " + statusName;
- }
- else
- {
- println " " + statusVar + " = " + status.getId();
- velocityMap.put(statusVar, status.getId());
- }
- }
- }
- // Get the field ids we need to put in to the velocity template
- def fieldsNode = ghsampleNode.get("fields");
- if (fieldsNode != null)
- {
- println "Parsing fields";
- for (fieldVar in fieldsNode.getFieldNames())
- {
- def fieldName = fieldsNode.get(fieldVar);
- fieldVar = fieldVar.replaceFirst('^\\$\\{(.*)\\}$', '$1');
- println " " + fieldVar + " = " + fieldName;
- // We shouldn't just get any field by name here, if it's a GreenHopper
- // field we need to be sure to get only the GreenHopper one (e.g.
- // only the GreenHopper Story Points/Business Value/Sprint fields)
- def field = customFieldManager.getCustomFieldObjectByName(fieldName.getValueAsText());
- if (!field)
- {
- println "Error: Could not find field " + fieldName;
- return "No field " + fieldName;
- }
- else
- {
- println " " + fieldVar + " = " + field.getId();
- velocityMap.put(fieldVar, field.getId());
- }
- }
- }
- // Create the sprints we need
- def sprintsNode = ghsampleNode.get("sprints");
- if (sprintsNode != null)
- {
- def sprintClass = greenhopperContext.getClassLoader().findClass("com.atlassian.greenhopper.service.sprint.Sprint");
- println "Parsing sprints";
- for (sprintVar in sprintsNode.getFieldNames())
- {
- def sprintDef = sprintsNode.get(sprintVar);
- def sprintBuilder = sprintClass.getDeclaredMethod("builder").invoke(null, null)
- def startDate = currentTime.plus(Period.parse(sprintDef.get("started").getTextValue()));
- def endDate = currentTime.plus(Period.parse(sprintDef.get("ends").getTextValue()));
- def completedDate;
- if (sprintDef.get("completed") != null)
- completedDate = currentTime.plus(Period.parse(sprintDef.get("completed").getTextValue()));
- def sprintName = sprintDef.get("name").getTextValue();
- sprintBuilder.name(sprintName).startDate(startDate).endDate(endDate);
- if (completedDate != null)
- sprintBuilder.completeDate(completedDate).state(sprintBuilder.state.CLOSE);
- else
- sprintBuilder.state(sprintBuilder.state.ACTIVE);
-
- def sprint = sprintBuilder.build();
- print "Building sprint " + sprint;
- def outcome = sprintManager.createSprint(sprint);
- if (!outcome.isValid())
- {
- println "Couldn't create Sprint";
- return "Failed Creating Sprint";
- }
- println "Sprint '" + sprintName + "' created with ID " + outcome.getValue().getId();
-
- sprintVar = sprintVar.replaceFirst('^\\$\\{(.*)\\}$', '$1');
- println " " + sprintVar + " = " + outcome.getValue().getId();
- velocityMap.put(sprintVar, outcome.getValue().getId());
- }
- }
- ((ObjectNode) jsonNode).remove("ghsample");
- println "Removed ghsample node";
- }
- def projectResult = projectService.getProjectByKey(user, projectKey);
- def existingProject;
- if (!projectResult.isValid())
- {
- println "Did not find existing project with key " + projectKey;
- // return;
- }
- else
- {
- existingProject = projectResult.getProject();
- println "Found existing project with key " + projectKey;
- }
- // Look for the project by name too, if there is a different project we're broken
- def projectByName = projectManager.getProjectObjByName(projectName);
- if (projectByName)
- {
- println "Found existing project with name " + projectName;
- if (existingProject != null && projectByName.getId() != existingProject.getId())
- {
- println "Found two different existing projects matching project to import, one with key " + projectKey + ", one with name " + projectName + ", not sure what you want JIM/us to do\n";
- return "Two Projects";
- }
- else if (existingProject == null)
- {
- println "Did not find project by key but did find by name, not sure if you really want me to use/delete it";
- return "Project by name";
- }
- }
- if (deleteProjectIfExists && existingProject)
- {
- println "Got existing project by key, now deleting it";
- if (deleteIssueSprintsIfProjectExists)
- {
- def deleteSprints = [:];
- def sprintField = customFieldManager.getCustomFieldObjectByName("Sprint");
- for (issueId in componentManager.getIssueManager().getIssueIdsForProject(existingProject.getId()))
- {
- def issue = issueManager.getIssueObject(issueId);
- def sprintFieldVal = issue.getCustomFieldValue(sprintField);
- if (sprintFieldVal)
- {
- for (sprintObj in sprintFieldVal)
- {
- println "For issue " + issue.getKey() + " got sprint " + sprintObj.getId();
- if (!deleteSprints.get(sprintObj.getId()))
- deleteSprints[sprintObj.getId()] = sprintObj.getId();
- }
- }
- }
- for (sprint in deleteSprints)
- {
- println "Deleting sprint " + sprint.value;
- def sprintOutcome = sprintManager.getSprint(sprint.value);
- if (sprintOutcome.isValid())
- {
- sprintManager.deleteSprint(sprintOutcome.getValue());
- println "... done";
- }
- }
- }
- errorCollection = new SimpleErrorCollection();
- ProjectService.DeleteProjectValidationResult deleteResult = new ProjectService.DeleteProjectValidationResult(errorCollection, existingProject)
- projectService.deleteProject(user, deleteResult)
- if (!deleteResult.isValid())
- {
- println "Failed deleting project";
- return "Failed Deleting Project";
- }
- println "Deleted project"
- }
- velocityMap.put("loreum", "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
- velocityMap.put("projectKey", projectKey);
- velocityMap.put("projectName", projectName);
- velocityMap.put("currentUser", user.getName());
- // Regenerate the JSON
- StringWriter sw = new StringWriter();
- def jsonWriter = mapper.getJsonFactory().createJsonGenerator(sw);
- jsonWriter.useDefaultPrettyPrinter();
- jsonWriter.writeTree(jsonNode);
- json = sw.toString();
- // println json;
- // Call JIM to create the sample data
- SimpleErrorCollection errorCollection = new SimpleErrorCollection();
- def found = 0;
- for (method in sampleDataImporter.respondsTo("createSampleData"))
- {
- if (method.getParamsCount() < 1 || !method.getNativeParameterTypes()[0].equals(String))
- continue;
- if (method.getParamsCount() == 5 && method.getNativeParameterTypes()[0].equals(String))
- {
- sampleDataImporter.createSampleData(json, velocityMap, null, null, errorCollection);
- found = 1;
- break;
- }
- else if (method.getParamsCount() == 6)
- {
- sampleDataImporter.createSampleData(json, velocityMap, null, null, null, errorCollection);
- found = 1;
- break;
- }
- }
- if (!found)
- {
- println "Found no method to create sample data";
- return "NoMethod";
- }
- if (errorCollection.hasAnyErrors())
- {
- println "Import failed";
- for (error in errorCollection.getErrorMessages())
- println " " + error;
- return "Import Failed";
- }
- // Go through the new project issue by issue and check the Rank field,
- // which will cause the rank to be correctly populated in order of issuekey
- def project = componentManager.getProjectManager().getProjectObjByKey(projectKey);
- if (project)
- {
- def issueKeys = [];
- for (issueId in componentManager.getIssueManager().getIssueIdsForProject(project.getId()))
- {
- def issue = issueManager.getIssueObject(issueId);
- println " Got issue " + issue.getKey();
- issueKeys.push(issue.getKey());
- }
- println issueKeys + " " + issueKeys.getClass().getName();
- println Collections.sort(issueKeys);
- for (issueKey in issueKeys.sort { a,b -> if (a.length() != b.length()) a.length() - b.length() else a.compareTo(b) })
- {
- def issue = issueManager.getIssueObject(issueKey);
- println "Issue " + issueKey + " has rank " + issue.getCustomFieldValue(customFieldManager.getCustomFieldObjectByName("Rank"));
- }
- }
- // Delete any "External Issue ID" field created by JIM
- for (customField in customFieldManager.getCustomFieldObjectsByName("External issue ID"))
- {
- def associatedProjects = customField.getAssociatedProjects();
- if (associatedProjects.size() == 1 && associatedProjects.get(0).getString("key") == projectKey)
- {
- println "Deleting External issue ID field";
- customFieldManager.removeCustomField(customField);
- }
- }
- println "Import completed"
- return "Import Completed";
- def GetApplicationContext(app)
- {
- OsgiContainerManager osgiContainerManager = ComponentManager.getComponentInstanceOfType(OsgiContainerManager.class);
- def appContext;
- osgiContainerManager.getBundles()
- for (bundle in osgiContainerManager.getBundles())
- {
- def bundleContext = bundle.getBundleContext()
- if (bundle.getSymbolicName() != app)
- continue;
- for (service in bundleContext.getServiceReferences(ApplicationContext.class.getName(), null))
- {
- if (service.getProperty("org.springframework.context.service.name") == app)
- {
- appContext = bundleContext.getService(service)
- break;
- }
- }
- break;
- }
- return appContext;
- }