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.scheduler; 018 019import java.util.Collection; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.concurrent.ScheduledExecutorService; 023import java.util.concurrent.atomic.AtomicInteger; 024 025import org.apache.camel.Endpoint; 026import org.apache.camel.impl.UriEndpointComponent; 027import org.apache.camel.spi.Metadata; 028 029public class SchedulerComponent extends UriEndpointComponent { 030 031 private final Map<String, ScheduledExecutorService> executors = new HashMap<>(); 032 private final Map<String, AtomicInteger> refCounts = new HashMap<>(); 033 034 @Metadata(defaultValue = "1", label = "scheduler") 035 private int concurrentTasks = 1; 036 037 public SchedulerComponent() { 038 super(SchedulerEndpoint.class); 039 } 040 041 @Override 042 protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { 043 SchedulerEndpoint answer = new SchedulerEndpoint(uri, this, remaining); 044 answer.setConcurrentTasks(getConcurrentTasks()); 045 setProperties(answer, parameters); 046 return answer; 047 } 048 049 public int getConcurrentTasks() { 050 return concurrentTasks; 051 } 052 053 /** 054 * Number of threads used by the scheduling thread pool. 055 * <p/> 056 * Is by default using a single thread 057 */ 058 public void setConcurrentTasks(int concurrentTasks) { 059 this.concurrentTasks = concurrentTasks; 060 } 061 062 protected ScheduledExecutorService addConsumer(SchedulerConsumer consumer) { 063 String name = consumer.getEndpoint().getName(); 064 int concurrentTasks = consumer.getEndpoint().getConcurrentTasks(); 065 066 ScheduledExecutorService answer; 067 synchronized (executors) { 068 answer = executors.get(name); 069 if (answer == null) { 070 answer = getCamelContext().getExecutorServiceManager().newScheduledThreadPool(this, "scheduler://" + name, concurrentTasks); 071 executors.put(name, answer); 072 // store new reference counter 073 refCounts.put(name, new AtomicInteger(1)); 074 } else { 075 // increase reference counter 076 AtomicInteger counter = refCounts.get(name); 077 if (counter != null) { 078 counter.incrementAndGet(); 079 } 080 } 081 } 082 return answer; 083 } 084 085 protected void removeConsumer(SchedulerConsumer consumer) { 086 String name = consumer.getEndpoint().getName(); 087 088 synchronized (executors) { 089 // decrease reference counter 090 AtomicInteger counter = refCounts.get(name); 091 if (counter != null && counter.decrementAndGet() <= 0) { 092 refCounts.remove(name); 093 // remove scheduler as its no longer in use 094 ScheduledExecutorService scheduler = executors.remove(name); 095 if (scheduler != null) { 096 getCamelContext().getExecutorServiceManager().shutdown(scheduler); 097 } 098 } 099 } 100 } 101 102 @Override 103 protected void doStop() throws Exception { 104 Collection<ScheduledExecutorService> collection = executors.values(); 105 for (ScheduledExecutorService scheduler : collection) { 106 getCamelContext().getExecutorServiceManager().shutdown(scheduler); 107 } 108 executors.clear(); 109 refCounts.clear(); 110 } 111 112}