fr.xebia.confluence.gist.GistMacro.java Source code

Java tutorial

Introduction

Here is the source code for fr.xebia.confluence.gist.GistMacro.java

Source

/**
 * 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();
    }

}