/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.hawtjms.provider.discovery; import io.hawtjms.provider.AsyncProviderWrapper; import io.hawtjms.provider.failover.FailoverProvider; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * An AsyncProvider instance that wraps the FailoverProvider and listens for * events about discovered remote peers using a configured DiscoveryAgent * instance. */ public class DiscoveryProvider extends AsyncProviderWrapper<FailoverProvider> implements DiscoveryListener { private static final Logger LOG = LoggerFactory.getLogger(DiscoveryProviderFactory.class); private final URI discoveryUri; private DiscoveryAgent discoveryAgent; private final ConcurrentHashMap<String, URI> serviceURIs = new ConcurrentHashMap<String, URI>(); /** * Creates a new instance of the DiscoveryProvider. * * The Provider is created and initialized with the original URI used to create it, * and an instance of a FailoverProcider which it will use to initiate and maintain * connections to the discovered peers. * * @param discoveryUri * @param next */ public DiscoveryProvider(URI discoveryUri, FailoverProvider next) { super(next); this.discoveryUri = discoveryUri; } @Override public void start() throws IOException, IllegalStateException { if (this.discoveryAgent == null) { throw new IllegalStateException("No DiscoveryAgent configured."); } discoveryAgent.setDiscoveryListener(this); discoveryAgent.start(); super.start(); } @Override public void close() { discoveryAgent.close(); super.close(); } //------------------- Property Accessors ---------------------------------// /** * @return the original URI used to configure this DiscoveryProvider. */ public URI getDiscoveryURI() { return this.discoveryUri; } /** * @return the configured DiscoveryAgent instance used by this DiscoveryProvider. */ public DiscoveryAgent getDiscoveryAgent() { return this.discoveryAgent; } /** * Sets the discovery agent used by this provider to locate remote peer instance. * * @param agent * the agent to use to discover remote peers */ public void setDiscoveryAgent(DiscoveryAgent agent) { this.discoveryAgent = agent; } //------------------- Discovery Event Handlers ---------------------------// @Override public void onServiceAdd(DiscoveryEvent event) { String url = event.getPeerUri(); if (url != null) { try { URI uri = new URI(url); LOG.info("Adding new peer connection URL: {}", uri); serviceURIs.put(event.getPeerUri(), uri); next.add(uri); } catch (URISyntaxException e) { LOG.warn("Could not add remote URI: {} due to bad URI syntax: {}", url, e.getMessage()); } } } @Override public void onServiceRemove(DiscoveryEvent event) { URI uri = serviceURIs.get(event.getPeerUri()); if (uri != null) { next.remove(uri); } } //------------------- Connection State Handlers --------------------------// @Override public void onConnectionInterrupted() { this.discoveryAgent.resume(); super.onConnectionInterrupted(); } @Override public void onConnectionRestored() { this.discoveryAgent.suspend(); super.onConnectionRestored(); } }