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