/* * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * Nuxeo - initial API and implementation * */ package org.nuxeo.runtime.deployment.preprocessor.template; import java.util.LinkedHashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuxeo.common.utils.TextTemplate; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class Template { private static final Log log = LogFactory.getLog(Template.class); public static final String BEGIN = "BEGIN"; public static final String END = "END"; protected static final String JBOSS5_COMPAT = "org.nuxeo.runtme.preprocessing.jboss5"; // we should use a linked hash map to preserve the // insertion order when iterating over the elements in the map final LinkedHashMap<String, Part> parts; /** * Must be removed when fixing deployment-fragment.xml files. */ protected boolean runningOnJBoss5 = false; public Template() { parts = new LinkedHashMap<>(); // XXX compat code String v = System.getProperty(JBOSS5_COMPAT); if (v != null) { runningOnJBoss5 = Boolean.parseBoolean(v); } } public void addPart(String name, String text) { parts.put(name, new Part(name, text)); } public void update(TemplateContribution tc, Map<String, String> ctx) { String content = getContent(tc, ctx); content = new TextTemplate(ctx).processText(content); if (tc.isAppending()) { appendText(tc.getMarker(), content); } else if (tc.isPrepending()) { prependText(tc.getMarker(), content); } else if (tc.isReplacing()) { replaceText(tc.getMarker(), content); } } public void appendText(String marker, String text) { Part part = parts.get(marker); if (part != null) { part.append(text); } else { log.debug("Could not find marker: " + marker); } } public void prependText(String marker, String text) { Part part = parts.get(marker); if (part != null) { part.prepend(text); } else { log.debug("Could not find marker: " + marker); } } public void replaceText(String marker, String text) { Part part = parts.get(marker); if (part != null) { part.replace(text); } else { log.debug("Could not find marker: " + marker); } } public String getText() { StringBuilder buf = new StringBuilder(); for (Part part : parts.values()) { buf.append(part.text); } return buf.toString(); } static class Part { public final String name; // the name of the part used in markers public final StringBuffer text; // the text before the marker public final int offset; // the initial length of the text Part(String name, String text) { this.name = name; this.text = text == null ? new StringBuffer() : new StringBuffer(text); offset = this.text.length(); } public void append(String aText) { text.append(aText); } public void prepend(String aText) { text.insert(offset, aText); } public void replace(String aText) { text.replace(offset, text.length(), aText); } public String getText() { return text.toString(); } public String getName() { return name; } } /* * TODO: Remove the following methods when deployment-fragment.xml files will be fixed. These files must not contain * <module><java>...</java></module> declarations. */ /** * Wrapper method introduced to fix JEE java modules in application template. XXX When this will be solved in trunk * you can remove this method and simply call {@code tc.getContent();}. */ protected String getContent(TemplateContribution tc, Map<String, String> context) { String content = tc.getContent(); if (runningOnJBoss5 && "application".equals(tc.getTemplate()) && "MODULE".equals(tc.getMarker())) { // remove JEE java modules String oldcontent = content; content = removeJavaModules(content); if (oldcontent != content) { log.warn("The deployment-fragment contains illegal JEE java module contribution: " + context.get("bundle.shortName")); } if (content.length() == 0) { return ""; } } return "\n" + content.trim() + "\n"; } protected static final Pattern JAVA_MODULE = Pattern.compile("<\\s*module\\s*>\\s*<\\s*java\\s*>.+<\\s*/\\s*java\\s*>\\s*<\\s*/\\s*module\\s*>"); /** * Remove {@code <module><java>...</java></module>} from {@code application.xml} contributions. This a temporary fix * to remove incorrect java module declarations from deployment-fragments - this should be fixed in each fragment. */ protected static String removeJavaModules(String content) { Matcher m = JAVA_MODULE.matcher(content); if (m.find()) { return m.replaceAll("").trim(); } return content; } }