/* * 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.publisher.core; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMException; 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.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.output.adapter.core.TenantConfigHolder; import org.wso2.carbon.event.publisher.core.config.EventPublisherConfiguration; import org.wso2.carbon.event.publisher.core.config.EventPublisherConfigurationFile; import org.wso2.carbon.event.publisher.core.config.EventPublisherConstants; import org.wso2.carbon.event.publisher.core.exception.EventPublisherConfigurationException; import org.wso2.carbon.event.publisher.core.exception.EventPublisherStreamValidationException; import org.wso2.carbon.event.publisher.core.exception.EventPublisherValidationException; import org.wso2.carbon.event.publisher.core.internal.CarbonEventPublisherService; import org.wso2.carbon.event.publisher.core.internal.ds.EventPublisherServiceValueHolder; import org.wso2.carbon.event.publisher.core.internal.util.EventPublisherConfigurationBuilder; import org.wso2.carbon.event.publisher.core.internal.util.helper.EventPublisherConfigurationFilesystemInvoker; import org.wso2.carbon.event.publisher.core.internal.util.helper.EventPublisherConfigurationHelper; 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 publisher as axis2 service */ public class EventPublisherDeployer extends AbstractDeployer implements EventProcessingDeployer { private static Log log = LogFactory.getLog(EventPublisherDeployer.class); private ConfigurationContext configurationContext; private Set<String> deployedEventPublisherFilePaths = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); private Set<String> undeployedEventPublisherFilePaths = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>()); public void init(ConfigurationContext configurationContext) { this.configurationContext = configurationContext; TenantConfigHolder.addTenantConfig(PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(), configurationContext); } /** * Process the event publisher file, create it and deploy it * * @param deploymentFileData information about the event publisher * @throws org.apache.axis2.deployment.DeploymentException for any errors */ public void deploy(DeploymentFileData deploymentFileData) throws DeploymentException { String path = deploymentFileData.getAbsolutePath(); if (!deployedEventPublisherFilePaths.contains(path)) { try { processDeployment(deploymentFileData); } catch (Throwable e) { log.error("Cannot deploy event publisher : " + deploymentFileData.getName(), e); throw new DeploymentException("Event publisher file " + deploymentFileData.getName() + " is not deployed ", e); } } else { deployedEventPublisherFilePaths.remove(path); } } private OMElement getEventPublisherOMElement(File eventPublisherFile) throws DeploymentException { String fileName = eventPublisherFile.getName(); OMElement eventPublisherElement; BufferedInputStream inputStream = null; try { inputStream = new BufferedInputStream(new FileInputStream(eventPublisherFile)); XMLStreamReader parser = XMLInputFactory.newInstance(). createXMLStreamReader(inputStream); StAXOMBuilder builder = new StAXOMBuilder(parser); eventPublisherElement = builder.getDocumentElement(); eventPublisherElement.build(); } catch (FileNotFoundException e) { String errorMessage = " file cannot be found with name : " + fileName; log.error(errorMessage, e); throw new DeploymentException(errorMessage, e); } catch (XMLStreamException e) { String errorMessage = "Invalid XML for file " + eventPublisherFile.getName(); log.error(errorMessage, e); throw new DeploymentException(errorMessage, e); } catch (OMException e) { String errorMessage = "XML tags are not properly closed in " + fileName; log.error(errorMessage, e); throw new DeploymentException(errorMessage, e); } finally { try { if (inputStream != null) { inputStream.close(); } } catch (IOException e) { String errorMessage = "Can not close the input stream"; log.error(errorMessage, e); } } return eventPublisherElement; } public void setExtension(String extension) { } /** * Removing already deployed event publisher configuration * * @param filePath the path to the event publisher artifact to be removed * @throws org.apache.axis2.deployment.DeploymentException */ public void undeploy(String filePath) throws DeploymentException { if (!undeployedEventPublisherFilePaths.contains(filePath)) { try { processUndeployment(filePath); } catch (Throwable e) { log.error("Cannot undeploy event publisher : " + new File(filePath).getName(), e); throw new DeploymentException("Event publisher file " + new File(filePath).getName() + " is not undeployed properly", e); } } else { undeployedEventPublisherFilePaths.remove(filePath); } } public void processDeployment(DeploymentFileData deploymentFileData) throws DeploymentException, EventPublisherConfigurationException { File eventPublisherFile = deploymentFileData.getFile(); boolean isEditable = !eventPublisherFile.getAbsolutePath().contains(File.separator + "carbonapps" + File.separator); CarbonEventPublisherService carbonEventPublisherService = EventPublisherServiceValueHolder.getCarbonEventPublisherService(); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); String eventPublisherName = ""; if (!carbonEventPublisherService.isEventPublisherFileAlreadyExist(eventPublisherFile.getName(), tenantId)) { try { OMElement eventPublisherOMElement = getEventPublisherOMElement(eventPublisherFile); if (!(eventPublisherOMElement.getQName().getLocalPart()).equals(EventPublisherConstants.EF_ELEMENT_ROOT_ELEMENT)) { throw new EventPublisherConfigurationException("Wrong event publisher configuration file, Invalid root element " + eventPublisherOMElement.getQName() + " in " + eventPublisherFile.getName()); } boolean isEncrypted = EventPublisherConfigurationHelper.validateEncryptedProperties(eventPublisherOMElement); if (isEditable && !isEncrypted) { String fileName = eventPublisherFile.getName(); EventPublisherConfigurationFilesystemInvoker.delete(fileName); EventPublisherConfigurationFilesystemInvoker.encryptAndSave(eventPublisherOMElement, fileName); return; } EventPublisherConfigurationHelper.validateEventPublisherConfiguration(eventPublisherOMElement); String mappingType = EventPublisherConfigurationHelper.getOutputMappingType(eventPublisherOMElement); if (mappingType != null) { mappingType = mappingType.toLowerCase(); EventPublisherConfiguration eventPublisherConfiguration = EventPublisherConfigurationBuilder.getEventPublisherConfiguration(eventPublisherOMElement, mappingType, isEditable, tenantId); eventPublisherName = eventPublisherConfiguration.getEventPublisherName(); String type = eventPublisherConfiguration.getToAdapterConfiguration().getType(); if (!EventPublisherServiceValueHolder.getOutputEventAdapterTypes().contains(type)) { throw new EventPublisherValidationException("Event Adapter with type: " + type + " does not exist", type); } if (!carbonEventPublisherService.isEventPublisherAlreadyExists(tenantId, eventPublisherName)) { carbonEventPublisherService.addEventPublisherConfiguration(eventPublisherConfiguration); carbonEventPublisherService.addEventPublisherConfigurationFile(createEventPublisherConfigurationFile(eventPublisherName, deploymentFileData.getFile(), EventPublisherConfigurationFile.Status.DEPLOYED, tenantId, null, null), tenantId); log.info("Event Publisher configuration successfully deployed and in active state : " + eventPublisherName); } else { throw new EventPublisherConfigurationException("Event Publisher not deployed and in inactive state," + " since there is a event publisher registered with the same name in this tenant :" + eventPublisherFile.getName()); } } else { throw new EventPublisherConfigurationException("Event Publisher not deployed and in inactive state, " + "since it does not contain a proper mapping type : " + eventPublisherFile.getName()); } } catch (EventPublisherConfigurationException ex) { if (isEditable) { log.error("Error, Event Publisher not deployed and in inactive state, " + ex.getMessage(), ex); carbonEventPublisherService.addEventPublisherConfigurationFile(createEventPublisherConfigurationFile(eventPublisherName, deploymentFileData.getFile(), EventPublisherConfigurationFile.Status.ERROR, tenantId, "Exception when deploying event publisher configuration file:\n" + ex.getMessage(), null), tenantId); } throw new EventPublisherConfigurationException(ex.getMessage(), ex); } catch (EventPublisherValidationException ex) { carbonEventPublisherService.addEventPublisherConfigurationFile(createEventPublisherConfigurationFile(eventPublisherName, deploymentFileData.getFile(), EventPublisherConfigurationFile.Status.WAITING_FOR_DEPENDENCY, tenantId, ex.getMessage(), ex.getDependency()), tenantId); log.info("Event Publisher deployment held back and in inactive state : " + eventPublisherFile.getName() + ", waiting for Output Event Adapter dependency : " + ex.getDependency()); } catch (EventPublisherStreamValidationException e) { carbonEventPublisherService.addEventPublisherConfigurationFile(createEventPublisherConfigurationFile(eventPublisherName, deploymentFileData.getFile(), EventPublisherConfigurationFile.Status.WAITING_FOR_STREAM_DEPENDENCY, tenantId, e.getMessage(), e.getDependency()), tenantId); log.info("Event Publisher deployment held back and in inactive state :" + eventPublisherFile.getName() + ", Stream validation exception : " + e.getMessage()); } catch (Throwable e) { if (isEditable) { log.error("Event Publisher not deployed, invalid configuration found at " + eventPublisherFile.getName() + ", and in inactive state, " + e.getMessage(), e); carbonEventPublisherService.addEventPublisherConfigurationFile(createEventPublisherConfigurationFile(eventPublisherName, deploymentFileData.getFile(), EventPublisherConfigurationFile.Status.ERROR, tenantId, "Deployment exception: " + e.getMessage(), null), tenantId); } throw new EventPublisherConfigurationException(e); } } else { throw new EventPublisherConfigurationException("Event Publisher " + eventPublisherFile.getName() + " is already registered with this tenant (" + tenantId + ")"); } } public void processUndeployment(String filePath) { String fileName = new File(filePath).getName(); log.info("Event Publisher undeployed successfully : " + fileName); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); CarbonEventPublisherService carbonEventPublisherService = EventPublisherServiceValueHolder.getCarbonEventPublisherService(); carbonEventPublisherService.removeEventPublisherConfigurationFile(fileName, tenantId); } public void setDirectory(String directory) { } public void executeManualDeployment(String filePath) throws DeploymentException, EventPublisherConfigurationException { processDeployment(new DeploymentFileData(new File(filePath))); } public void executeManualUndeployment(String filePath) { processUndeployment(filePath); } private EventPublisherConfigurationFile createEventPublisherConfigurationFile( String eventPublisherName, File file, EventPublisherConfigurationFile.Status status, int tenantId, String deploymentStatusMessage, String dependency) { EventPublisherConfigurationFile eventPublisherConfigurationFile = new EventPublisherConfigurationFile(); eventPublisherConfigurationFile.setFileName(file.getName()); eventPublisherConfigurationFile.setFilePath(file.getAbsolutePath()); eventPublisherConfigurationFile.setEventPublisherName(eventPublisherName); eventPublisherConfigurationFile.setStatus(status); eventPublisherConfigurationFile.setDependency(dependency); eventPublisherConfigurationFile.setDeploymentStatusMessage(deploymentStatusMessage); eventPublisherConfigurationFile.setTenantId(tenantId); return eventPublisherConfigurationFile; } public Set<String> getDeployedEventPublisherFilePaths() { return deployedEventPublisherFilePaths; } public Set<String> getUndeployedEventPublisherFilePaths() { return undeployedEventPublisherFilePaths; } }