PageRenderTime 54ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/groovy/com/onresolve/jira/groovy/CannedScriptRunner.groovy

https://bitbucket.org/sorin/jira-plugin-intellij
Groovy | 308 lines | 217 code | 54 blank | 37 comment | 35 complexity | 481d66ae84deec194ab560829357c784 MD5 | raw file
  1. package com.onresolve.jira.groovy
  2. import com.atlassian.jira.ComponentManager
  3. import com.atlassian.jira.util.BuildUtils
  4. import com.atlassian.jira.util.ErrorCollection
  5. import com.atlassian.jira.util.SimpleErrorCollection
  6. import com.opensymphony.util.TextUtils
  7. import java.util.regex.Matcher
  8. import javax.servlet.ServletRequest
  9. import webwork.action.ServletActionContext
  10. import com.atlassian.jira.project.ProjectManager
  11. class CannedScriptRunner extends GroovyRunner {
  12. private String preview
  13. private ErrorCollection errorCollection
  14. private URL scriptURL
  15. CannedScriptRunner(ScriptManager scriptManager) {
  16. super(scriptManager)
  17. }
  18. public List<String> getScriptArgs(String className) throws Exception {
  19. GroovyClassLoader gcl = getGcl();
  20. List<String> rt = new ArrayList<String>();
  21. def script = gcl.loadClass(className, true, false).newInstance();
  22. return script.getParameters(null)*."Name" ?: []
  23. }
  24. public String getCannedScriptHumanDesc (String className, Map actualArgs, boolean forPreview) throws Exception {
  25. GroovyClassLoader gcl = getGcl();
  26. def script = gcl.loadClass(className, true, false).newInstance();
  27. return script.getDescription(actualArgs, forPreview)
  28. }
  29. public ErrorCollection getValidationErrors (String className, Map actualArgs, boolean forPreview) throws Exception {
  30. GroovyClassLoader gcl = getGcl();
  31. def script = gcl.loadClass(className, true, false).newInstance();
  32. return script.doValidate(actualArgs, forPreview) ?: new SimpleErrorCollection()
  33. }
  34. public Map runCannedScript (String className, Map bindVars) throws Exception {
  35. GroovyClassLoader gcl = getGcl();
  36. // ensure script loaded else need to load, possibly reading a different filename for the class from properties file
  37. // above should alread by be managed by the custom resource loader
  38. Map returnVars = [:]
  39. def script = gcl.loadClass(className, true, false).newInstance();
  40. // hack to get the script manager into test classes
  41. if (script.respondsTo("setScriptManager")) {
  42. script.setScriptManager(scriptManager)
  43. }
  44. returnVars = script.doScript(bindVars);
  45. return returnVars;
  46. }
  47. public Object getScriptDef(String className) {
  48. GroovyClassLoader gcl = getGcl();
  49. try {
  50. def script = gcl.loadClass(className, true, false).newInstance();
  51. URL scriptURL = gcl.resourceLoader.loadGroovySource(className)
  52. setScriptURL(scriptURL)
  53. return script
  54. } catch (Exception e) {
  55. log.warn("Class " + className + " failed to load: " + e.getMessage(), e);
  56. }
  57. null
  58. }
  59. private void mergeParamsWithArgsOBSOLETE(Map<String, Object> bindVars) throws Exception {
  60. List<String> scriptParams = getScriptArgs(getCannedScript());
  61. List<String> scriptArgs = getCannedScriptArgs();
  62. for (int i = 0; i < scriptArgs.size(); i++) {
  63. bindVars.put(scriptParams.get(i), scriptArgs.get(i));
  64. }
  65. }
  66. public List getCannedScripts() {
  67. getCannedScripts(null)
  68. }
  69. public List getCannedScripts(String packageName) {
  70. packageName = packageName ?: "com.onresolve.jira.groovy.canned"
  71. List a = [];
  72. GroovyClassLoader gcl = getGcl();
  73. Properties props = scriptManager.getProperties()
  74. Long currentBuildNumber = BuildUtils.getCurrentBuildNumber() as Long
  75. // dev mode only, to get around reloading issues
  76. // List<String> arrayList = new ArrayList<String>();
  77. // arrayList.add("com/onresolve/jira/groovy/canned/admin/ExampleBuiltinScript.groovy");
  78. // arrayList.add("com/onresolve/jira/groovy/canned/admin/GetUser.groovy");
  79. /*
  80. arrayList.add("com/onresolve/jira/groovy/canned/admin/WontCompile.groovy");
  81. arrayList.add("com/onresolve/jira/groovy/canned/admin/BulkFixResolutions.groovy");
  82. arrayList.add("com/onresolve/jira/groovy/canned/admin/CopyProject.groovy");
  83. arrayList.add("com/onresolve/jira/groovy/canned/admin/RunUnitTests.groovy");
  84. arrayList.add("com/onresolve/jira/groovy/canned/admin/CopyCustomField.groovy");
  85. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/conditions/TestCondition.groovy");
  86. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/conditions/AllSubtasksResolvedCondition.groovy");
  87. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/postfunctions/ResolveParentAfterSubtasks.groovy");
  88. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/postfunctions/FireEventWhen.groovy");
  89. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/postfunctions/CloneIssue.groovy");
  90. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/postfunctions/CreateSubTask.groovy");
  91. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/postfunctions/SendCustomEmail.groovy");
  92. // arrayList.add("com/onresolve/jira/groovy/canned/workflow/postfunctions/FasttrackTransition.groovy");
  93. log.debug ("class forPackage ($packageName): $arrayList")
  94. for (String fileName: arrayList) {
  95. */
  96. // Set<String> forPackage = arrayList;
  97. Set<String> forPackage = PackageScanner.getClassesForPackage(packageName)
  98. // log.debug ("class forPackage ($packageName): $forPackage")
  99. for (String fileName : forPackage) {
  100. // CannedScript i/f is in a different classloader so we can't cast
  101. def scriptDef = null;
  102. try {
  103. boolean isValidForVersion
  104. boolean specificInstructions = false
  105. fileName = fileName.replaceAll(/\.groovy$/, "").replaceAll("/", ".")
  106. List hasValidVersions = props.collect {
  107. Matcher matcher = (it.key =~ /${fileName}\.(\d+)\.to\.(\d+)$/)
  108. if (matcher.matches()) {
  109. specificInstructions = true
  110. Long minVersion = matcher[0][1] as Long
  111. Long maxVersion = matcher[0][2] as Long
  112. return (currentBuildNumber >= minVersion && (maxVersion == 0 || currentBuildNumber <= maxVersion))
  113. }
  114. false
  115. }
  116. isValidForVersion = (!specificInstructions) || hasValidVersions.contains(true)
  117. if (isValidForVersion) {
  118. // this is slow
  119. String className = fileName.replaceAll(/\.groovy$/, "").replaceAll("/", ".")
  120. def clazz = gcl.loadClass(className)
  121. def cannedScrClazz = gcl.loadClass("com.onresolve.jira.groovy.canned.CannedScript")
  122. if (clazz.interfaces.toList().contains(cannedScrClazz)) {
  123. scriptDef = clazz.newInstance()
  124. a.add(scriptDef);
  125. }
  126. }
  127. else {
  128. // log.debug ("File $fileName out of range for this build $currentBuildNumber")
  129. }
  130. } catch (Exception e) {
  131. log.warn("Class " + fileName + " failed to load: " + e.getMessage(), e);
  132. }
  133. }
  134. return a;
  135. }
  136. protected void doValidation() {
  137. // log.debug ("CannedScriptRunner.doValidation");
  138. }
  139. protected String doExecute() {
  140. ComponentManager.getInstance().getWebResourceManager().requireResource("com.onresolve.jira.groovy.groovyrunner:codemirror");
  141. try {
  142. Map<String, Object> bindVars = new HashMap<String, Object>();
  143. if (TextUtils.stringSet(getCannedScript())) {
  144. ServletRequest servletRequest = ServletActionContext.getRequest();
  145. Map paramMap = servletRequest.getParameterMap()
  146. // log.debug ("keyset: " + paramMap*.key)
  147. Map<String,Object> sortedParams = [:] as Map<String,Object>
  148. for (String pKey in paramMap*.key) {
  149. if (pKey.startsWith("cannedScriptArgs_Hidden_")) {
  150. List p = servletRequest.getParameterValues(pKey).toList()
  151. sortedParams.put(pKey.replace("cannedScriptArgs_Hidden_", ""), (p.size() < 2 ? p.first() : p))
  152. }
  153. }
  154. for (String pKey in paramMap*.key) {
  155. if (pKey.startsWith("cannedScriptArgs_") && ! pKey.startsWith("cannedScriptArgs_Hidden_")) {
  156. // log.debug ("Key: $pKey value: " + paramMap.get(pKey))
  157. List p = servletRequest.getParameterValues(pKey).toList()
  158. // log.debug("p: $p")
  159. sortedParams.put(pKey.replace("cannedScriptArgs_", ""), (p.size() < 2 ? p.first() : p))
  160. }
  161. }
  162. // log.debug ("sortedParams: " + sortedParams.sort())
  163. setCannedScriptArgs(sortedParams);
  164. // log.debug("CannedScriptArgs: " + getCannedScriptArgs());
  165. if (TextUtils.stringSet(servletRequest.getParameter("Preview"))) {
  166. setErrorCollection(getValidationErrors(getCannedScript(), getCannedScriptArgs(), true))
  167. if (errorCollection.hasAnyErrors()) {
  168. return ERROR
  169. }
  170. def preview = getCannedScriptHumanDesc(getCannedScript(), getCannedScriptArgs(), true)
  171. setPreview (preview)
  172. }
  173. else if (TextUtils.stringSet(servletRequest.getParameter("Next"))) {
  174. setErrorCollection(getValidationErrors(getCannedScript(), getCannedScriptArgs(), false))
  175. if (errorCollection.hasAnyErrors()) {
  176. return ERROR
  177. }
  178. log.debug(getCannedScriptArgs())
  179. }
  180. else if (TextUtils.stringSet(servletRequest.getParameter("AddListener"))) {
  181. setErrorCollection(getValidationErrors(getCannedScript(), getCannedScriptArgs(), false))
  182. if (errorCollection.hasAnyErrors()) {
  183. return ERROR
  184. }
  185. }
  186. else if (TextUtils.stringSet(servletRequest.getParameter("RunCanned"))) {
  187. setErrorCollection(getValidationErrors(getCannedScript(), getCannedScriptArgs(), false))
  188. if (errorCollection.hasAnyErrors()) {
  189. return ERROR
  190. }
  191. // get param values
  192. // mergeParamsWithArgs(bindVars);
  193. run(getCannedScript(), getCannedScriptArgs());
  194. }
  195. }
  196. else {
  197. return SUCCESS;
  198. }
  199. } catch (Exception e) {
  200. result = e.toString();
  201. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  202. PrintStream ps = new PrintStream(baos);
  203. e.printStackTrace(ps);
  204. setScriptExceptionStackTrace(baos.toString("UTF8"));
  205. log.error("The script failed : " + result, e);
  206. setScriptException(e);
  207. }
  208. return SUCCESS;
  209. }
  210. public void setGcl(GroovyClassLoader gcl) {
  211. this.gcl = gcl;
  212. }
  213. public boolean isAdminPanel() {
  214. return true
  215. }
  216. public String getPreview() {
  217. return preview;
  218. }
  219. public ErrorCollection getErrorCollection() {
  220. return errorCollection
  221. }
  222. public boolean getHasErrors() {
  223. return (errorCollection && errorCollection.getErrorMessages()) as boolean
  224. }
  225. public ErrorCollection setErrorCollection(ErrorCollection errorCollection) {
  226. this.errorCollection = errorCollection
  227. }
  228. public void setPreview(String preview) {
  229. this.preview = preview;
  230. }
  231. public static boolean isCannedScript(String s) {
  232. s.startsWith("com.onresolve.jira.groovy.canned")
  233. }
  234. public void setScriptURL(URL scriptURL) {
  235. this.scriptURL = scriptURL
  236. }
  237. public URL getScriptURL() {
  238. return this.scriptURL
  239. }
  240. public ProjectManager getProjectManager() {
  241. ComponentManager.getInstance().getProjectManager()
  242. }
  243. public boolean isInStringOrList(what, obj) {
  244. if (obj instanceof String) {
  245. what == obj
  246. }
  247. else if (obj instanceof List) {
  248. obj.contains(what)
  249. }
  250. else {
  251. false
  252. }
  253. }
  254. }