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.remote;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022import java.util.concurrent.TimeUnit;
023
024import org.apache.camel.spi.ServiceCallServer;
025import org.apache.camel.spi.ServiceCallServerListStrategy;
026import org.apache.camel.util.ObjectHelper;
027
028public class CachingServiceCallServiceListStrategy<T extends ServiceCallServer> implements ServiceCallServerListStrategy<T> {
029    private final ServiceCallServerListStrategy<T> delegate;
030    private List<T> servers;
031    private long lastUpdate;
032    private long timeout;
033
034    public CachingServiceCallServiceListStrategy(ServiceCallServerListStrategy<T> delegate) {
035        this.delegate = ObjectHelper.notNull(delegate, "delegate");
036        this.lastUpdate = 0;
037        this.servers = Collections.emptyList();
038        this.timeout = 60 * 1000; // 1 min;
039    }
040
041    public void setTimeout(long timeout) {
042        this.timeout = timeout;
043    }
044
045    public void setTimeout(long timeout, TimeUnit unit) {
046        this.timeout = unit.toMillis(timeout);
047    }
048
049    public long getTimeout() {
050        return timeout;
051    }
052
053    public CachingServiceCallServiceListStrategy<T> timeout(long timeout) {
054        setTimeout(timeout);
055        return this;
056    }
057
058    public CachingServiceCallServiceListStrategy<T> timeout(long timeout, TimeUnit unit) {
059        setTimeout(timeout, unit);
060        return this;
061    }
062
063    @Override
064    public List<T> getInitialListOfServers(String name) {
065        return delegate.getInitialListOfServers(name);
066    }
067
068    @Override
069    public List<T> getUpdatedListOfServers(String name) {
070        long now = System.currentTimeMillis();
071
072        if (lastUpdate == 0 || now > lastUpdate + timeout) {
073            List<T> updatedList = delegate.getUpdatedListOfServers(name);
074            if (updatedList.isEmpty()) {
075                servers = Collections.emptyList();
076            } else {
077                // List is copied as the delegated ServiceCallServerListStrategy
078                // may update the list
079                servers = Collections.unmodifiableList(new ArrayList<>(updatedList));
080            }
081
082            lastUpdate = now;
083        }
084
085        return servers;
086    }
087
088    // **********************
089    // Helpers
090    // **********************
091
092    public static <S extends ServiceCallServer> CachingServiceCallServiceListStrategy<S> wrap(ServiceCallServerListStrategy<S> delegate) {
093        return new CachingServiceCallServiceListStrategy<>(delegate);
094    }
095
096    public static <S extends ServiceCallServer> CachingServiceCallServiceListStrategy<S> wrap(ServiceCallServerListStrategy<S> delegate, long timeout) {
097        return new CachingServiceCallServiceListStrategy<>(delegate)
098            .timeout(timeout);
099    }
100
101    public static <S extends ServiceCallServer> CachingServiceCallServiceListStrategy<S> wrap(ServiceCallServerListStrategy<S> delegate, long timeout, TimeUnit unit) {
102        return new CachingServiceCallServiceListStrategy<>(delegate)
103            .timeout(timeout, unit);
104    }
105}