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.reifier; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.apache.camel.ExchangePattern; 023import org.apache.camel.Expression; 024import org.apache.camel.NoSuchLanguageException; 025import org.apache.camel.Processor; 026import org.apache.camel.Route; 027import org.apache.camel.builder.ExpressionBuilder; 028import org.apache.camel.model.ProcessorDefinition; 029import org.apache.camel.model.ToDynamicDefinition; 030import org.apache.camel.processor.SendDynamicProcessor; 031import org.apache.camel.spi.Language; 032import org.apache.camel.spi.PropertiesComponent; 033import org.apache.camel.util.Pair; 034import org.apache.camel.util.StringHelper; 035import org.apache.camel.util.URISupport; 036 037public class ToDynamicReifier<T extends ToDynamicDefinition> extends ProcessorReifier<T> { 038 039 public ToDynamicReifier(Route route, ProcessorDefinition<?> definition) { 040 super(route, (T) definition); 041 } 042 043 @Override 044 public Processor createProcessor() throws Exception { 045 String uri; 046 Expression exp; 047 if (definition.getEndpointProducerBuilder() != null) { 048 uri = definition.getEndpointProducerBuilder().getUri(); 049 exp = definition.getEndpointProducerBuilder().expr(camelContext); 050 } else { 051 uri = StringHelper.notEmpty(definition.getUri(), "uri", this); 052 exp = createExpression(uri); 053 } 054 055 SendDynamicProcessor processor = new SendDynamicProcessor(uri, exp); 056 processor.setCamelContext(camelContext); 057 processor.setPattern(parse(ExchangePattern.class, definition.getPattern())); 058 if (definition.getCacheSize() != null) { 059 processor.setCacheSize(parseInt(definition.getCacheSize())); 060 } 061 if (definition.getIgnoreInvalidEndpoint() != null) { 062 processor.setIgnoreInvalidEndpoint(parseBoolean(definition.getIgnoreInvalidEndpoint(), false)); 063 } 064 if (definition.getAllowOptimisedComponents() != null) { 065 processor.setAllowOptimisedComponents(parseBoolean(definition.getAllowOptimisedComponents(), true)); 066 } 067 if (definition.getAutoStartComponents() != null) { 068 processor.setAutoStartupComponents(parseBoolean(definition.getAutoStartComponents(), true)); 069 } 070 return processor; 071 } 072 073 protected Expression createExpression(String uri) { 074 List<Expression> list = new ArrayList<>(); 075 076 // make sure to parse property placeholders 077 uri = camelContext.resolvePropertyPlaceholders(uri); 078 079 String[] parts = safeSplitRaw(uri); 080 for (String part : parts) { 081 // the part may have optional language to use, so you can mix 082 // languages 083 String value = StringHelper.after(part, "language:"); 084 if (value != null) { 085 String before = StringHelper.before(value, ":"); 086 String after = StringHelper.after(value, ":"); 087 if (before != null && after != null) { 088 // maybe its a language, must have language: as prefix 089 try { 090 Language partLanguage = camelContext.resolveLanguage(before); 091 if (partLanguage != null) { 092 Expression exp = partLanguage.createExpression(after); 093 list.add(exp); 094 continue; 095 } 096 } catch (NoSuchLanguageException e) { 097 // ignore 098 } 099 } 100 } 101 102 // fallback and use simple language 103 Language lan = camelContext.resolveLanguage("simple"); 104 Expression exp = lan.createExpression(part); 105 list.add(exp); 106 } 107 108 Expression exp; 109 if (list.size() == 1) { 110 exp = list.get(0); 111 } else { 112 exp = ExpressionBuilder.concatExpression(list); 113 } 114 115 return exp; 116 } 117 118 // Utilities 119 // ------------------------------------------------------------------------- 120 121 /** 122 * We need to split the string safely for each + sign, but avoid splitting 123 * within RAW(...). 124 */ 125 private static String[] safeSplitRaw(String s) { 126 List<String> list = new ArrayList<>(); 127 128 if (!s.contains("+")) { 129 // no plus sign so there is only one part, so no need to split 130 list.add(s); 131 } else { 132 // there is a plus sign so we need to split in a safe manner 133 List<Pair<Integer>> rawPairs = URISupport.scanRaw(s); 134 StringBuilder sb = new StringBuilder(); 135 char[] chars = s.toCharArray(); 136 for (int i = 0; i < chars.length; i++) { 137 char ch = chars[i]; 138 if (ch != '+' || URISupport.isRaw(i, rawPairs)) { 139 sb.append(ch); 140 } else { 141 list.add(sb.toString()); 142 sb.setLength(0); 143 } 144 } 145 // any leftover? 146 if (sb.length() > 0) { 147 list.add(sb.toString()); 148 sb.setLength(0); 149 } 150 } 151 152 return list.toArray(new String[list.size()]); 153 } 154 155}