/**
* Copyright (c) 2012 - 2018 Data In Motion and others.
* All rights reserved.
*
* This program and the accompanying materials are made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Data In Motion - initial API and implementation
*/
package org.gecko.rsa.discovery;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.gecko.rsa.api.ExportEndpointHandler;
import org.osgi.framework.BundleContext;
import org.osgi.service.remoteserviceadmin.EndpointEventListener;
/**
* Basic endpoint description discovery.
* It handles the import of service descriptions from foreign frameworks as well as
* the export of service descriptions that needs to be exported to other frameworks.
*
* To export descriptions, the discovery, resp. the {@link ExportingEndpointListener}
* registers itself a {@link EndpointEventListener}.
*
* To import a service we need to listen to other {@link EndpointEventListener} that are
* usually either topology managers or other discoveries. But We only want to listen for
* topology managers in that case
*
* @author Mark Hoffmann
* @since 29.03.2019
*/
public class EndpointDiscovery {
private static final Logger logger = Logger.getLogger(EndpointDiscovery.class.getName());
private final AtomicBoolean start = new AtomicBoolean(false);
private final String discoveryId;
private transient BundleContext bctx;
private ExportingEndpointListener exportingEndpointListener;
private ImportingEndpointManager importingEndpointManager;
private ExportEndpointHandler exportHandler = null;
/**
* Creates a new instance.
* @param the bundle context
* @param the name that is distinguish for this discovery
*/
public EndpointDiscovery(BundleContext bctx, String discoveryId) {
this.bctx = bctx;
this.discoveryId = discoveryId;
}
/**
* Creates a new instance.
* @param the bundle context
* @param the name that is distinguish for this discovery
*/
public EndpointDiscovery(BundleContext bctx, String discoveryId, ExportEndpointHandler exportHandler) {
this.bctx = bctx;
this.discoveryId = discoveryId;
this.exportHandler = exportHandler;
}
public ImportingEndpointManager getImportingEndpointManager() {
return this.importingEndpointManager;
}
public ExportingEndpointListener getExportingEndpointListener() {
return exportingEndpointListener;
}
/**
* Starts the end-point description provider.
* It tracks local published from the topology manager as well as remote end-points
* that are received from the service registry
*/
public void start() {
if (start.compareAndSet(false, true)) {
doStart();
} else {
logger.log(Level.INFO, String.format("[%s] Discovery is already started", discoveryId));
}
}
/**
* Stops the messaging adapter discovery
*/
public void stop() {
if (start.compareAndSet(true, false)) {
doStop();
} else {
logger.log(Level.INFO, String.format("[%s] Discovery was not started yet", discoveryId));
}
}
/**
* Returns true, if the discovery is running
* @return true, if the discovery is running
*/
public boolean isRunning() {
return start.get();
}
/**
* Executes the start logic.
*/
protected void doStart() {
/*
* Creation of the manager that handles incoming/importing service descriptions.
* It is then responsible to delegate the description to a corresponding topology manager
*/
importingEndpointManager = new ImportingEndpointManager(discoveryId);
/*
* Register listener that listens for service descriptions of local services, that needs
* to be exported to other frameworks. These are triggered from the topology managers
*/
exportingEndpointListener = new ExportingEndpointListener(exportHandler, discoveryId);
exportingEndpointListener.start(bctx);
importingEndpointManager.start(bctx);
}
/**
* Stops and cleans up everything
*/
protected void doStop() {
try {
if (importingEndpointManager != null) {
importingEndpointManager.close();
}
if (exportingEndpointListener != null) {
exportingEndpointListener.close();
}
} catch (IOException e) {
logger.log(Level.SEVERE, "Error stopping MessageAdapter discovery, because of an IO error", e);
} catch (Exception e) {
logger.log(Level.SEVERE, "Error stopping MessageAdapter discovery", e);
}
}
}