001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.component.language; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.io.UnsupportedEncodingException; 022import java.net.URLEncoder; 023 024import org.apache.camel.Component; 025import org.apache.camel.Consumer; 026import org.apache.camel.Expression; 027import org.apache.camel.Processor; 028import org.apache.camel.Producer; 029import org.apache.camel.RuntimeCamelException; 030import org.apache.camel.component.ResourceEndpoint; 031import org.apache.camel.spi.Language; 032import org.apache.camel.spi.Metadata; 033import org.apache.camel.spi.UriEndpoint; 034import org.apache.camel.spi.UriParam; 035import org.apache.camel.spi.UriPath; 036import org.apache.camel.util.IOHelper; 037import org.apache.camel.util.ObjectHelper; 038import org.apache.camel.util.ResourceHelper; 039 040/** 041 * Language endpoint. 042 * 043 * @version 044 */ 045@UriEndpoint(scheme = "language", title = "Language", syntax = "language:languageName:resourceUri", producerOnly = true, label = "core,script") 046public class LanguageEndpoint extends ResourceEndpoint { 047 private Language language; 048 private Expression expression; 049 private boolean contentResolvedFromResource; 050 @UriPath(enums = "bean,constant,el,exchangeProperty,file,groovy,header,javascript,jsonpath,jxpath,mvel,ognl,php,python" 051 + ",ref,ruby,simple,spel,sql,terser,tokenize,xpath,xquery,xtokenize") 052 @Metadata(required = "true") 053 private String languageName; 054 // resourceUri is optional in the language endpoint 055 @UriPath(description = "Path to the resource, or a reference to lookup a bean in the Registry to use as the resource") 056 @Metadata(required = "false") 057 private String resourceUri; 058 @UriParam 059 private String script; 060 @UriParam(defaultValue = "true") 061 private boolean transform = true; 062 @UriParam 063 private boolean binary; 064 @UriParam 065 private boolean cacheScript; 066 067 public LanguageEndpoint() { 068 // enable cache by default 069 setContentCache(true); 070 } 071 072 public LanguageEndpoint(String endpointUri, Component component, Language language, Expression expression, String resourceUri) { 073 super(endpointUri, component, resourceUri); 074 this.language = language; 075 this.expression = expression; 076 // enable cache by default 077 setContentCache(true); 078 } 079 080 public Producer createProducer() throws Exception { 081 ObjectHelper.notNull(getCamelContext(), "CamelContext", this); 082 083 if (language == null && languageName != null) { 084 language = getCamelContext().resolveLanguage(languageName); 085 } 086 087 ObjectHelper.notNull(language, "language", this); 088 if (cacheScript && expression == null && script != null) { 089 script = resolveScript(script); 090 expression = language.createExpression(script); 091 } 092 093 return new LanguageProducer(this); 094 } 095 096 public Consumer createConsumer(Processor processor) throws Exception { 097 throw new RuntimeCamelException("Cannot consume to a LanguageEndpoint: " + getEndpointUri()); 098 } 099 100 /** 101 * Resolves the script. 102 * 103 * @param script script or uri for a script to load 104 * @return the script 105 * @throws IOException is thrown if error loading the script 106 */ 107 protected String resolveScript(String script) throws IOException { 108 String answer; 109 if (ResourceHelper.hasScheme(script)) { 110 InputStream is = loadResource(script); 111 answer = getCamelContext().getTypeConverter().convertTo(String.class, is); 112 IOHelper.close(is); 113 } else { 114 answer = script; 115 } 116 117 return answer; 118 } 119 120 public boolean isSingleton() { 121 return true; 122 } 123 124 @Override 125 protected String createEndpointUri() { 126 String s = script; 127 try { 128 s = URLEncoder.encode(s, "UTF-8"); 129 } catch (UnsupportedEncodingException e) { 130 // ignore 131 } 132 return languageName + ":" + s; 133 } 134 135 public Language getLanguage() { 136 return language; 137 } 138 139 public Expression getExpression() { 140 if (isContentResolvedFromResource() && isContentCacheCleared()) { 141 return null; 142 } 143 return expression; 144 } 145 146 public void setExpression(Expression expression) { 147 this.expression = expression; 148 } 149 150 public boolean isTransform() { 151 return transform; 152 } 153 154 /** 155 * Whether or not the result of the script should be used as message body. 156 * <p/> 157 * This options is default <tt>true</tt>. 158 * 159 * @param transform <tt>true</tt> to use result as new message body, <tt>false</tt> to keep the existing message body 160 */ 161 public void setTransform(boolean transform) { 162 this.transform = transform; 163 } 164 165 public boolean isBinary() { 166 return binary; 167 } 168 169 /** 170 * Whether the script is binary content or text content. 171 * <p/> 172 * By default the script is read as text content (eg <tt>java.lang.String</tt>) 173 * 174 * @param binary <tt>true</tt> to read the script as binary, instead of text based. 175 */ 176 public void setBinary(boolean binary) { 177 this.binary = binary; 178 } 179 180 /** 181 * Sets the name of the language to use 182 * 183 * @param languageName the name of the language 184 */ 185 public void setLanguageName(String languageName) { 186 this.languageName = languageName; 187 } 188 189 /** 190 * Path to the resource, or a reference to lookup a bean in the Registry to use as the resource 191 * 192 * @param resourceUri the resource path 193 */ 194 @Override 195 public void setResourceUri(String resourceUri) { 196 super.setResourceUri(resourceUri); 197 } 198 199 @Override 200 public String getResourceUri() { 201 return super.getResourceUri(); 202 } 203 204 /** 205 * Sets the script to execute 206 * 207 * @param script the script 208 */ 209 public void setScript(String script) { 210 this.script = script; 211 } 212 213 public String getScript() { 214 return script; 215 } 216 217 public boolean isContentResolvedFromResource() { 218 return contentResolvedFromResource; 219 } 220 221 public void setContentResolvedFromResource(boolean contentResolvedFromResource) { 222 this.contentResolvedFromResource = contentResolvedFromResource; 223 } 224 225 public boolean isCacheScript() { 226 return cacheScript; 227 } 228 229 /** 230 * Whether to cache the compiled script and reuse 231 * <p/> 232 * Notice reusing the script can cause side effects from processing one Camel 233 * {@link org.apache.camel.Exchange} to the next {@link org.apache.camel.Exchange}. 234 */ 235 public void setCacheScript(boolean cacheScript) { 236 this.cacheScript = cacheScript; 237 } 238 239 public void clearContentCache() { 240 super.clearContentCache(); 241 // must also clear expression and script 242 expression = null; 243 script = null; 244 } 245 246}