PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/swizzle-jiramacro/src/main/java/org/codehaus/swizzle/jiramacro/SwizzleJiraMacro.java

https://gitlab.com/mfriedenhagen/swizzle
Java | 273 lines | 204 code | 46 blank | 23 comment | 20 complexity | 8ac63fed23df943b7943741359611c3a MD5 | raw file
  1. /**
  2. *
  3. * Copyright 2006 David Blevins
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.codehaus.swizzle.jiramacro;
  18. import org.codehaus.swizzle.jirareport.Main;
  19. import com.atlassian.confluence.core.ContentEntityObject;
  20. import com.atlassian.confluence.renderer.PageContext;
  21. import com.atlassian.confluence.renderer.radeox.macros.MacroUtils;
  22. import com.atlassian.renderer.v2.RenderMode;
  23. import com.atlassian.renderer.v2.SubRenderer;
  24. import com.atlassian.renderer.v2.macro.MacroException;
  25. import com.atlassian.renderer.v2.macro.basic.AbstractPanelMacro;
  26. import org.apache.velocity.VelocityContext;
  27. import java.io.ByteArrayOutputStream;
  28. import java.io.CharArrayWriter;
  29. import java.io.File;
  30. import java.io.FileWriter;
  31. import java.io.IOException;
  32. import java.io.PrintStream;
  33. import java.io.PrintWriter;
  34. import java.lang.reflect.InvocationTargetException;
  35. import java.net.MalformedURLException;
  36. import java.net.URL;
  37. import java.security.MessageDigest;
  38. import java.security.NoSuchAlgorithmException;
  39. import java.util.Iterator;
  40. import java.util.Map;
  41. import java.util.WeakHashMap;
  42. /**
  43. * @version $Revision$ $Date$
  44. */
  45. public class SwizzleJiraMacro extends AbstractPanelMacro {
  46. private WeakHashMap cache = new WeakHashMap();
  47. private long timeToLive = (60 * 60 * 1000); // 1 hour
  48. public static class Key {
  49. private static MessageDigest md;
  50. static {
  51. try {
  52. md = MessageDigest.getInstance("SHA");
  53. } catch (NoSuchAlgorithmException e) {
  54. throw new IllegalStateException(e);
  55. }
  56. }
  57. private final byte[] digest;
  58. private final int hash;
  59. public Key(String body) {
  60. hash = body.hashCode();
  61. digest = md.digest(body.getBytes());
  62. }
  63. public boolean equals(Object o) {
  64. if (this == o) return true;
  65. if (o == null || getClass() != o.getClass()) return false;
  66. final Key key = (Key) o;
  67. return MessageDigest.isEqual(digest, key.digest);
  68. }
  69. public int hashCode() {
  70. return hash;
  71. }
  72. }
  73. public static class Entry {
  74. private final String content;
  75. private final long created;
  76. public Entry(String content) {
  77. this.content = content;
  78. this.created = System.currentTimeMillis();
  79. }
  80. public boolean isTimedOut(long timeOut) {
  81. return created + timeOut < System.currentTimeMillis();
  82. }
  83. public String getContent() {
  84. return content;
  85. }
  86. public long getCreated() {
  87. return created;
  88. }
  89. }
  90. public static class PageCache {
  91. private final String name;
  92. private final int version;
  93. private final WeakHashMap cache = new WeakHashMap();
  94. public PageCache(String name, int version) {
  95. this.name = name;
  96. this.version = version;
  97. }
  98. public String getName() {
  99. return name;
  100. }
  101. public int getVersion() {
  102. return version;
  103. }
  104. public WeakHashMap getCache() {
  105. return cache;
  106. }
  107. }
  108. private synchronized WeakHashMap getCache(ContentEntityObject page) {
  109. String name = page.getNameForComparison();
  110. PageCache pageCache = (PageCache) cache.get(name);
  111. if (pageCache == null) {
  112. pageCache = new PageCache(name, page.getVersion());
  113. cache.put(name, pageCache);
  114. } else if (pageCache.getVersion() < page.getVersion()) {
  115. pageCache.getCache().clear();
  116. pageCache = new PageCache(name, page.getVersion());
  117. cache.put(name, pageCache);
  118. }
  119. return pageCache.getCache();
  120. }
  121. public String execute(Map params, String body, com.atlassian.renderer.RenderContext renderContext) throws MacroException {
  122. PageContext pageContext = (PageContext) renderContext;
  123. ContentEntityObject entity = pageContext.getEntity();
  124. // One cache per page, one synchronized block to get it
  125. // this would affect read/writes on all pages
  126. WeakHashMap cache = getCache(entity);
  127. // Now that we have the cache for just this page,
  128. // synchronized on it and do our work.
  129. synchronized (cache) {
  130. Key key = new Key(body);
  131. Entry entry = (Entry) cache.get(key);
  132. if (entry != null && !entry.isTimedOut(timeToLive)) {
  133. return entry.getContent();
  134. }
  135. String content = generateContent(params, body, renderContext);
  136. cache.put(key, new Entry(content));
  137. return content;
  138. }
  139. }
  140. private String generateContent(Map params, String body, com.atlassian.renderer.RenderContext renderContext) throws MacroException {
  141. URL templateUrl = null;
  142. try {
  143. String url = (String) params.get("template");
  144. if (url != null) {
  145. templateUrl = new URL(url);
  146. }
  147. } catch (MalformedURLException e) {
  148. e.printStackTrace();
  149. return "Invalid template url: " + e.getMessage();
  150. }
  151. File tempFile = null;
  152. String content = body;
  153. String template;
  154. if (templateUrl != null) {
  155. template = templateUrl.toExternalForm();
  156. } else {
  157. try {
  158. tempFile = File.createTempFile("swizzlejira", ".vm");
  159. FileWriter fileWriter = new FileWriter(tempFile);
  160. fileWriter.write(content);
  161. fileWriter.flush();
  162. fileWriter.close();
  163. template = tempFile.getAbsolutePath();
  164. } catch (IOException e) {
  165. throw new MacroException("Unable to save template content to temp file.", e);
  166. }
  167. }
  168. PrintStream out = null;
  169. ByteArrayOutputStream baos = null;
  170. try {
  171. baos = new ByteArrayOutputStream();
  172. out = new PrintStream(baos);
  173. Map defaults = MacroUtils.defaultVelocityContext();
  174. for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) {
  175. Map.Entry entry = (Map.Entry) iterator.next();
  176. defaults.put(entry.getKey(), entry.getValue());
  177. }
  178. VelocityContext context = new VelocityContext(defaults);
  179. context.put("as", new IssuesUtil());
  180. Main.generate(context, template, out);
  181. } catch (Throwable e) {
  182. if (e instanceof InvocationTargetException) {
  183. InvocationTargetException ite = (InvocationTargetException) e;
  184. e = ite.getCause();
  185. }
  186. CharArrayWriter trace = new CharArrayWriter();
  187. PrintWriter writer = new PrintWriter(trace);
  188. writer.println("Template: " + template);
  189. e.printStackTrace(writer);
  190. writer.flush();
  191. writer.close();
  192. String error = new String(trace.toCharArray());
  193. return error.replaceAll("\n", "<br>");
  194. }
  195. try {
  196. out.flush();
  197. out.close();
  198. tempFile.delete();
  199. } catch (Exception e) {
  200. e.printStackTrace();
  201. }
  202. SubRenderer subRenderer = getSubRenderer();
  203. String velocityOutput = new String(baos.toByteArray());
  204. return subRenderer.render(velocityOutput, renderContext);
  205. }
  206. public String getName() {
  207. return "swizzlejira";
  208. }
  209. protected String getPanelContentCSSClass() {
  210. return "jirareportContent";
  211. }
  212. protected String getPanelCSSClass() {
  213. return "jirareport";
  214. }
  215. protected String getPanelHeaderCSSClass() {
  216. return "jirareportHeader";
  217. }
  218. public RenderMode getBodyRenderMode() {
  219. return RenderMode.allow(RenderMode.F_NONE);
  220. }
  221. public boolean suppressMacroRenderingDuringWysiwyg() {
  222. return false;
  223. }
  224. protected SubRenderer getSubRenderer() {
  225. return super.getSubRenderer();
  226. }
  227. }