/*
* 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.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.log4j.Logger;
import org.apache.synapse.config.xml.XMLConfigConstants;
import org.apache.synapse.inbound.InboundProcessorParams;
import org.apache.synapse.transport.passthru.core.ssl.SSLConfiguration;
import org.wso2.carbon.base.ServerConfiguration;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class PersistenceUtils {
// Attributes
private static final String NAME_ATT = "name";
private static final String PORT_ATT = "port";
private static final String DOMAIN_ATT = "domain";
private static final String PROTOCOL_ATT = "protocol";
private static final String INJECT_SEQ_ATT = "injectingSeq";
private static final String ONERROR_SEQ_ATT = "onErrorSeq";
private static final String CLASS_IMPL_ATT = "classImpl";
private static final String PARAM_NAME_ATT = "paramName";
private static final String PARAM_VALUE_ATT = "paramValue";
private static final String KEYSTORE_ATT = "keystore";
private static final String TRUSTSTORE_ATT = "truststore";
private static final String CLIENTAUTH_ATT ="SSLVerifyClient";
private static final String SSLPROTOCOL_ATT = "SSLProtocol";
private static final String HTTPSPROTOCOLS_ATT = "HttpsProtocols";
private static final String REVOCATIONVERIFIER_ATT = "CertificateRevocationVerifier";
private static final String PREFERRED_CIPHERS_ATT = "PreferredCiphers";
// QNames
private static final QName INBOUND_ENDPOINTS_QN = new QName("inboundEndpoints");
private static final QName INBOUND_LISTENING_ENDPOINTS_QN = new QName("inboundListeningEndpoints");
private static final QName INBOUND_POLLING_ENDPOINTS_QN = new QName("inboundPollingingEndpoints");
private static final QName INBOUND_ENDPOINT_LISTENER_QN = new QName("inboundEndpointListener");
private static final QName INBOUND_ENDPOINT_POLL_QN = new QName("inboundEndpointPoll");
private static final QName ENDPOINT_QN = new QName("endpoint");
private static final QName PARAMS_QN = new QName("inboundParameters");
private static final QName PARAM_QN = new QName("inboundParameter");
private static final QName NAME_QN = new QName(NAME_ATT);
private static final QName PORT_QN = new QName(PORT_ATT);
private static final QName DOMAIN_QN = new QName(DOMAIN_ATT);
private static final QName PROTOCOL_QN = new QName(PROTOCOL_ATT);
private static final QName INJECT_SEQ_QN = new QName(INJECT_SEQ_ATT);
private static final QName ONERROR_SEQ_QN = new QName(ONERROR_SEQ_ATT);
private static final QName CLASS_IMPL_QN = new QName(CLASS_IMPL_ATT);
private static final QName PARAM_NAME_QN = new QName(PARAM_NAME_ATT);
private static final QName PARAM_VALUE_QN = new QName(PARAM_VALUE_ATT);
private static final QName KEYSTORE_QN = new QName(KEYSTORE_ATT);
private static final QName TRUSTORE_QN = new QName(TRUSTSTORE_ATT);
private static final QName CLIENTAUTH_QN = new QName(CLIENTAUTH_ATT);
private static final QName SSLPROTOCOL_QN = new QName(SSLPROTOCOL_ATT);
private static final QName HTTPSPROTOCOL_QN = new QName(HTTPSPROTOCOLS_ATT);
private static final QName REVOCATIONVERIFIER_QN = new QName(REVOCATIONVERIFIER_ATT);
private static final QName PREFERRED_CIPHERS_QN = new QName(PREFERRED_CIPHERS_ATT);
private static final String PORT_OFFSET_SYSTEM_VAR = "portOffset";
private static final String PORT_OFFSET_CONFIG = "Ports.Offset";
public static final String WEBSOCKET_USE_PORT_OFFSET = "ws.use.port.offset";
private static OMFactory fac = OMAbstractFactory.getOMFactory();
private static final OMNamespace nullNS =
fac.createOMNamespace(XMLConfigConstants.NULL_NAMESPACE, "");
private static final Logger log = Logger.getLogger(PersistenceUtils.class);
/**
* Convert EndpointInfo to a OMElement
*
* @param endpointInfo tenant data map
* @return equivalent OMElement for EndpointInfo
*/
public static OMElement convertEndpointInfoToOM(
Map<Integer, List<InboundEndpointInfoDTO>> endpointInfo, Map<String,Set<String>> endpointPollingInfo) {
OMElement rootElement = fac.createOMElement(INBOUND_ENDPOINTS_QN);
OMElement parentElement = fac.createOMElement(INBOUND_LISTENING_ENDPOINTS_QN, rootElement);
for (Map.Entry<Integer, List<InboundEndpointInfoDTO>> mapEntry : endpointInfo.entrySet()) {
int port = mapEntry.getKey();
OMElement listenerElem = fac.createOMElement(INBOUND_ENDPOINT_LISTENER_QN, parentElement);
listenerElem.addAttribute(PORT_ATT, String.valueOf(port), nullNS);
List<InboundEndpointInfoDTO> tenantDomains = mapEntry.getValue();
for (InboundEndpointInfoDTO inboundEndpointInfoDTO : tenantDomains) {
OMElement endpointElem = fac.createOMElement(ENDPOINT_QN, listenerElem);
endpointElem.addAttribute(NAME_ATT, inboundEndpointInfoDTO.getEndpointName(), nullNS);
endpointElem.addAttribute(DOMAIN_ATT, inboundEndpointInfoDTO.getTenantDomain(), nullNS);
endpointElem.addAttribute(PROTOCOL_ATT, inboundEndpointInfoDTO.getProtocol(), nullNS);
OMElement paramsElem = fac.createOMElement(PARAMS_QN, endpointElem);
if (inboundEndpointInfoDTO.getInboundParams() != null) {
if (inboundEndpointInfoDTO.getInboundParams().getInjectingSeq() != null) {
endpointElem.addAttribute(INJECT_SEQ_ATT,
inboundEndpointInfoDTO.getInboundParams().getInjectingSeq(), nullNS);
}
if (inboundEndpointInfoDTO.getInboundParams().getOnErrorSeq() != null) {
endpointElem.addAttribute(ONERROR_SEQ_ATT,
inboundEndpointInfoDTO.getInboundParams().getOnErrorSeq(), nullNS);
}
if (inboundEndpointInfoDTO.getInboundParams().getClassImpl() != null) {
endpointElem.addAttribute(CLASS_IMPL_ATT,
inboundEndpointInfoDTO.getInboundParams().getClassImpl(), nullNS);
}
for (Map.Entry<Object, Object> e :
inboundEndpointInfoDTO.getInboundParams().getProperties().entrySet()) {
OMElement paramElem = fac.createOMElement(PARAM_QN, paramsElem);
paramElem.addAttribute(PARAM_NAME_ATT, (String) e.getKey(), nullNS);
paramElem.addAttribute(PARAM_VALUE_ATT, (String) e.getValue(), nullNS);
}
}
if (inboundEndpointInfoDTO.getSslConfiguration() != null) {
if (inboundEndpointInfoDTO.getSslConfiguration().getKeyStore() != null) {
endpointElem.addAttribute(KEYSTORE_ATT, inboundEndpointInfoDTO.getSslConfiguration().getKeyStore(), nullNS);
}
if (inboundEndpointInfoDTO.getSslConfiguration().getTrustStore() != null) {
endpointElem.addAttribute(TRUSTSTORE_ATT, inboundEndpointInfoDTO.getSslConfiguration().getTrustStore(), nullNS);
}
if (inboundEndpointInfoDTO.getSslConfiguration().getClientAuthEl() != null) {
endpointElem.addAttribute(CLIENTAUTH_ATT, inboundEndpointInfoDTO.getSslConfiguration().getClientAuthEl(), nullNS);
}
if (inboundEndpointInfoDTO.getSslConfiguration().getSslProtocol() != null) {
endpointElem.addAttribute(SSLPROTOCOL_ATT, inboundEndpointInfoDTO.getSslConfiguration().getSslProtocol(), nullNS);
}
if (inboundEndpointInfoDTO.getSslConfiguration().getHttpsProtocolsEl() != null) {
endpointElem.addAttribute(HTTPSPROTOCOLS_ATT, inboundEndpointInfoDTO.getSslConfiguration().getHttpsProtocolsEl(), nullNS);
}
if (inboundEndpointInfoDTO.getSslConfiguration().getRevocationVerifier() != null) {
endpointElem.addAttribute(REVOCATIONVERIFIER_ATT, inboundEndpointInfoDTO.getSslConfiguration().getRevocationVerifier(), nullNS);
}
}
}
}
parentElement = fac.createOMElement(INBOUND_POLLING_ENDPOINTS_QN, rootElement);
for (Map.Entry<String, Set<String>> mapEntry : endpointPollingInfo.entrySet()) {
String tenantDomain = mapEntry.getKey();
OMElement listenerElem = fac.createOMElement(INBOUND_ENDPOINT_POLL_QN, parentElement);
Set<String> lNames = mapEntry.getValue();
for (String strName : lNames) {
OMElement endpointElem = fac.createOMElement(ENDPOINT_QN, listenerElem);
endpointElem.addAttribute(NAME_ATT, strName, nullNS);
endpointElem.addAttribute(DOMAIN_ATT, tenantDomain, nullNS);
}
}
return rootElement;
}
/**
* Create EndpointInfo from OMElement
*
* @param endpointInfoOM OMElement containing endpoint information
* @return equivalent EndpointInfo for OMElement
*/
public static Map<Integer,List<InboundEndpointInfoDTO>> convertOMToEndpointListeningInfo(
OMElement endpointInfoOM) {
Map<Integer, List<InboundEndpointInfoDTO>> endpointInfo =
new ConcurrentHashMap<Integer, List<InboundEndpointInfoDTO>>();
Iterator rootElementsItr =
endpointInfoOM.getChildrenWithName(INBOUND_LISTENING_ENDPOINTS_QN);
if(!rootElementsItr.hasNext()){
return endpointInfo;
}
Iterator listenerElementsItr =
((OMElement)rootElementsItr.next()).getChildrenWithName(INBOUND_ENDPOINT_LISTENER_QN);
while (listenerElementsItr.hasNext()) {
List<InboundEndpointInfoDTO> tenantList = new ArrayList<InboundEndpointInfoDTO>();
OMElement listenerElement = (OMElement) listenerElementsItr.next();
int port = Integer.parseInt(listenerElement.getAttributeValue(PORT_QN));
Iterator endpointsItr = listenerElement.getChildrenWithName(ENDPOINT_QN);
while (endpointsItr.hasNext()) {
OMElement endpointElement = (OMElement) endpointsItr.next();
InboundProcessorParams params = deserializeInboundParameters(endpointElement);
InboundEndpointInfoDTO inboundEndpointInfoDTO =
new InboundEndpointInfoDTO(endpointElement.getAttributeValue(DOMAIN_QN),
endpointElement.getAttributeValue(PROTOCOL_QN),
endpointElement.getAttributeValue(NAME_QN), params);
if (endpointElement.getAttributeValue(PROTOCOL_QN).equals("https")) {
SSLConfiguration sslConfiguration = new SSLConfiguration(
endpointElement.getAttributeValue(KEYSTORE_QN),
endpointElement.getAttributeValue(TRUSTORE_QN),
endpointElement.getAttributeValue(CLIENTAUTH_QN),
endpointElement.getAttributeValue(HTTPSPROTOCOL_QN),
endpointElement.getAttributeValue(REVOCATIONVERIFIER_QN),
endpointElement.getAttributeValue(SSLPROTOCOL_QN),
endpointElement.getAttributeValue(PREFERRED_CIPHERS_QN));
inboundEndpointInfoDTO.setSslConfiguration(sslConfiguration);
}
tenantList.add(inboundEndpointInfoDTO);
}
endpointInfo.put(port, tenantList);
}
return endpointInfo;
}
/**
* Create EndpointInfo from OMElement
*
* @param endpointInfoOM OMElement containing endpoint information
* @return equivalent EndpointInfo for OMElement
*/
public static Map<String,Set<String>> convertOMToEndpointPollingInfo(
OMElement endpointInfoOM) {
Map<String,Set<String>> endpointInfo =
new ConcurrentHashMap<String,Set<String>>();
Iterator rootElementsItr =
endpointInfoOM.getChildrenWithName(INBOUND_POLLING_ENDPOINTS_QN);
if(!rootElementsItr.hasNext()){
return endpointInfo;
}
Iterator pollElementsItr =
((OMElement)rootElementsItr.next()).getChildrenWithName(INBOUND_ENDPOINT_POLL_QN);
while (pollElementsItr.hasNext()) {
List<InboundEndpointInfoDTO> tenantList = new ArrayList<InboundEndpointInfoDTO>();
OMElement pollElement = (OMElement) pollElementsItr.next();
Iterator endpointsItr = pollElement.getChildrenWithName(ENDPOINT_QN);
while (endpointsItr.hasNext()) {
OMElement endpointElement = (OMElement) endpointsItr.next();
String iTenantDomain = endpointElement.getAttributeValue(DOMAIN_QN);
String strEndpointName = endpointElement.getAttributeValue(NAME_QN);
Set lNames = endpointInfo.get(iTenantDomain);
if(lNames == null){
lNames = new HashSet<String>();
}
lNames.add(strEndpointName);
endpointInfo.put(iTenantDomain, lNames);
}
}
return endpointInfo;
}
private static InboundProcessorParams deserializeInboundParameters(OMElement endpointElement) {
InboundProcessorParams inboundParams = new InboundProcessorParams();
inboundParams.setName(endpointElement.getAttributeValue(NAME_QN));
inboundParams.setProtocol(endpointElement.getAttributeValue(PROTOCOL_QN));
inboundParams.setInjectingSeq(endpointElement.getAttributeValue(INJECT_SEQ_QN));
inboundParams.setOnErrorSeq(endpointElement.getAttributeValue(ONERROR_SEQ_QN));
inboundParams.setClassImpl(endpointElement.getAttributeValue(CLASS_IMPL_QN));
Properties props = new Properties();
OMElement paramsEle = endpointElement.getFirstChildWithName(PARAMS_QN);
if (paramsEle != null) {
Iterator parameters = paramsEle.getChildrenWithName(PARAM_QN);
while (parameters.hasNext()) {
OMElement parameter = (OMElement) parameters.next();
props.setProperty(parameter.getAttributeValue(PARAM_NAME_QN),
parameter.getAttributeValue(PARAM_VALUE_QN));
}
}
inboundParams.setProperties(props);
return inboundParams;
}
/**
* used to get the port offset value of server according to inbound properties
*
* @param properties inbound properties
* @return port offset of server
*/
public static int getPortOffset(Properties properties) {
//Read the property of web socket endpoint ws.use.port.offset
boolean usePortOffset = Boolean.valueOf(properties.getProperty(WEBSOCKET_USE_PORT_OFFSET));
if (usePortOffset) {
//if its true return port offset according to the below
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
String portOffset = System.getProperty(PORT_OFFSET_SYSTEM_VAR,
carbonConfig.getFirstProperty(PORT_OFFSET_CONFIG));
try {
if ((portOffset != null)) {
return Integer.parseInt(portOffset.trim());
} else {
return 0;
}
} catch (NumberFormatException e) {
log.error("Invalid Port Offset: " + portOffset + ". Default value 0 will be used.", e);
return 0;
}
}
// else return the 0 as it not need to have port offset
return 0;
}
}