/*
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.event.receiver.core.internal.util.helper;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.deployment.DeploymentEngine;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.databridge.commons.Attribute;
import org.wso2.carbon.databridge.commons.StreamDefinition;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterSchema;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterService;
import org.wso2.carbon.event.input.adapter.core.Property;
import org.wso2.carbon.event.receiver.core.EventReceiverDeployer;
import org.wso2.carbon.event.receiver.core.config.EventReceiverConfiguration;
import org.wso2.carbon.event.receiver.core.config.EventReceiverConstants;
import org.wso2.carbon.event.receiver.core.config.InputMappingAttribute;
import org.wso2.carbon.event.receiver.core.exception.EventReceiverConfigurationException;
import org.wso2.carbon.event.receiver.core.exception.EventReceiverStreamValidationException;
import org.wso2.carbon.event.receiver.core.exception.EventReceiverValidationException;
import org.wso2.carbon.event.receiver.core.InputMapper;
import org.wso2.carbon.event.receiver.core.internal.ds.EventReceiverServiceValueHolder;
import org.wso2.carbon.event.receiver.core.internal.type.json.JSONInputMapperConfigurationBuilder;
import org.wso2.carbon.event.receiver.core.internal.type.map.MapInputMappingConfigBuilder;
import org.wso2.carbon.event.receiver.core.internal.type.text.TextInputMapperConfigurationBuilder;
import org.wso2.carbon.event.receiver.core.internal.type.wso2event.WSO2EventInputMapperConfigurationBuilder;
import org.wso2.carbon.event.receiver.core.internal.type.xml.XMLInputMapperConfigrationBuilder;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class EventReceiverConfigurationHelper {
private static final Log log = LogFactory.getLog(EventReceiverConfigurationHelper.class);
public static String getInputMappingType(OMElement eventReceiverOMElement) {
OMElement mappingElement = eventReceiverOMElement.getFirstChildWithName(new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_MAPPING));
return mappingElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_TYPE));
}
public static String getEventReceiverName(OMElement eventReceiverOMElement) {
return eventReceiverOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_NAME));
}
public static EventReceiverDeployer getEventReceiverDeployer(
AxisConfiguration axisConfiguration) {
DeploymentEngine deploymentEngine = (DeploymentEngine) axisConfiguration.getConfigurator();
return (EventReceiverDeployer) deploymentEngine.getDeployer(EventReceiverConstants.ER_CONFIG_DIRECTORY, EventReceiverConstants.ER_CONFIG_FILE_EXTENSION);
}
public static Attribute[] getAttributes(List<InputMappingAttribute> inputMappingAttributes) {
List<Attribute> metaAttributes = new ArrayList<Attribute>();
List<Attribute> correlationAttributes = new ArrayList<Attribute>();
List<Attribute> payloadAttributes = new ArrayList<Attribute>();
for (InputMappingAttribute inputMappingAttribute : inputMappingAttributes) {
if (inputMappingAttribute.getToElementKey().startsWith(EventReceiverConstants.META_DATA_PREFIX)) {
metaAttributes.add(new Attribute(inputMappingAttribute.getToElementKey(), inputMappingAttribute.getToElementType()));
} else if (inputMappingAttribute.getToElementKey().startsWith(EventReceiverConstants.CORRELATION_DATA_PREFIX)) {
correlationAttributes.add(new Attribute(inputMappingAttribute.getToElementKey(), inputMappingAttribute.getToElementType()));
} else {
payloadAttributes.add(new Attribute(inputMappingAttribute.getToElementKey(), inputMappingAttribute.getToElementType()));
}
}
Attribute[] outputAttributes = new Attribute[metaAttributes.size() + correlationAttributes.size() + payloadAttributes.size()];
int attributeCount = 0;
for (Attribute attribute : metaAttributes) {
outputAttributes[attributeCount++] = attribute;
}
for (Attribute attribute : correlationAttributes) {
outputAttributes[attributeCount++] = attribute;
}
for (Attribute attribute : payloadAttributes) {
outputAttributes[attributeCount++] = attribute;
}
return outputAttributes;
}
public static void validateEventReceiverConfiguration(OMElement eventReceiverOMElement)
throws EventReceiverConfigurationException {
if (!eventReceiverOMElement.getLocalName().equals(EventReceiverConstants.ER_ELEMENT_ROOT_ELEMENT)) {
throw new EventReceiverConfigurationException("Invalid event receiver configuration.");
}
if (eventReceiverOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_NAME)) == null || eventReceiverOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_NAME)).trim().isEmpty()) {
throw new EventReceiverConfigurationException("Need to have an eventReceiver name");
}
String eventReceiverName = eventReceiverOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_NAME));
Iterator childElements = eventReceiverOMElement.getChildElements();
int count = 0;
while (childElements.hasNext()) {
count++;
childElements.next();
}
if (count != 3) {
throw new EventReceiverConfigurationException("Not a valid configuration, Event Receiver Configuration can only contains 3 child tags (From,Mapping & To), for " + eventReceiverName);
}
OMElement fromElement = eventReceiverOMElement.getFirstChildWithName(new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_FROM));
OMElement mappingElement = eventReceiverOMElement.getFirstChildWithName(new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_MAPPING));
OMElement toElement = eventReceiverOMElement.getFirstChildWithName(new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_TO));
if (fromElement == null || mappingElement == null || toElement == null) {
throw new EventReceiverConfigurationException("Invalid event receiver configuration for event receiver: " + eventReceiverName);
}
//From property of the event receiver configuration file
Iterator fromPropertyIter = eventReceiverOMElement.getChildrenWithName(
new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_FROM));
OMElement fromPropertyOMElement = null;
count = 0;
while (fromPropertyIter.hasNext()) {
fromPropertyOMElement = (OMElement) fromPropertyIter.next();
count++;
}
if (count != 1) {
throw new EventReceiverConfigurationException("There can be only one 'From' element in Event Receiver configuration file.");
}
String fromEventAdapterType = fromPropertyOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_TA_TYPE));
if (fromEventAdapterType == null || fromEventAdapterType.isEmpty()) {
throw new EventReceiverConfigurationException("There should be a event adapter type in Receiver configuration file.");
}
if (!validateFromPropertyConfiguration(fromElement, fromEventAdapterType)) {
throw new EventReceiverConfigurationException("From property does not contains all the required values for event adapter type " + fromEventAdapterType);
}
//Mapping property of the event receiver configuration file
Iterator mappingPropertyIter = eventReceiverOMElement.getChildrenWithName(
new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_MAPPING));
OMElement mappingPropertyOMElement = null;
count = 0;
while (mappingPropertyIter.hasNext()) {
mappingPropertyOMElement = (OMElement) mappingPropertyIter.next();
count++;
}
if (count != 1) {
throw new EventReceiverConfigurationException("There can be only one 'Mapping' element in Event Receiver configuration " + eventReceiverName);
}
String mappingType = mappingPropertyOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_TYPE));
if (mappingType == null || mappingType.isEmpty()) {
throw new EventReceiverConfigurationException("There should be proper mapping type in Event Receiver configuration " + eventReceiverName);
}
validateMappingProperties(mappingElement, mappingType);
//To property of the event publisher configuration file
Iterator toPropertyIter = eventReceiverOMElement.getChildrenWithName(
new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_TO));
OMElement toPropertyOMElement = null;
count = 0;
while (toPropertyIter.hasNext()) {
toPropertyOMElement = (OMElement) toPropertyIter.next();
count++;
}
if (count != 1) {
throw new EventReceiverConfigurationException("There can be only one 'To' element in Event Receiver configuration " + eventReceiverName);
}
String toStreamName = toPropertyOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_STREAM_NAME));
String toStreamVersion = toPropertyOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_VERSION));
if (toStreamName == null || toStreamName.isEmpty() || toStreamVersion == null || toStreamVersion.isEmpty()) {
throw new EventReceiverConfigurationException("There should be stream name and version in the 'To' element, of " + eventReceiverName);
}
}
private static boolean validateFromPropertyConfiguration(OMElement fromElement, String fromEventAdapterType) {
List<String> requiredProperties = new ArrayList<String>();
List<String> propertiesInConfig = new ArrayList<String>();
Iterator toElementPropertyIterator = fromElement.getChildrenWithName(
new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_PROPERTY)
);
InputEventAdapterService eventAdapterService = EventReceiverServiceValueHolder.getInputEventAdapterService();
InputEventAdapterSchema adapterSchema = eventAdapterService.getInputEventAdapterSchema(fromEventAdapterType);
if (adapterSchema == null) {
throw new EventReceiverValidationException("Event Adapter with type: " + fromEventAdapterType + " does not exist", fromEventAdapterType);
}
List<Property> propertyList = adapterSchema.getPropertyList();
if (propertyList != null) {
for (Property property : propertyList) {
if (property.isRequired()) {
requiredProperties.add(property.getPropertyName());
}
}
while (toElementPropertyIterator.hasNext()) {
OMElement toElementProperty = (OMElement) toElementPropertyIterator.next();
String propertyName = toElementProperty.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_NAME));
propertiesInConfig.add(propertyName);
}
if (!propertiesInConfig.containsAll(requiredProperties)) {
return false;
}
}
return true;
}
@SuppressWarnings("unchecked")
public static void validateMappingProperties(OMElement mappingElement, String mappingType)
throws EventReceiverConfigurationException {
if (mappingType.equalsIgnoreCase(EventReceiverConstants.ER_WSO2EVENT_MAPPING_TYPE)) {
WSO2EventInputMapperConfigurationBuilder.validateWso2EventMapping(mappingElement);
} else if (mappingType.equalsIgnoreCase(EventReceiverConstants.ER_TEXT_MAPPING_TYPE)) {
TextInputMapperConfigurationBuilder.validateTextMapping(mappingElement);
} else if (mappingType.equalsIgnoreCase(EventReceiverConstants.ER_MAP_MAPPING_TYPE)) {
MapInputMappingConfigBuilder.validateMapEventMapping(mappingElement);
} else if (mappingType.equalsIgnoreCase(EventReceiverConstants.ER_XML_MAPPING_TYPE)) {
XMLInputMapperConfigrationBuilder.validateXMLEventMapping(mappingElement);
} else if (mappingType.equalsIgnoreCase(EventReceiverConstants.ER_JSON_MAPPING_TYPE)) {
JSONInputMapperConfigurationBuilder.validateJsonEventMapping(mappingElement);
} else {
log.info("No validations available for input mapping type :" + mappingType);
}
}
public static void validateExportedStream(EventReceiverConfiguration eventReceiverConfiguration,
StreamDefinition exportedStreamDefinition,
InputMapper inputMapper) {
if (eventReceiverConfiguration != null && exportedStreamDefinition != null) {
if (eventReceiverConfiguration.getInputMapping().isCustomMappingEnabled()) {
String streamId = exportedStreamDefinition.getStreamId();
if (inputMapper.getOutputAttributes() == null || inputMapper.getOutputAttributes().length == 0) {
throw new EventReceiverStreamValidationException("The input mapper is not exporting any output attributes for stream " + streamId);
}
List<Attribute> outputAttributes = new ArrayList<Attribute>(Arrays.asList(inputMapper.getOutputAttributes()));
List<Attribute> metaAttributeList = exportedStreamDefinition.getMetaData();
if (metaAttributeList != null) {
for (Attribute attribute : metaAttributeList) {
Attribute prependedAttribute = new Attribute(EventReceiverConstants.META_DATA_PREFIX + attribute.getName(), attribute.getType());
if (!outputAttributes.contains(prependedAttribute)) {
throw new EventReceiverStreamValidationException("The meta data attribute '" + attribute.getName()
+ "' in stream '" + streamId + "' cannot be found under attributes exported by this event receiver mapping", streamId);
} else {
outputAttributes.remove(prependedAttribute);
}
}
}
List<Attribute> correlationAttributeList = exportedStreamDefinition.getCorrelationData();
if (correlationAttributeList != null) {
for (Attribute attribute : correlationAttributeList) {
Attribute prependedAttribute = new Attribute(EventReceiverConstants.CORRELATION_DATA_PREFIX + attribute.getName(), attribute.getType());
if (!outputAttributes.contains(prependedAttribute)) {
throw new EventReceiverStreamValidationException("The correlation data attribute '" + attribute.getName()
+ "' in stream '" + streamId + "' cannot be found under attributes exported by this event receiver mapping", streamId);
} else {
outputAttributes.remove(prependedAttribute);
}
}
}
List<Attribute> payloadAttributeList = exportedStreamDefinition.getPayloadData();
if (payloadAttributeList != null) {
for (Attribute attribute : payloadAttributeList) {
if (!outputAttributes.contains(attribute)) {
throw new EventReceiverStreamValidationException("The payload data attribute '" + attribute.getName()
+ "' in stream '" + streamId + "' cannot be found under attributes exported by this event receiver mapping", streamId);
} else {
outputAttributes.remove(attribute);
}
}
}
if (outputAttributes.size() > 0) {
throw new EventReceiverStreamValidationException("The attribute '" + outputAttributes.get(0).getName()
+ "' exported by this event receiver mapping cannot be found not in '" + streamId + "'", streamId);
}
}
}
}
/*
Checks whether all the secure fields are encrypted.
*/
public static boolean validateEncryptedProperties(OMElement eventAdapterConfigOMElement) {
String adaptorType = eventAdapterConfigOMElement.getFirstChildWithName(new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_FROM)).getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_TA_TYPE));
//get Static and Dynamic PropertyLists
List<String> encryptedProperties = EventReceiverServiceValueHolder.getCarbonEventReceiverService().getEncryptedProperties(adaptorType);
Iterator propertyIter = eventAdapterConfigOMElement.getFirstChildWithName(new QName(EventReceiverConstants.ER_CONF_NS, EventReceiverConstants.ER_ELEMENT_FROM)).getChildrenWithName(new QName(EventReceiverConstants.ER_ELEMENT_PROPERTY));
while (propertyIter.hasNext()) {
OMElement propertyOMElement = (OMElement) propertyIter.next();
String name = propertyOMElement.getAttributeValue(
new QName(EventReceiverConstants.ER_ATTR_NAME));
String value = propertyOMElement.getText();
if (encryptedProperties.contains(name.trim())) {
OMAttribute encryptedAttribute = propertyOMElement.getAttribute(new QName(EventReceiverConstants.ER_ATTR_ENCRYPTED));
if ((value != null && value.length() > 0) && (encryptedAttribute == null || (!"true".equals(encryptedAttribute.getAttributeValue())))) {
return false;
}
}
}
return true;
}
}