| /** |
| * 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.mustache; |
| |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.StringWriter; |
| import java.util.Map; |
| |
| import com.github.mustachejava.DefaultMustacheFactory; |
| import com.github.mustachejava.Mustache; |
| import com.github.mustachejava.MustacheFactory; |
| 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 static org.apache.camel.component.mustache.MustacheConstants.MUSTACHE_ENDPOINT_URI_PREFIX; |
| import static org.apache.camel.component.mustache.MustacheConstants.MUSTACHE_RESOURCE_URI; |
| import static org.apache.camel.component.mustache.MustacheConstants.MUSTACHE_TEMPLATE; |
| |
| /** |
| * Transforms the message using a Mustache template. |
| */ |
| @UriEndpoint(scheme = "mustache", title = "Mustache", syntax = "mustache:resourceUri", producerOnly = true, label = "transformation") |
| public class MustacheEndpoint extends ResourceEndpoint { |
| |
| private MustacheFactory mustacheFactory; |
| private Mustache mustache; |
| @UriParam |
| private String encoding; |
| @UriParam(defaultValue = "{{") |
| private String startDelimiter; |
| @UriParam(defaultValue = "}}") |
| private String endDelimiter; |
| |
| public MustacheEndpoint() { |
| } |
| |
| public MustacheEndpoint(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 MUSTACHE_ENDPOINT_URI_PREFIX + getResourceUri(); |
| } |
| |
| @Override |
| public void clearContentCache() { |
| this.mustache = null; |
| super.clearContentCache(); |
| } |
| |
| @Override |
| protected void onExchange(Exchange exchange) throws Exception { |
| String newResourceUri = exchange.getIn().getHeader(MUSTACHE_RESOURCE_URI, String.class); |
| if (newResourceUri == null) { |
| // Get Mustache |
| String newTemplate = exchange.getIn().getHeader(MUSTACHE_TEMPLATE, String.class); |
| Mustache newMustache; |
| if (newTemplate == null) { |
| newMustache = getOrCreateMustache(); |
| } else { |
| newMustache = createMustache(new StringReader(newTemplate), "mustache:temp#" + newTemplate.hashCode()); |
| exchange.getIn().removeHeader(MUSTACHE_TEMPLATE); |
| } |
| |
| // Execute Mustache |
| Map<String, Object> variableMap = ExchangeHelper.createVariableMap(exchange); |
| StringWriter writer = new StringWriter(); |
| newMustache.execute(writer, variableMap); |
| writer.flush(); |
| |
| // Fill out message |
| Message out = exchange.getOut(); |
| out.setBody(writer.toString()); |
| out.setHeaders(exchange.getIn().getHeaders()); |
| out.setAttachments(exchange.getIn().getAttachments()); |
| } else { |
| exchange.getIn().removeHeader(MustacheConstants.MUSTACHE_RESOURCE_URI); |
| MustacheEndpoint newEndpoint = getCamelContext().getEndpoint(MUSTACHE_ENDPOINT_URI_PREFIX + newResourceUri, MustacheEndpoint.class); |
| newEndpoint.onExchange(exchange); |
| } |
| } |
| |
| /** |
| * Read and compile a Mustache template |
| * |
| * @param resourceReader Reader used to get template |
| * @param resourceUri Template Id |
| * @return Template |
| */ |
| private Mustache createMustache(Reader resourceReader, String resourceUri) throws IOException { |
| ClassLoader oldcl = Thread.currentThread().getContextClassLoader(); |
| try { |
| ClassLoader apcl = getCamelContext().getApplicationContextClassLoader(); |
| if (apcl != null) { |
| Thread.currentThread().setContextClassLoader(apcl); |
| } |
| Mustache newMustache; |
| if (startDelimiter != null && endDelimiter != null && mustacheFactory instanceof DefaultMustacheFactory) { |
| DefaultMustacheFactory defaultMustacheFactory = (DefaultMustacheFactory) mustacheFactory; |
| newMustache = defaultMustacheFactory.compile(resourceReader, resourceUri, startDelimiter, endDelimiter); |
| } else { |
| newMustache = mustacheFactory.compile(resourceReader, resourceUri); |
| } |
| return newMustache; |
| } finally { |
| resourceReader.close(); |
| if (oldcl != null) { |
| Thread.currentThread().setContextClassLoader(oldcl); |
| } |
| } |
| } |
| |
| private Mustache getOrCreateMustache() throws IOException { |
| if (mustache == null) { |
| mustache = createMustache(getResourceAsReader(), getResourceUri()); |
| } |
| return mustache; |
| } |
| |
| @Override |
| public String getResourceUri() { |
| // do not have leading slash as mustache cannot find the resource, as that entails classpath root |
| String uri = super.getResourceUri(); |
| if (uri != null && (uri.startsWith("/") || uri.startsWith("\\"))) { |
| return uri.substring(1); |
| } else { |
| return uri; |
| } |
| } |
| |
| public MustacheFactory getMustacheFactory() { |
| return mustacheFactory; |
| } |
| |
| /** |
| * To use a custom {@link MustacheFactory} |
| */ |
| public void setMustacheFactory(MustacheFactory mustacheFactory) { |
| this.mustacheFactory = mustacheFactory; |
| } |
| |
| public String getEncoding() { |
| return encoding; |
| } |
| |
| /** |
| * Character encoding of the resource content. |
| */ |
| public void setEncoding(String encoding) { |
| this.encoding = encoding; |
| } |
| |
| private Reader getResourceAsReader() throws IOException { |
| return encoding == null |
| ? new InputStreamReader(getResourceAsInputStream()) |
| : new InputStreamReader(getResourceAsInputStream(), encoding); |
| } |
| |
| public String getStartDelimiter() { |
| return startDelimiter; |
| } |
| |
| /** |
| * Characters used to mark template code beginning. |
| */ |
| public void setStartDelimiter(String startDelimiter) { |
| this.startDelimiter = startDelimiter; |
| } |
| |
| public String getEndDelimiter() { |
| return endDelimiter; |
| } |
| |
| /** |
| * Characters used to mark template code end. |
| */ |
| public void setEndDelimiter(String endDelimiter) { |
| this.endDelimiter = endDelimiter; |
| } |
| |
| } |