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.model; 018 019import java.util.ArrayList; 020import java.util.List; 021import javax.xml.bind.annotation.XmlAccessType; 022import javax.xml.bind.annotation.XmlAccessorType; 023import javax.xml.bind.annotation.XmlAttribute; 024import javax.xml.bind.annotation.XmlRootElement; 025 026import org.apache.camel.ExchangePattern; 027import org.apache.camel.Expression; 028import org.apache.camel.NoSuchLanguageException; 029import org.apache.camel.Processor; 030import org.apache.camel.builder.ExpressionBuilder; 031import org.apache.camel.processor.SendDynamicProcessor; 032import org.apache.camel.spi.Language; 033import org.apache.camel.spi.Metadata; 034import org.apache.camel.spi.RouteContext; 035import org.apache.camel.util.ObjectHelper; 036 037/** 038 * Sends the message to a dynamic endpoint 039 * <p/> 040 * You can specify multiple languages in the uri separated by the plus sign, such as <tt>mock:+language:xpath:/order/@uri</tt> 041 * where <tt>mock:</tt> would be a prefix to a xpath expression. 042 * <p/> 043 * For more dynamic behavior use <a href="http://camel.apache.org/recipient-list.html">Recipient List</a> or 044 * <a href="http://camel.apache.org/dynamic-router.html">Dynamic Router</a> EIP instead. 045 */ 046@Metadata(label = "eip,endpoint,routing") 047@XmlRootElement(name = "toD") 048@XmlAccessorType(XmlAccessType.FIELD) 049public class ToDynamicDefinition extends NoOutputDefinition<ToDynamicDefinition> { 050 @XmlAttribute @Metadata(required = "true") 051 private String uri; 052 @XmlAttribute 053 private ExchangePattern pattern; 054 @XmlAttribute 055 private Integer cacheSize; 056 @XmlAttribute 057 private Boolean ignoreInvalidEndpoint; 058 059 public ToDynamicDefinition() { 060 } 061 062 public ToDynamicDefinition(String uri) { 063 this.uri = uri; 064 } 065 066 @Override 067 public Processor createProcessor(RouteContext routeContext) throws Exception { 068 ObjectHelper.notEmpty(uri, "uri", this); 069 070 Expression exp = createExpression(routeContext); 071 072 SendDynamicProcessor processor = new SendDynamicProcessor(uri, exp); 073 processor.setCamelContext(routeContext.getCamelContext()); 074 processor.setPattern(pattern); 075 if (cacheSize != null) { 076 processor.setCacheSize(cacheSize); 077 } 078 if (ignoreInvalidEndpoint != null) { 079 processor.setIgnoreInvalidEndpoint(ignoreInvalidEndpoint); 080 } 081 return processor; 082 } 083 084 protected Expression createExpression(RouteContext routeContext) { 085 List<Expression> list = new ArrayList<Expression>(); 086 String[] parts = uri.split("\\+"); 087 for (String part : parts) { 088 // the part may have optional language to use, so you can mix languages 089 String value = ObjectHelper.after(part, "language:"); 090 if (value != null) { 091 String before = ObjectHelper.before(value, ":"); 092 String after = ObjectHelper.after(value, ":"); 093 if (before != null && after != null) { 094 // maybe its a language, must have language: as prefix 095 try { 096 Language partLanguage = routeContext.getCamelContext().resolveLanguage(before); 097 if (partLanguage != null) { 098 Expression exp = partLanguage.createExpression(after); 099 list.add(exp); 100 continue; 101 } 102 } catch (NoSuchLanguageException e) { 103 // ignore 104 } 105 } 106 } 107 // fallback and use simple language 108 Language lan = routeContext.getCamelContext().resolveLanguage("simple"); 109 Expression exp = lan.createExpression(part); 110 list.add(exp); 111 } 112 113 Expression exp; 114 if (list.size() == 1) { 115 exp = list.get(0); 116 } else { 117 exp = ExpressionBuilder.concatExpression(list); 118 } 119 120 return exp; 121 } 122 123 @Override 124 public String toString() { 125 return "DynamicTo[" + getLabel() + "]"; 126 } 127 128 // Fluent API 129 // ------------------------------------------------------------------------- 130 131 /** 132 * Sets the optional {@link ExchangePattern} used to invoke this endpoint 133 */ 134 public ToDynamicDefinition pattern(ExchangePattern pattern) { 135 setPattern(pattern); 136 return this; 137 } 138 139 /** 140 * Sets the maximum size used by the {@link org.apache.camel.impl.ConsumerCache} which is used to cache and reuse producers. 141 * 142 * @param cacheSize the cache size, use <tt>0</tt> for default cache size, or <tt>-1</tt> to turn cache off. 143 * @return the builder 144 */ 145 public ToDynamicDefinition cacheSize(int cacheSize) { 146 setCacheSize(cacheSize); 147 return this; 148 } 149 150 /** 151 * Ignore the invalidate endpoint exception when try to create a producer with that endpoint 152 * 153 * @return the builder 154 */ 155 public ToDynamicDefinition ignoreInvalidEndpoint() { 156 setIgnoreInvalidEndpoint(true); 157 return this; 158 } 159 160 // Properties 161 // ------------------------------------------------------------------------- 162 163 public String getUri() { 164 return uri; 165 } 166 167 /** 168 * The uri of the endpoint to send to. The uri can be dynamic computed using the {@link org.apache.camel.language.simple.SimpleLanguage} expression. 169 */ 170 public void setUri(String uri) { 171 this.uri = uri; 172 } 173 174 public ExchangePattern getPattern() { 175 return pattern; 176 } 177 178 public void setPattern(ExchangePattern pattern) { 179 this.pattern = pattern; 180 } 181 182 public Integer getCacheSize() { 183 return cacheSize; 184 } 185 186 public void setCacheSize(Integer cacheSize) { 187 this.cacheSize = cacheSize; 188 } 189 190 public Boolean getIgnoreInvalidEndpoint() { 191 return ignoreInvalidEndpoint; 192 } 193 194 public void setIgnoreInvalidEndpoint(Boolean ignoreInvalidEndpoint) { 195 this.ignoreInvalidEndpoint = ignoreInvalidEndpoint; 196 } 197 198 199}