pt.webdetails.cte.editor.ace.ProcessedHtmlPage.java Source code

Java tutorial

Introduction

Here is the source code for pt.webdetails.cte.editor.ace.ProcessedHtmlPage.java

Source

/*!
* Copyright 2002 - 2015 Webdetails, a Pentaho company.  All rights reserved.
*
* This software was developed by Webdetails and is provided under the terms
* of the Mozilla Public License, Version 2.0, or any later version. You may not use
* this file except in compliance with the license. If you need a copy of the license,
* please go to  http://mozilla.org/MPL/2.0/. The Initial Developer is Webdetails.
*
* Software distributed under the Mozilla Public License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to
* the license for the specific language governing your rights and limitations.
*/
package pt.webdetails.cte.editor.ace;

import net.htmlparser.jericho.Attributes;
import net.htmlparser.jericho.HTMLElementName;
import net.htmlparser.jericho.OutputDocument;
import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.StartTag;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import pt.webdetails.cpf.context.api.IUrlProvider;
import pt.webdetails.cpf.packager.origin.PathOrigin;
import pt.webdetails.cpf.repository.api.IContentAccessFactory;
import pt.webdetails.cpf.utils.MimeTypes;
import pt.webdetails.cpf.utils.Pair;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Pattern;

/**
 * Serves a pre-processed webpage.
 * Updates URLs so a page can be serviced outside its location.
 * Also allows to inject simple javascript assignments.
 */
public abstract class ProcessedHtmlPage {

    private static Log log = LogFactory.getLog(ProcessedHtmlPage.class);
    protected static final Pattern URL_PROTOCOL = Pattern.compile("^\\w*\\:");

    private static final String CODE_SNIPPET_START_TAG = String.format("<script type=\"%s\">\n",
            MimeTypes.JAVASCRIPT);
    private static final String CODE_SNIPPET_END_TAG = "\n</script>\n";

    private IUrlProvider urlProvider;
    private IContentAccessFactory access;

    protected ProcessedHtmlPage(IUrlProvider urlProvider, IContentAccessFactory access) {
        this.urlProvider = urlProvider;
        this.access = access;
    }

    private IUrlProvider getUrlProvider() {
        return urlProvider;
    }

    private IContentAccessFactory getRepo() {
        return access;
    }

    protected String processPage(PathOrigin baseDir, String pagePath) throws IOException {

        long start = System.currentTimeMillis();
        InputStream file = null;
        try {
            file = baseDir.getReader(getRepo()).getFileInputStream(pagePath);
            Source html = new Source(file);
            OutputDocument outDoc = new OutputDocument(html);
            // transform
            modifyDocument(html, baseDir, outDoc);
            return outDoc.toString();
        } finally {
            IOUtils.closeQuietly(file);
            if (log.isDebugEnabled()) {
                log.debug(String.format("processPage for %s took %dms", pagePath,
                        System.currentTimeMillis() - start));
            }
        }

    }

    /**
     * Updates relative source attributes to externally accessible abs paths
     * @param html the document
     * @param baseDir html location
     * @param out processed document
     */
    protected void modifyDocument(Source html, PathOrigin baseDir, OutputDocument out) {
        replaceUrlAttribute(html.getAllStartTags(HTMLElementName.LINK), "href", baseDir, out);
        replaceUrlAttribute(html.getAllStartTags(HTMLElementName.SCRIPT), "src", baseDir, out);
        replaceUrlAttribute(html.getAllStartTags(HTMLElementName.IMG), "src", baseDir, out);
        //int insertPos = html.getFirstElement( HTMLElementName.HEAD ).getEndTag().getBegin();
        //out.insert( insertPos, getCodeSnippet( getBackendAssignments( getUrlProvider() ) ) );
    }

    /**
     * Will be added in a code snippet at the end of the HEAD element.
     */
    protected abstract Iterable<Pair<String, String>> getBackendAssignments(IUrlProvider urlProvider);

    protected String getCodeSnippet(Iterable<Pair<String, String>> assignments) {
        StringBuilder element = new StringBuilder(CODE_SNIPPET_START_TAG);
        for (Pair<String, String> assignment : assignments) {
            element.append(assignment.first).append(" = ").append(assignment.second).append(";\n");
        }
        element.append(CODE_SNIPPET_END_TAG);
        return element.toString();
    }

    protected boolean shouldProcessPath(String path) {
        // if it is a relative path
        return !StringUtils.isEmpty(path) && !path.startsWith("/") && !URL_PROTOCOL.matcher(path).find();
    }

    protected String processPath(PathOrigin origin, String path, IUrlProvider urlProvider) {
        return normalizeUri(origin.getUrl(path, urlProvider));
    }

    protected int replaceUrlAttribute(Iterable<StartTag> tags, final String pathAttribute, PathOrigin baseDir,
            OutputDocument doc) {
        int count = 0;
        for (StartTag tag : tags) {
            Attributes attr = tag.parseAttributes();
            String path = attr.getValue(pathAttribute);
            if (shouldProcessPath(path)) {
                String newPath = processPath(baseDir, path, getUrlProvider());
                if (log.isTraceEnabled()) { //TODO: trace
                    log.trace(String.format("replaced: in %s@%s \"%s\" --> \"%s\"", tag.getName(), pathAttribute,
                            path, newPath));
                }
                doc.replace(attr, true).put(pathAttribute, newPath);
                count++;
            }
        }
        return count;
    }

    private static String normalizeUri(String path) {
        try {
            URI uri = new URI(path);
            return uri.normalize().getPath();
        } catch (URISyntaxException e) {
            log.error("normalizeUri: cannot process path " + path, e);
            return path;
        }
    }

}