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.impl; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.LinkedHashSet; 022import java.util.Map; 023import java.util.Set; 024import java.util.concurrent.ConcurrentHashMap; 025import java.util.concurrent.ConcurrentMap; 026 027import org.apache.camel.CamelContext; 028import org.apache.camel.Endpoint; 029import org.apache.camel.spi.EndpointRegistry; 030import org.apache.camel.util.CamelContextHelper; 031import org.apache.camel.util.LRUCache; 032import org.apache.camel.util.ServiceHelper; 033 034/** 035 * Default implementation of {@link org.apache.camel.spi.EndpointRegistry} 036 */ 037public class DefaultEndpointRegistry extends LRUCache<EndpointKey, Endpoint> implements EndpointRegistry<EndpointKey> { 038 private static final long serialVersionUID = 1L; 039 private ConcurrentMap<EndpointKey, Endpoint> staticMap; 040 private final CamelContext context; 041 042 public DefaultEndpointRegistry(CamelContext context) { 043 // do not stop on eviction, as the endpoint may still be in use 044 super(CamelContextHelper.getMaximumEndpointCacheSize(context), CamelContextHelper.getMaximumEndpointCacheSize(context), false); 045 // static map to hold endpoints we do not want to be evicted 046 this.staticMap = new ConcurrentHashMap<EndpointKey, Endpoint>(); 047 this.context = context; 048 } 049 050 public DefaultEndpointRegistry(CamelContext context, Map<EndpointKey, Endpoint> endpoints) { 051 this(context); 052 putAll(endpoints); 053 } 054 055 @Override 056 public void start() throws Exception { 057 resetStatistics(); 058 } 059 060 @Override 061 public Endpoint get(Object o) { 062 // try static map first 063 Endpoint answer = staticMap.get(o); 064 if (answer == null) { 065 answer = super.get(o); 066 } else { 067 hits.increment(); 068 } 069 return answer; 070 } 071 072 @Override 073 public Endpoint put(EndpointKey key, Endpoint endpoint) { 074 // at first we must see if the key already exists and then replace it back, so it stays the same spot 075 Endpoint answer = staticMap.remove(key); 076 if (answer != null) { 077 // replace existing 078 staticMap.put(key, endpoint); 079 return answer; 080 } 081 082 answer = super.remove(key); 083 if (answer != null) { 084 // replace existing 085 super.put(key, endpoint); 086 return answer; 087 } 088 089 // we want endpoints to be static if they are part of setting up or starting routes 090 if (context.isSetupRoutes() || context.isStartingRoutes()) { 091 answer = staticMap.put(key, endpoint); 092 } else { 093 answer = super.put(key, endpoint); 094 } 095 096 return answer; 097 } 098 099 @Override 100 public void putAll(Map<? extends EndpointKey, ? extends Endpoint> map) { 101 // need to use put instead of putAll to ensure the entries gets added to either static or dynamic map 102 for (Map.Entry<? extends EndpointKey, ? extends Endpoint> entry : map.entrySet()) { 103 put(entry.getKey(), entry.getValue()); 104 } 105 } 106 107 @Override 108 public boolean containsKey(Object o) { 109 return staticMap.containsKey(o) || super.containsKey(o); 110 } 111 112 @Override 113 public boolean containsValue(Object o) { 114 return staticMap.containsValue(o) || super.containsValue(o); 115 } 116 117 @Override 118 public int size() { 119 return staticMap.size() + super.size(); 120 } 121 122 public int staticSize() { 123 return staticMap.size(); 124 } 125 126 @Override 127 public int dynamicSize() { 128 return super.size(); 129 } 130 131 @Override 132 public boolean isEmpty() { 133 return staticMap.isEmpty() && super.isEmpty(); 134 } 135 136 @Override 137 public Endpoint remove(Object o) { 138 Endpoint answer = staticMap.remove(o); 139 if (answer == null) { 140 answer = super.remove(o); 141 } 142 return answer; 143 } 144 145 @Override 146 public void clear() { 147 staticMap.clear(); 148 super.clear(); 149 } 150 151 @Override 152 public Set<EndpointKey> keySet() { 153 Set<EndpointKey> answer = new LinkedHashSet<EndpointKey>(); 154 answer.addAll(staticMap.keySet()); 155 answer.addAll(super.keySet()); 156 return answer; 157 } 158 159 @Override 160 public Collection<Endpoint> values() { 161 Collection<Endpoint> answer = new ArrayList<Endpoint>(); 162 answer.addAll(staticMap.values()); 163 answer.addAll(super.values()); 164 return answer; 165 } 166 167 @Override 168 public Set<Entry<EndpointKey, Endpoint>> entrySet() { 169 Set<Entry<EndpointKey, Endpoint>> answer = new LinkedHashSet<Entry<EndpointKey, Endpoint>>(); 170 answer.addAll(staticMap.entrySet()); 171 answer.addAll(super.entrySet()); 172 return answer; 173 } 174 175 @Override 176 public int getMaximumCacheSize() { 177 return super.getMaxCacheSize(); 178 } 179 180 /** 181 * Purges the cache 182 */ 183 @Override 184 public void purge() { 185 // only purge the dynamic part 186 super.clear(); 187 } 188 189 @Override 190 public boolean isStatic(String key) { 191 return staticMap.containsKey(new EndpointKey(key)); 192 } 193 194 @Override 195 public boolean isDynamic(String key) { 196 return super.containsKey(new EndpointKey(key)); 197 } 198 199 @Override 200 public void stop() throws Exception { 201 ServiceHelper.stopServices(staticMap.values()); 202 ServiceHelper.stopServices(values()); 203 purge(); 204 } 205 206 @Override 207 public String toString() { 208 return "EndpointRegistry for " + context.getName() + ", capacity: " + getMaxCacheSize(); 209 } 210}