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.timer; 018 019import java.text.SimpleDateFormat; 020import java.util.Collection; 021import java.util.Date; 022import java.util.HashMap; 023import java.util.Map; 024import java.util.Timer; 025import java.util.concurrent.atomic.AtomicInteger; 026 027import org.apache.camel.Endpoint; 028import org.apache.camel.impl.UriEndpointComponent; 029 030/** 031 * The <a href="http://camel.apache.org/timer.html">Timer Component</a> is for generating message exchanges when a timer fires. 032 * 033 * Represents the component that manages {@link TimerEndpoint}. It holds the 034 * list of {@link TimerConsumer} objects that are started. 035 * 036 * @version 037 */ 038public class TimerComponent extends UriEndpointComponent { 039 private final Map<String, Timer> timers = new HashMap<>(); 040 private final Map<String, AtomicInteger> refCounts = new HashMap<>(); 041 042 public TimerComponent() { 043 super(TimerEndpoint.class); 044 } 045 046 public Timer getTimer(TimerConsumer consumer) { 047 String key = consumer.getEndpoint().getTimerName(); 048 if (!consumer.getEndpoint().isDaemon()) { 049 key = "nonDaemon:" + key; 050 } 051 052 Timer answer; 053 synchronized (timers) { 054 answer = timers.get(key); 055 if (answer == null) { 056 // the timer name is also the thread name, so lets resolve a name to be used 057 String name = consumer.getEndpoint().getCamelContext().getExecutorServiceManager().resolveThreadName("timer://" + consumer.getEndpoint().getTimerName()); 058 answer = new Timer(name, consumer.getEndpoint().isDaemon()); 059 timers.put(key, answer); 060 // store new reference counter 061 refCounts.put(key, new AtomicInteger(1)); 062 } else { 063 // increase reference counter 064 AtomicInteger counter = refCounts.get(key); 065 if (counter != null) { 066 counter.incrementAndGet(); 067 } 068 } 069 } 070 return answer; 071 } 072 073 public void removeTimer(TimerConsumer consumer) { 074 String key = consumer.getEndpoint().getTimerName(); 075 if (!consumer.getEndpoint().isDaemon()) { 076 key = "nonDaemon:" + key; 077 } 078 079 synchronized (timers) { 080 // decrease reference counter 081 AtomicInteger counter = refCounts.get(key); 082 if (counter != null && counter.decrementAndGet() <= 0) { 083 refCounts.remove(key); 084 // remove timer as its no longer in use 085 Timer timer = timers.remove(key); 086 if (timer != null) { 087 timer.cancel(); 088 } 089 } 090 } 091 } 092 093 @Override 094 protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { 095 TimerEndpoint answer = new TimerEndpoint(uri, this, remaining); 096 097 // convert time from String to a java.util.Date using the supported patterns 098 String time = getAndRemoveOrResolveReferenceParameter(parameters, "time", String.class); 099 String pattern = getAndRemoveOrResolveReferenceParameter(parameters, "pattern", String.class); 100 if (time != null) { 101 SimpleDateFormat sdf; 102 if (pattern != null) { 103 sdf = new SimpleDateFormat(pattern); 104 } else if (time.contains("T")) { 105 sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); 106 } else { 107 sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 108 } 109 Date date = sdf.parse(time); 110 answer.setTime(date); 111 answer.setPattern(pattern); 112 } 113 114 setProperties(answer, parameters); 115 return answer; 116 } 117 118 @Override 119 protected void doStop() throws Exception { 120 Collection<Timer> collection = timers.values(); 121 for (Timer timer : collection) { 122 timer.cancel(); 123 } 124 timers.clear(); 125 refCounts.clear(); 126 } 127}