/** * 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.camel.component.chunk; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; import java.util.Map; import com.x5.template.Chunk; import com.x5.template.Theme; import org.apache.camel.Component; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.Message; import org.apache.camel.component.ResourceEndpoint; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.util.ExchangeHelper; import org.apache.commons.io.IOUtils; import static org.apache.camel.component.chunk.ChunkConstants.CHUNK_ENDPOINT_URI_PREFIX; import static org.apache.camel.component.chunk.ChunkConstants.CHUNK_LAYER_SEPARATOR; import static org.apache.camel.component.chunk.ChunkConstants.CHUNK_RESOURCE_URI; import static org.apache.camel.component.chunk.ChunkConstants.CHUNK_TEMPLATE; /** * Transforms the message using a Chunk template. */ @UriEndpoint(firstVersion = "2.15.0", scheme = "chunk", title = "Chunk", syntax = "chunk:resourceUri", producerOnly = true, label = "transformation") public class ChunkEndpoint extends ResourceEndpoint { private Theme theme; private Chunk chunk; @UriParam(description = "Define the encoding of the body") private String encoding; @UriParam(description = "Define the themes folder to scan") private String themeFolder; @UriParam(description = "Define the themes subfolder to scan") private String themeSubfolder; @UriParam(description = "Define the theme layer to elaborate") private String themeLayer; @UriParam(description = "Define the file extension of the template") private String extension; public ChunkEndpoint() { } public ChunkEndpoint(String endpointUri, Component component, String resourceUri) { super(endpointUri, component, resourceUri); } @Override public boolean isSingleton() { return true; } @Override public ExchangePattern getExchangePattern() { return ExchangePattern.InOut; } @Override protected String createEndpointUri() { return CHUNK_ENDPOINT_URI_PREFIX + getResourceUri(); } @Override public void clearContentCache() { this.chunk = null; super.clearContentCache(); } @Override protected void onExchange(Exchange exchange) throws Exception { boolean fromTemplate; String newResourceUri = exchange.getIn().getHeader(CHUNK_RESOURCE_URI, String.class); if (newResourceUri == null) { String newTemplate = exchange.getIn().getHeader(CHUNK_TEMPLATE, String.class); Chunk newChunk; if (newTemplate == null) { fromTemplate = false; newChunk = getOrCreateChunk(theme, fromTemplate); } else { fromTemplate = true; newChunk = createChunk(new StringReader(newTemplate), theme, fromTemplate); exchange.getIn().removeHeader(CHUNK_TEMPLATE); } // Execute Chunk Map<String, Object> variableMap = ExchangeHelper.createVariableMap(exchange); StringWriter writer = new StringWriter(); newChunk.putAll(variableMap); newChunk.render(writer); writer.flush(); // Fill out message Message out = exchange.getOut(); out.setBody(newChunk.toString()); out.setHeaders(exchange.getIn().getHeaders()); out.setAttachments(exchange.getIn().getAttachments()); } else { exchange.getIn().removeHeader(ChunkConstants.CHUNK_RESOURCE_URI); ChunkEndpoint newEndpoint = getCamelContext().getEndpoint(CHUNK_ENDPOINT_URI_PREFIX + newResourceUri, ChunkEndpoint.class); newEndpoint.onExchange(exchange); } } /** * Create a Chunk template * * @param resourceReader Reader used to get template * @param theme The theme * @return Chunk */ private Chunk createChunk(Reader resourceReader, Theme theme, boolean fromTemplate) throws IOException { ClassLoader oldcl = Thread.currentThread().getContextClassLoader(); try { ClassLoader apcl = getCamelContext().getApplicationContextClassLoader(); if (apcl != null) { Thread.currentThread().setContextClassLoader(apcl); } Chunk newChunk; if (fromTemplate) { newChunk = theme.makeChunk(); String targetString = IOUtils.toString(resourceReader); newChunk.append(targetString); } else { String targetString = IOUtils.toString(resourceReader); newChunk = theme.makeChunk(targetString); } return newChunk; } finally { resourceReader.close(); if (oldcl != null) { Thread.currentThread().setContextClassLoader(oldcl); } } } private Chunk getOrCreateChunk(Theme theme, boolean fromTemplate) throws IOException { if (chunk == null) { chunk = createChunk(new StringReader(getResourceUriExtended()), theme, fromTemplate); } return chunk; } private Theme getOrCreateTheme() throws IOException { if (theme == null) { if (themeFolder == null && themeSubfolder == null) { theme = new Theme(); } else if (themeFolder != null && themeSubfolder == null) { URL url = getCamelContext().getClassResolver().loadResourceAsURL(themeFolder); theme = new Theme(url.getPath(), ""); } else { URL url = getCamelContext().getClassResolver().loadResourceAsURL(themeFolder); theme = new Theme(url.getPath(), themeSubfolder); } if (encoding != null) { theme.setEncoding(encoding); } } return theme; } @Override public String getResourceUri() { String uri = super.getResourceUri(); if (uri != null && (uri.startsWith("/") || uri.startsWith("\\"))) { return uri.substring(1); } else { return uri; } } private String getResourceUriExtended() throws IOException { return themeLayer == null ? getResourceUri() : getResourceUri() + CHUNK_LAYER_SEPARATOR + themeLayer; } public String getEncoding() { return encoding; } public void setEncoding(String encoding) { this.encoding = encoding; } public String getThemeFolder() { return themeFolder; } public void setThemeFolder(String themeFolder) { this.themeFolder = themeFolder; } public String getThemeSubfolder() { return themeSubfolder; } public void setThemeSubfolder(String themeSubfolder) { this.themeSubfolder = themeSubfolder; } public String getThemeLayer() { return themeLayer; } public void setThemeLayer(String themeLayer) { this.themeLayer = themeLayer; } public String getExtension() { return extension; } public void setExtension(String extension) { this.extension = extension; } @Override protected void doStart() throws Exception { super.doStart(); if (theme == null) { theme = getOrCreateTheme(); } } @Override protected void doStop() throws Exception { super.doStop(); // noop } }