/* * 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.event.receiver.core; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.deployment.AbstractDeployer; import org.apache.axis2.deployment.DeploymentException; import org.apache.axis2.deployment.repository.util.DeploymentFileData; import org.apache.axis2.engine.AxisConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.event.application.deployer.EventProcessingDeployer; import org.wso2.carbon.event.input.adapter.core.TenantConfigHolder; import org.wso2.carbon.event.receiver.core.config.EventReceiverConfiguration; import org.wso2.carbon.event.receiver.core.config.EventReceiverConfigurationFile; import org.wso2.carbon.event.receiver.core.config.EventReceiverConstants; 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.internal.CarbonEventReceiverService; import org.wso2.carbon.event.receiver.core.internal.ds.EventReceiverServiceValueHolder; import org.wso2.carbon.event.receiver.core.internal.util.EventReceiverConfigurationBuilder; import org.wso2.carbon.event.receiver.core.internal.util.helper.EventReceiverConfigurationFileSystemInvoker; import org.wso2.carbon.event.receiver.core.internal.util.helper.EventReceiverConfigurationHelper; import javax.xml.namespace.QName; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** * Deploy event receivers as axis2 service */ public class EventReceiverDeployer extends AbstractDeployer implements EventProcessingDeployer { private static Log log = LogFactory.getLog(EventReceiverDeployer.class); private ConfigurationContext configurationContext; private Set<String> deployedEventReceiverFilePaths = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); private Set<String> undeployedEventReceiverFilePaths = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); @Override public void init(ConfigurationContext configurationContext) { this.configurationContext = configurationContext; TenantConfigHolder.addTenantConfig(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(), configurationContext); } /** * Process the event receiver configuration file, create it and deploy it * * @param deploymentFileData information about the event receiver * @throws org.apache.axis2.deployment.DeploymentException for any errors */ @Override public void deploy(DeploymentFileData deploymentFileData) throws DeploymentException { String path = deploymentFileData.getAbsolutePath(); if (!deployedEventReceiverFilePaths.contains(path)) { try { processDeployment(deploymentFileData); } catch (Throwable e) { log.error("Cannot deploy event receiver : " + deploymentFileData.getName(), e); throw new DeploymentException("Event receiver file " + deploymentFileData.getName() + " is not deployed ", e); } } else { deployedEventReceiverFilePaths.remove(path); } } private OMElement getEventReceiverConfigOMElement(File ebConfigFile) throws DeploymentException { OMElement ebConfigElement = null; BufferedInputStream inputStream = null; try { inputStream = new BufferedInputStream(new FileInputStream(ebConfigFile)); XMLStreamReader parser = XMLInputFactory.newInstance(). createXMLStreamReader(inputStream); StAXOMBuilder receiver = new StAXOMBuilder(parser); ebConfigElement = receiver.getDocumentElement(); ebConfigElement.build(); } catch (FileNotFoundException e) { String errorMessage = ebConfigFile.getName() + " cannot be found"; log.error(errorMessage, e); throw new DeploymentException(errorMessage, e); } catch (XMLStreamException e) { String errorMessage = "Invalid XML for " + ebConfigFile.getName(); log.error(errorMessage, e); throw new DeploymentException(errorMessage, e); } catch (Exception e) { String errorMessage = "Error parsing configuration syntax: " + ebConfigFile.getName(); log.error(errorMessage, e); throw new DeploymentException(errorMessage, e); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { String errorMessage = "Cannot close the input stream"; log.error(errorMessage, e); } } return ebConfigElement; } @Override public void setExtension(String extension) { } /** * Removing already deployed event receiver configuration file * * @param filePath the filePath to the EventReceiverConfiguration file to be removed * @throws org.apache.axis2.deployment.DeploymentException */ @Override public void undeploy(String filePath) throws DeploymentException { if (!undeployedEventReceiverFilePaths.contains(filePath)) { try { processUndeployment(filePath); } catch (Throwable e) { log.error("Cannot undeploy event receiver : " + new File(filePath).getName(), e); throw new DeploymentException("Event receiver file " + new File(filePath).getName() + " is not undeployed properly", e); } } else { undeployedEventReceiverFilePaths.remove(filePath); } } public void setDirectory(String directory) { } public void processDeployment(DeploymentFileData deploymentFileData) throws DeploymentException, EventReceiverConfigurationException { File eventReceiverFile = deploymentFileData.getFile(); boolean isEditable = !eventReceiverFile.getAbsolutePath().contains(File.separator + "carbonapps" + File.separator); AxisConfiguration axisConfiguration = configurationContext.getAxisConfiguration(); CarbonEventReceiverService carbonEventReceiverService = EventReceiverServiceValueHolder.getCarbonEventReceiverService(); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); String eventReceiverName = ""; String streamNameWithVersion = null; OMElement eventReceiverOMElement = null; if (!carbonEventReceiverService.isEventReceiverFileAlreadyExist(eventReceiverFile.getName(), tenantId)) { try { eventReceiverOMElement = getEventReceiverConfigOMElement(eventReceiverFile); if (!eventReceiverOMElement.getLocalName().equals(EventReceiverConstants.ER_ELEMENT_ROOT_ELEMENT)) { throw new EventReceiverConfigurationException("Wrong event receiver configuration file, Invalid root element " + eventReceiverOMElement.getQName() + " in " + eventReceiverFile.getName()); } boolean isEncrypted = EventReceiverConfigurationHelper.validateEncryptedProperties(eventReceiverOMElement); if (isEditable && !isEncrypted) { String fileName = eventReceiverFile.getName(); EventReceiverConfigurationFileSystemInvoker.delete(fileName); EventReceiverConfigurationFileSystemInvoker.encryptAndSave(eventReceiverOMElement, fileName); return; } EventReceiverConfigurationHelper.validateEventReceiverConfiguration(eventReceiverOMElement); eventReceiverName = eventReceiverOMElement.getAttributeValue(new QName(EventReceiverConstants.ER_ATTR_NAME)); String mappingType = EventReceiverConfigurationHelper.getInputMappingType(eventReceiverOMElement); if (mappingType != null) { mappingType = mappingType.toLowerCase(); EventReceiverConfiguration eventReceiverConfiguration = EventReceiverConfigurationBuilder.getEventReceiverConfiguration(eventReceiverOMElement, mappingType, isEditable, tenantId); eventReceiverName = eventReceiverConfiguration.getEventReceiverName(); String type = eventReceiverConfiguration.getFromAdapterConfiguration().getType(); if (!EventReceiverServiceValueHolder.getInputEventAdapterTypes().contains(type)) { throw new EventReceiverValidationException("Event Adapter with type: " + type + " does not exist", type); } if (!carbonEventReceiverService.isEventReceiverAlreadyExists(tenantId, eventReceiverName)) { carbonEventReceiverService.addEventReceiverConfiguration(eventReceiverConfiguration); carbonEventReceiverService.addEventReceiverConfigurationFile(createEventReceiverConfigurationFile(eventReceiverName, deploymentFileData.getFile(), EventReceiverConfigurationFile.Status.DEPLOYED, tenantId, null, null), tenantId); log.info("Event Receiver configuration successfully deployed and in active state: " + eventReceiverName); } else { throw new EventReceiverConfigurationException("Event Receiver not deployed and in inactive state," + " since there is a event receiver registered with the same name in this tenant:" + eventReceiverFile.getName()); } } else { throw new EventReceiverConfigurationException("Event Receiver not deployed and in inactive state, " + "since it does not contain a proper mapping type : " + eventReceiverFile.getName()); } } catch (EventReceiverConfigurationException e) { if (isEditable) { log.error("Error, Event Receiver not deployed and in inactive state, " + e.getMessage(), e); carbonEventReceiverService.addEventReceiverConfigurationFile(createEventReceiverConfigurationFile(eventReceiverName, deploymentFileData.getFile(), EventReceiverConfigurationFile.Status.ERROR, tenantId, "Exception when deploying event receiver configuration file: " + e.getMessage(), null), tenantId); } throw new EventReceiverConfigurationException(e.getMessage(), e); } catch (EventReceiverValidationException e) { carbonEventReceiverService.addEventReceiverConfigurationFile(createEventReceiverConfigurationFile(eventReceiverName, deploymentFileData.getFile(), EventReceiverConfigurationFile.Status.WAITING_FOR_DEPENDENCY, tenantId, e.getMessage(), e.getDependency()), tenantId); log.info("Event receiver deployment held back and in inactive state: " + eventReceiverFile.getName() + ", waiting for Input Event Adapter dependency: " + e.getDependency()); } catch (EventReceiverStreamValidationException e) { carbonEventReceiverService.addEventReceiverConfigurationFile(createEventReceiverConfigurationFile(eventReceiverName, deploymentFileData.getFile(), EventReceiverConfigurationFile.Status.WAITING_FOR_STREAM_DEPENDENCY, tenantId, e.getMessage(), e.getDependency()), tenantId); log.info("Event receiver deployment held back and in inactive state: " + eventReceiverFile.getName() + ", Stream validation exception: " + e.getMessage()); } catch (Throwable e) { if (isEditable) { log.error("Event Receiver not deployed, invalid configuration found at " + eventReceiverFile.getName() + ", and in inactive state, " + e.getMessage(), e); carbonEventReceiverService.addEventReceiverConfigurationFile(createEventReceiverConfigurationFile(eventReceiverName, deploymentFileData.getFile(), EventReceiverConfigurationFile.Status.ERROR, tenantId, "Deployment exception: " + e.getMessage(), null), tenantId); } throw new EventReceiverConfigurationException(e); } } else { throw new EventReceiverConfigurationException("Event Receiver " + eventReceiverFile.getName() + " is already registered with this tenant (" + tenantId + ")"); } } private EventReceiverConfigurationFile createEventReceiverConfigurationFile( String eventReceiverName, File file, EventReceiverConfigurationFile.Status status, int tenantId, String deploymentStatusMessage, String dependency) { EventReceiverConfigurationFile eventReceiverConfigurationFile = new EventReceiverConfigurationFile(); eventReceiverConfigurationFile.setFileName(file.getName()); eventReceiverConfigurationFile.setFilePath(file.getAbsolutePath()); eventReceiverConfigurationFile.setEventReceiverName(eventReceiverName); eventReceiverConfigurationFile.setStatus(status); eventReceiverConfigurationFile.setDependency(dependency); eventReceiverConfigurationFile.setDeploymentStatusMessage(deploymentStatusMessage); eventReceiverConfigurationFile.setTenantId(tenantId); return eventReceiverConfigurationFile; } public void processUndeployment(String filePath) throws EventReceiverConfigurationException { String fileName = new File(filePath).getName(); log.info("Event Receiver undeployed successfully: " + fileName); CarbonEventReceiverService carbonEventReceiverService = EventReceiverServiceValueHolder.getCarbonEventReceiverService(); carbonEventReceiverService.removeEventReceiverConfigurationFile(fileName); } public void executeManualDeployment(DeploymentFileData deploymentFileData) throws EventReceiverConfigurationException { try { processDeployment(deploymentFileData); } catch (DeploymentException e) { throw new EventReceiverConfigurationException("Error while attempting manual deployment: " + e.getMessage(), e); } } public void executeManualUndeployment(String filePath) throws EventReceiverConfigurationException { processUndeployment(filePath); } public Set<String> getDeployedEventReceiverFilePaths() { return deployedEventReceiverFilePaths; } public Set<String> getUndeployedEventReceiverFilePaths() { return undeployedEventReceiverFilePaths; } }