Package org.apache.sling.scripting.jst

Source Code of org.apache.sling.scripting.jst.HtmlCodeGenerator

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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 org.apache.sling.scripting.jst;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.LinkedList;
import java.util.List;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.script.ScriptException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.wrappers.SlingRequestPaths;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.jcr.JsonItemWriter;
import org.cyberneko.html.parsers.DOMParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

/** Generates HTML code for JST templates */
class HtmlCodeGenerator {
    private final List<String> libraryScripts = new LinkedList<String>();
    private final HtmlContentRenderer htmlRenderer;
    private final Logger log = LoggerFactory.getLogger(getClass());

    // TODO should be configurable or synced with the actual location
    public final static String SLING_JS_PATH = "/system/sling.js";

    /** Property names to use to build the page title, in order of preference */
    public final static String [] TITLE_PROPERTY_NAMES = {
        "title",
        "name",
        "description"
    };

    public HtmlCodeGenerator() {
        libraryScripts.add(SLING_JS_PATH);
        htmlRenderer = new HtmlContentRenderer();
    }

    /** Generate HTML code for the given request and script path */
    void generateHtml(SlingHttpServletRequest request, String scriptPath,
            InputStream scriptStream, PrintWriter output)
    throws RepositoryException, JSONException, ScriptException, IOException {

        // access our data (need a Node)
        final Resource r = request.getResource();
        final Node n = r.adaptTo(Node.class);
        final String pageTitle = getTitle(r, n);

        // Parse script using the NekoHTML permissive HTML parser
        final DOMParser parser = new DOMParser();
        try {
            parser.setFeature("http://xml.org/sax/features/namespaces", false);
            parser.setProperty("http://cyberneko.org/html/properties/names/elems", "lower");
            parser.setProperty("http://cyberneko.org/html/properties/names/attrs", "lower");
            parser.parse(new InputSource(scriptStream));
        } catch(Exception e) {
            final ScriptException se = new ScriptException("Error parsing script " + scriptPath);
            se.initCause(e);
            throw se;
        }
        final Document template = parser.getDocument();

        // compute default rendering
        final StringWriter defaultRendering = new StringWriter();
        if(n!=null) {
            final PrintWriter pw = new PrintWriter(defaultRendering);
            htmlRenderer.render(pw, r, n, pageTitle);
            pw.flush();
        }

        // compute currentNode values in JSON format
        final StringWriter jsonData = new StringWriter();
        if(n != null) {
            final PrintWriter pw = new PrintWriter(jsonData);
            final JsonItemWriter j = new JsonItemWriter(null);
            final int maxRecursionLevels = 1;
            pw.print("var currentNode=");
            j.dump(n, pw, maxRecursionLevels);
            pw.print(";");
            pw.flush();
        }

        // run XSLT transform on script, passing parameter
        // for our computed values
        final String xslt = "/xslt/script-transform.xsl";
        InputStream xslTransform = getClass().getResourceAsStream(xslt);
        if(xslTransform == null) {
            throw new ScriptException("XSLT transform " + xslt + " not found");
        }
        try {
            final TransformerFactory tf = TransformerFactory.newInstance();
            final Transformer t = tf.newTransformer(new StreamSource(xslTransform));
            t.setParameter("pageTitle", pageTitle);
            t.setParameter("slingScriptPath", fullPath(request,SLING_JS_PATH));
            t.setParameter("jstScriptPath", fullPath(request, scriptPath + ".jst.js"));
            t.setParameter("defaultRendering", defaultRendering.toString());
            t.setParameter("jsonData", jsonData.toString());
            final Result result = new StreamResult(output);
            final DOMSource source = new DOMSource(template);
            t.transform(source, result);

        } catch (Exception e) {
            final ScriptException se = new ScriptException("Error in XSLT transform for " + scriptPath);
            se.initCause(e);
            throw se;

        } finally {
            xslTransform.close();
        }
    }

    /** Return the full path to supplied resource */
    static String fullPath (SlingHttpServletRequest request, String path) {
        return SlingRequestPaths.getContextPath(request) + SlingRequestPaths.getServletPath(request) + path;
    }

    /** Return the title to use for the generated page */
    protected String getTitle(Resource r, Node n) {
        String title = null;

        if(n != null) {
            for(String name : TITLE_PROPERTY_NAMES) {
                try {
                    if(n.hasProperty(name)) {
                        final String s = n.getProperty(name).getString();
                        if(s.length() > 0) {
                            title = s;
                            break;
                        }
                    }
                } catch(RepositoryException re) {
                    log.warn("RepositoryException in getTitle()", re);
                }
            }
        }

        if(title == null) {
            title = r.getPath();
            if(title.startsWith("/")) {
                title = title.substring(1);
            }
        }

        return title;
    }
}
TOP

Related Classes of org.apache.sling.scripting.jst.HtmlCodeGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.