Java tutorial
/** * Copyright 2011 Alexandre Dutra * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * */ package fr.xebia.confluence.gist; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.util.Map; import org.apache.commons.io.IOUtils; import com.atlassian.cache.Cache; import com.atlassian.cache.CacheManager; import com.atlassian.confluence.core.ConfluenceActionSupport; import com.atlassian.confluence.setup.settings.SettingsManager; import com.atlassian.renderer.RenderContext; import com.atlassian.renderer.TokenType; import com.atlassian.renderer.v2.RenderMode; import com.atlassian.renderer.v2.macro.BaseMacro; import com.atlassian.renderer.v2.macro.MacroException; import com.atlassian.renderer.v2.macro.WysiwygBodyType; import com.google.common.io.Closeables; /** * */ public class GistMacro extends BaseMacro { private static final String ID_DEFAULT_PARAM_KEY = "0"; private static final String ID_PARAM_KEY = "id"; private static final String FILE_PARAM_KEY = "file"; private static final String PREFETCH_PARAM_KEY = "prefetch"; private static final String PROXY_HOST_PARAM_KEY = "proxyHost"; private static final String PROXY_PORT_PARAM_KEY = "proxyPort"; private static final String CACHE_KEY = "fr.xebia.confluence.confluence-gist-macro"; private static final String COULD_NOT_FETCH_URL_CONTENTS_ERROR_KEY = "fr.xebia.confluence.confluence-gist-macro.errors.prefetch"; private static final String TRUE = "true"; private static final String SCRIPT_START = "<script src=\""; private static final String SCRIPT_END = "\"></script>"; private CacheManager cacheManager; private SettingsManager settingsManager; public void setCacheManager(CacheManager cacheManager) { this.cacheManager = cacheManager; } public void setSettingsManager(SettingsManager settingsManager) { this.settingsManager = settingsManager; } @Override public RenderMode getBodyRenderMode() { return RenderMode.NO_RENDER; } @Override public TokenType getTokenType(@SuppressWarnings("rawtypes") Map parameters, String body, RenderContext context) { return TokenType.BLOCK; } @Override public WysiwygBodyType getWysiwygBodyType() { return WysiwygBodyType.WIKI_MARKUP; } @Override public boolean hasBody() { return false; } @Override public boolean isInline() { return false; } @Override public boolean suppressMacroRenderingDuringWysiwyg() { return true; } @Override public boolean suppressSurroundingTagDuringWysiwygRendering() { return false; } @Override public String execute(@SuppressWarnings("rawtypes") Map parameters, String body, RenderContext renderContext) throws MacroException { String id; if (parameters.containsKey(ID_PARAM_KEY)) { id = extractMacroParameter(parameters, ID_PARAM_KEY); } else { id = extractMacroParameter(parameters, ID_DEFAULT_PARAM_KEY); } String file = extractMacroParameter(parameters, FILE_PARAM_KEY); StringBuilder gistUrl = createGistUrl(id, file); if (parameters.containsKey(PREFETCH_PARAM_KEY) && TRUE.equals(parameters.get(PREFETCH_PARAM_KEY))) { Cache cache = cacheManager.getCache(CACHE_KEY); String key = getCacheKey(id, file); String contents = (String) cache.get(key); if (contents == null) { String proxyHost = extractMacroParameter(parameters, PROXY_HOST_PARAM_KEY); String proxyPort = extractMacroParameter(parameters, PROXY_PORT_PARAM_KEY); contents = fetchGistUrl(gistUrl.toString(), proxyHost, proxyPort); cache.put(key, contents); } return contents; } else { StringBuilder sb = new StringBuilder(); sb.append(SCRIPT_START); sb.append(gistUrl); sb.append(SCRIPT_END); return sb.toString(); } } private String extractMacroParameter(Map<?, ?> parameters, String key) { return (String) parameters.get(key); } private String fetchGistUrl(String gistUrl, String proxyHost, String proxyPort) throws MacroException { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); InputStream in = null; try { URL url = new URL(gistUrl); URLConnection c; if (proxyHost != null) { int port; if (proxyPort == null) { port = 80; } else { port = Integer.parseInt(proxyPort); } Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, port)); c = url.openConnection(proxy); } else { c = url.openConnection(); } in = c.getInputStream(); IOUtils.copy(in, pw, settingsManager.getGlobalSettings().getDefaultEncoding()); pw.flush(); sw.flush(); return sw.toString(); } catch (IOException e) { String message = ConfluenceActionSupport.getTextStatic(COULD_NOT_FETCH_URL_CONTENTS_ERROR_KEY, new String[] { gistUrl, e.getMessage() }); throw new MacroException(message, e); } finally { Closeables.closeQuietly(pw); Closeables.closeQuietly(sw); Closeables.closeQuietly(in); } } private StringBuilder createGistUrl(String id, String file) { StringBuilder sb = new StringBuilder(); sb.append("https://gist.github.com/"); sb.append(id); sb.append(".js"); if (file != null) { sb.append("?file="); sb.append(file); } return sb; } private String getCacheKey(String id, String file) { StringBuilder sb = new StringBuilder(); sb.append(id); if (file != null) { sb.append("-"); sb.append(file); } return sb.toString(); } }