/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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 org.wso2.carbon.inbound.endpoint.persistence;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.util.AXIOMUtil;
import org.apache.log4j.Logger;
import org.apache.synapse.inbound.InboundProcessorParams;
import org.apache.synapse.transport.passthru.core.ssl.SSLConfiguration;
import org.wso2.carbon.core.RegistryResources;
import org.wso2.carbon.registry.core.Registry;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.exceptions.ResourceNotFoundException;
import javax.xml.stream.XMLStreamException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class InboundEndpointsDataStore {
private static final Logger log = Logger.getLogger(InboundEndpointsDataStore.class);
private Map<Integer,List<InboundEndpointInfoDTO>> endpointListeningInfo;
//Store polling endpoints with <TenantId<Endpoint_Name>> format
private Map<String,Set<String>> endpointPollingInfo;
private Registry registry = null;
private final String rootPath = RegistryResources.ROOT + "esb/inbound/inbound-endpoints/";
private static InboundEndpointsDataStore instance = new InboundEndpointsDataStore();
public static InboundEndpointsDataStore getInstance() {
return instance;
}
private InboundEndpointsDataStore() {
try {
registry = ServiceReferenceHolder.getInstance().getRegistry();
} catch (RegistryException e) {
handleException("Error while obtaining a registry instance", e);
}
try {
Resource fetchedResource = registry.get(rootPath);
if (fetchedResource != null) {
String fetchedData=null;
if(fetchedResource.getContent() instanceof byte[]){
fetchedData = new String((byte[])fetchedResource.getContent());
};
OMElement fetchedOM = null;
try {
fetchedOM = AXIOMUtil.stringToOM(fetchedData);
} catch (XMLStreamException e) {
handleException("Error while converting fetched registry data to a OM", e);
}
endpointListeningInfo = PersistenceUtils.convertOMToEndpointListeningInfo(fetchedOM);
endpointPollingInfo = PersistenceUtils.convertOMToEndpointPollingInfo(fetchedOM);
}
} catch (ResourceNotFoundException ex) {
log.info("Inbound endpoint registry data not found, so re-initializing registry data");
initRegistryData();
} catch (RegistryException e) {
handleException("Error occurred while fetching inbound endpoint data from registry", e);
}
}
/**
* Initialize registry data
*/
private void initRegistryData() {
/**
* Note : ports in this map are not offset by the value of port offset.
*/
endpointListeningInfo = new ConcurrentHashMap<Integer, List<InboundEndpointInfoDTO>>();
endpointPollingInfo = new ConcurrentHashMap<String, Set<String>>();
try {
Resource resource = registry.newResource();
resource.setContent(PersistenceUtils.convertEndpointInfoToOM(endpointListeningInfo, endpointPollingInfo).toString());
registry.put(rootPath, resource);
} catch (RegistryException e) {
handleException("Initializing registry data.Error while creating registry resource", e);
}
}
/**
* Register endpoint in the InboundEndpointsDataStore
*
* @param port listener port
* @param tenantDomain tenant domain
* @param protocol protocol
* @param name endpoint name
*/
public void registerListeningEndpoint(int port, String tenantDomain, String protocol, String name, InboundProcessorParams params) {
List<InboundEndpointInfoDTO> tenantList = endpointListeningInfo.get(port);
if (tenantList == null) {
// If there is no existing listeners in the port, create a new list
tenantList = new ArrayList<InboundEndpointInfoDTO>();
port = port - PersistenceUtils.getPortOffset(params.getProperties());
endpointListeningInfo.put(port, tenantList);
}
tenantList.add(new InboundEndpointInfoDTO(tenantDomain, protocol, name, params));
updateRegistry();
}
/**
* Register endpoint in the InboundEndpointsDataStore
*
* @param tenantDomain tenant domain
* @param name endpoint name
*/
public void registerPollingingEndpoint(String tenantDomain, String name) {
Set<String> lNames = endpointPollingInfo.get(tenantDomain);
if (lNames == null) {
lNames = new HashSet<String>();
}
lNames.add(name);
endpointPollingInfo.put(tenantDomain, lNames);
updateRegistry();
}
/**
* Register SSL endpoint in the InboundEndpointsDataStore
*
* @param port listener port
* @param tenantDomain tenant domain
* @param protocol protocol
* @param name endpoint name
*/
public void registerSSLListeningEndpoint(int port, String tenantDomain, String protocol, String name,
SSLConfiguration sslConfiguration, InboundProcessorParams params) {
List<InboundEndpointInfoDTO> tenantList = endpointListeningInfo.get(port);
if (tenantList == null) {
// If there is no existing listeners in the port, create a new list
tenantList = new ArrayList<InboundEndpointInfoDTO>();
endpointListeningInfo.put(port, tenantList);
}
InboundEndpointInfoDTO inboundEndpointInfoDTO = new InboundEndpointInfoDTO(tenantDomain, protocol, name, params);
inboundEndpointInfoDTO.setSslConfiguration(sslConfiguration);
tenantList.add(inboundEndpointInfoDTO);
updateRegistry();
}
/**
* Get endpoint name for given port and domain
*
* @param port port
* @param tenantDomain tenant domain
* @return endpoint name
*/
public String getListeningEndpointName(int port, String tenantDomain) {
List<InboundEndpointInfoDTO> tenantList = endpointListeningInfo.get(port);
if (tenantList != null) {
for (InboundEndpointInfoDTO tenantInfo : tenantList) {
if (tenantInfo.getTenantDomain().equals(tenantDomain)) {
return tenantInfo.getEndpointName();
}
}
}
return null;
}
/**
* Unregister an endpoint from data store
*
* @param port port
* @param tenantDomain tenant domain name
*/
public void unregisterListeningEndpoint(int port, String tenantDomain) {
List<InboundEndpointInfoDTO> tenantList = endpointListeningInfo.get(port);
if (tenantList != null) {
for (InboundEndpointInfoDTO tenantInfo : tenantList) {
if (tenantInfo.getTenantDomain().equals(tenantDomain)) {
tenantList.remove(tenantInfo);
break;
}
}
}
if (endpointListeningInfo.get(port) != null && endpointListeningInfo.get(port).size() == 0) {
endpointListeningInfo.remove(port);
}
updateRegistry();
}
/**
* Unregister an endpoint from data store
*
* @param tenantId
* @param name
*/
public void unregisterPollingEndpoint(String tenantDomain, String name) {
Set<String> lNames = endpointPollingInfo.get(tenantDomain);
if (lNames != null && !lNames.isEmpty()) {
for (String strName : lNames) {
if (strName.equals(name)) {
lNames.remove(strName);
break;
}
}
if(lNames.isEmpty()){
endpointPollingInfo.remove(tenantDomain);
}
}
updateRegistry();
}
/**
* Check polling endpoint from data store
*
* @param tenantDomain
* @param name
*/
public boolean isPollingEndpointRegistered(String tenantDomain, String name) {
Set<String> lNames = endpointPollingInfo.get(tenantDomain);
if (lNames != null && !lNames.isEmpty()) {
for (String strName : lNames) {
if (strName.equals(name)) {
return true;
}
}
}
return false;
}
/**
* Check whether endpoint registry is empty for a particular port
*
* @param port port
* @return whether no endpoint is registered for a port
*/
public boolean isEndpointRegistryEmpty(int port) {
return endpointListeningInfo.get(port) == null;
}
/**
* Get details of all endpoints
*
* @return information of all endpoints
*/
public Map<Integer,List<InboundEndpointInfoDTO>> getAllListeningEndpointData() {
return endpointListeningInfo;
}
/**
* Get details of all polling endpoints
*
* @return information of all polling endpoints
*/
public Map<String,Set<String>> getAllPollingingEndpointData() {
return endpointPollingInfo;
}
/**
* Synchronize in memory endpoint data with registry
*/
private synchronized void updateRegistry() {
OMElement dataOM = PersistenceUtils.convertEndpointInfoToOM(endpointListeningInfo, endpointPollingInfo);
try {
Resource resource = registry.get(rootPath);
resource.setContent(dataOM.toString());
registry.put(rootPath, resource);
} catch (RegistryException e) {
handleException("Exception occurred while updating registry data", e);
}
}
private void handleException(String msg, Exception ex) {
//TODO: check whether we need more error handling here
log.error(msg, ex);
}
}