001/* 002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Florent Guillaume 016 */ 017package org.nuxeo.apidoc.documentation; 018 019import java.util.LinkedList; 020 021import org.apache.commons.lang.StringUtils; 022import org.nuxeo.ecm.platform.htmlsanitizer.HtmlSanitizerService; 023import org.nuxeo.runtime.api.Framework; 024 025/** 026 * Helper to generate HTML for documentation strings. 027 */ 028public class DocumentationHelper { 029 030 private static final String BR = "<br/>"; 031 032 private static final String BR2 = "<br />"; 033 034 private static final String BR3 = "<br>"; 035 036 private static final String P = "<p/>"; 037 038 private static final String P2 = "<p />"; 039 040 // private static final String CODE_START = "<div class=\"code\"><pre>"; 041 private static final String CODE_START = "<code><pre>"; 042 043 // private static final String CODE_END = "</pre></div>"; 044 private static final String CODE_END = "</pre></code>"; 045 046 private static final String AUTHOR = "@author"; 047 048 // utility class 049 private DocumentationHelper() { 050 } 051 052 /** 053 * Transforms Nuxeo extension point {@code <documentation>} content into HTML. 054 * <p> 055 * <ul> 056 * <li>standalone newlines are turned into {@code <br/>}</li> 057 * <li>{@code <code>} blocks are turned into a {@code <div class="code">} with a {@code <pre>}</li> 058 * <li>{@code @author} blocks are removed</li> 059 * </ul> 060 */ 061 public static String getHtml(String doc) { 062 if (doc == null) { 063 return ""; 064 } 065 HtmlSanitizerService sanitizer = Framework.getService(HtmlSanitizerService.class); 066 if (sanitizer == null && !Framework.isTestModeSet()) { 067 throw new RuntimeException("Cannot find HtmlSanitizerService"); 068 } 069 070 LinkedList<String> lines = new LinkedList<String>(); 071 lines.add(P); 072 boolean newline = true; 073 boolean firstcode = false; 074 boolean code = false; 075 for (String line : doc.split("\n")) { 076 if (!code) { 077 line = line.trim(); 078 if ("".equals(line) || BR.equals(line) || BR2.equals(line) || BR3.equals(line) || P.equals(line) 079 || P2.equals(line)) { 080 if (!newline) { 081 lines.add(P); 082 newline = true; 083 } 084 } else { 085 if ("<code>".equals(line)) { 086 code = true; 087 firstcode = true; 088 line = CODE_START; 089 if (!newline) { 090 line = P + line; 091 } 092 lines.add(line); 093 newline = false; 094 } else if (line.startsWith(AUTHOR)) { 095 if (!newline) { 096 lines.add(P); 097 } 098 newline = true; 099 } else { 100 lines.add(line); 101 newline = false; 102 } 103 } 104 } else { // code 105 if ("</code>".equals(line.trim())) { 106 code = false; 107 line = CODE_END + P; 108 newline = true; 109 } else { 110 line = line.replace("&", "&").replace("<", "<"); 111 } 112 if (firstcode) { 113 // don't add a \n at the start of the code 114 firstcode = false; 115 line = lines.removeLast() + line; 116 } 117 lines.add(line); 118 } 119 } 120 if (code) { 121 lines.add(CODE_END); 122 } 123 String html = StringUtils.join(lines, "\n"); 124 if (sanitizer != null) { 125 html = sanitizer.sanitizeString(html, null); 126 } 127 return secureXML(html); 128 } 129 130 /** 131 * Makes sure no passwords are embedded in the XML. 132 */ 133 public static String secureXML(String xml) { 134 if (xml == null || !xml.contains("assword")) { 135 return xml; 136 } 137 xml = xml.replaceAll("<([a-zA-Z]*[pP])assword>[^<]*</([a-zA-Z]*)assword>", "<$1assword>********</$2assword>"); 138 // attributes: nuxeo-core-auth 139 xml = xml.replaceAll("([a-zA-Z]*[pP])assword=\"[^\"]*\"", "$1assword=\"********\""); 140 // property: default-repository-config 141 xml = xml.replaceAll("([a-zA-Z]*[pP])assword\">[^<]*<", "$1assword\">********<"); 142 return xml; 143 } 144 145}