Package org.wso2.carbon.rulecep.service

Source Code of org.wso2.carbon.rulecep.service.ServiceBuilder

/*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF 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.rulecep.service;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.deployment.DeploymentConstants;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.deployment.DescriptionBuilder;
import org.apache.axis2.deployment.repository.util.ArchiveReader;
import org.apache.axis2.deployment.repository.util.DeploymentFileData;
import org.apache.axis2.description.*;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.engine.MessageReceiver;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.rulecep.adapters.InputManager;
import org.wso2.carbon.rulecep.adapters.OutputManager;
import org.wso2.carbon.rulecep.adapters.impl.OMElementResourceAdapter;
import org.wso2.carbon.rulecep.adapters.impl.POJOResourceAdapter;
import org.wso2.carbon.rulecep.adapters.service.InputOutputAdaptersService;
import org.wso2.carbon.rulecep.commons.descriptions.*;
import org.wso2.carbon.rulecep.commons.descriptions.service.OperationDescription;
import org.wso2.carbon.rulecep.commons.descriptions.service.ServiceDescription;
import org.wso2.carbon.rulecep.commons.descriptions.service.ServiceDescriptionFactory;
import org.wso2.carbon.rulecep.commons.descriptions.service.ServiceDescriptionSerializer;
import org.wso2.carbon.rulecep.commons.utils.OMElementHelper;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
* Creates Rule Services based on the rule deployment file information
*/
public class ServiceBuilder {

    private static Log log = LogFactory.getLog(ServiceBuilder.class);

    private InputOutputAdaptersService inputOutputAdaptersService;
    private final ArchiveReader archiveReader = new ArchiveReader();
    private AxisConfiguration axisConfig;
    private ConfigurationContext configurationContext;
    private static final Axis2MessageInterceptor INTERCEPTOR = new Axis2MessageInterceptor();
    private static final XPathFactory AXIOM_XPATH_FACTORY = new AXIOMXPathFactory();
    private static final XPathSerializer AXIOM_XPATH_SERIALIZER = new AXIOMXPathSerializer();
    private static final OMElementHelper OM_ELEMENT_HELPER = OMElementHelper.getInstance();
    private final ServiceDeployerInformation deployerInformation;
    private final ResourceLoader resourceLoader;

    public ServiceBuilder(ConfigurationContext configurationContext,
                          ServiceDeployerInformation deployerInformation) {
        this.deployerInformation = deployerInformation;
        this.configurationContext = configurationContext;
        this.axisConfig = configurationContext.getAxisConfiguration();
        ServiceManger manger = ServiceManger.getInstance();
        this.inputOutputAdaptersService = manger.getInputOutputAdaptersService();
        this.resourceLoader = new ResourceLoader(manger.getRegistryService());
    }

    /**
     * @param serviceGroup       <code>AxisServiceGroup</code> instance of the services to be built
     * @param deploymentFileData Information about rule archive or rule service file
     * @return A list of services built from the rule service archive or rule service file
     * @throws AxisFault for any errors during service build operation
     */
    public List<AxisService> build(AxisServiceGroup serviceGroup,
                                   DeploymentFileData deploymentFileData) throws AxisFault {
        // load services from WSDL
        HashMap<String, AxisService> wsdlservice =
                archiveReader.processWSDLs(deploymentFileData);
        if (wsdlservice != null && wsdlservice.size() > 0) {
            for (AxisService service : wsdlservice.values()) {
                if (service == null) {
                    continue;
                }
                Iterator operations = service.getOperations();
                while (operations.hasNext()) {
                    AxisOperation axisOperation = (AxisOperation) operations.next();
                    axisConfig.getPhasesInfo().setOperationPhases(axisOperation);
                }
            }
        }

        // create rule services from the .rsl file
        InputStream inputStream = null;
        ArrayList<AxisService> serviceList = null;
        String ruleServiceFileName = deploymentFileData.getName()//TODO validate
        if (ruleServiceFileName.endsWith(deployerInformation.getFileExtension())) {
            try {
                inputStream = new FileInputStream(deploymentFileData.getFile());
            } catch (FileNotFoundException e) {
                handleException("The rule service file can not be found. The file name was :" +
                        ruleServiceFileName);
            }
            if (inputStream == null) {
                handleException("Cannot get a input stream from the file :" +
                        ruleServiceFileName);
            }
        } else if (ruleServiceFileName.endsWith(deployerInformation.getArchiveExtension())) {
            String serviceName =
                    ruleServiceFileName.substring(0, ruleServiceFileName.lastIndexOf("."));
            String rslFile = serviceName + "." + deployerInformation.getFileExtension();
            inputStream = resourceLoader.loadResourceFromLocal(rslFile,
                    deploymentFileData.getClassLoader());
            if (inputStream == null) {     //TODO read a service xml parameter
                handleException("Cannot find the .rsl file from the rule service archive. " +
                        "The file should be " + rslFile);
            }
            if (containsServiceXML(deploymentFileData.getAbsolutePath())) {
                serviceList = archiveReader.processServiceGroup(
                        deploymentFileData.getAbsolutePath(), deploymentFileData,
                        serviceGroup, deploymentFileData.getFile().isDirectory(), wsdlservice,
                        configurationContext);
            }
        } else {
            handleException("Invalid file type! Either .rsl or .aar file" +
                    " should be as the rule service. File was : " + ruleServiceFileName);
        }

        ServiceDescription ruleServiceDescription = createRuleServiceDescription(inputStream);

        // can get the operaton extension points here.

        AxisService ruleService = createAxisService(ruleServiceDescription,
                serviceGroup, deploymentFileData, wsdlservice);
        if (ruleService == null) {
            handleException(" Can not create rule services form the file : " +
                    deploymentFileData.getName());
        }
        // process the service XML
        List<AxisService> servicesToBeUsed = new ArrayList<AxisService>();
        if (serviceList != null) {
            servicesToBeUsed.addAll(serviceList);
        } else {
            servicesToBeUsed.add(ruleService);
        }

        for (AxisService axisService : servicesToBeUsed) {
            if (axisService == null) {
                continue;
            }
            String name = axisService.getName();
            assert ruleService != null;
            if (!ruleService.getName().equals(name)) {
                continue;
            }
            finalizeBuild(axisService, ruleServiceDescription, deploymentFileData);
        }
        return servicesToBeUsed;
    }


    /**
     * //TODO - remove
     * Prepare the inputs as a composite one input.This is because , in a rule service ,
     * inputs are similar to teh argument
     *
     * @param resourceDescriptions A list of inputs
     * @param classLoader          Service class loader
     * @return A prepared composite input
     */
    private List<ResourceDescription> prepareInputs(List<ResourceDescription> resourceDescriptions,
                                                    ClassLoader classLoader) {
        if (resourceDescriptions.isEmpty() || resourceDescriptions.size() == 1) {
            return resourceDescriptions;
        }
        ResourceDescription composite = new ResourceDescription();
        for (ResourceDescription description : resourceDescriptions) {
            if (inputOutputAdaptersService.getFactAdapterFactory().containsInputAdapter(
                    description.getType()) || description.getExpression() != null) {
                return resourceDescriptions;
            } else {
                composite.addChildResource(description);
            }
        }
        composite.setResourceClassLoader(classLoader);
        composite.setType(POJOResourceAdapter.TYPE);
        List<ResourceDescription> descriptions = new ArrayList<ResourceDescription>();
        descriptions.add(composite);
        return descriptions;
    }

    /**
     * Creates a RuleServiceDescription instance from the .rsl file
     *
     * @param inputStream Stream of the .rsl file
     * @return a <code>RuleServiceDescription</code> instance
     */
    private ServiceDescription createRuleServiceDescription(InputStream inputStream) {
        try {
            OMElement omElement = OM_ELEMENT_HELPER.toOM(inputStream);
            omElement.detach();
            return ServiceDescriptionFactory.create(omElement,
                    AXIOM_XPATH_FACTORY, deployerInformation.getExtensionBuilder());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ignored) {
                }
            }
        }
    }

    /**
     * @param serviceDescription Information about the rule service
     * @param axisServiceGroup   service group for the service to be built
     * @param deploymentFileData Information about the rule service artifact
     * @param wsdlServices       A list of services loaded from the WSDL if there is a WSDL
     * @return An <code>AxisService </code> representing the rule service
     * @throws DeploymentException for any error during service creation
     */
    private AxisService createAxisService(ServiceDescription serviceDescription,
                                          AxisServiceGroup axisServiceGroup,
                                          DeploymentFileData deploymentFileData,
                                          Map<String, AxisService> wsdlServices) throws DeploymentException {

        final Map<String, AxisService> serviceMap = new HashMap<String, AxisService>();
        AxisService axisService = null;
        OMElement serviceXML =
                ServiceDescriptionSerializer.serializeToServiceXML(serviceDescription, null,
                        AXIOM_XPATH_SERIALIZER);
        String serviceName = DescriptionBuilder.getShortFileName(deploymentFileData.getName());
        if (serviceName != null) {
            axisService = wsdlServices.get(serviceName);
        }
        if (axisService == null) {
            axisService = wsdlServices.get(
                    DescriptionBuilder.getShortFileName(deploymentFileData.getName()));
        }
        if (axisService == null) {
            axisService = new AxisService(serviceName);
        } else {
            axisService.setWsdlFound(true);
            axisService.setCustomWsdl(true);
        }

        axisService.setParent(axisServiceGroup);
        axisService.setClassLoader(deploymentFileData.getClassLoader());

        org.apache.axis2.deployment.ServiceBuilder serviceBuilder =
                new org.apache.axis2.deployment.ServiceBuilder(configurationContext, axisService);
        serviceBuilder.setWsdlServiceMap((HashMap<String, AxisService>) wsdlServices);
        AxisService service = serviceBuilder.populateService(serviceXML);
        serviceMap.put(service.getName(), service);
        return service;
    }

    /**
     * The final step of the rule service build
     * Create rule engine , wsdl and message receivers
     *
     * @param axisService            <code>AxisService</code> being built
     * @param ruleServiceDescription Information about the rule service
     * @param deploymentFileData     Information about the rule service artifact
     * @throws AxisFault for any error during this operation
     */
    private void finalizeBuild(AxisService axisService, ServiceDescription ruleServiceDescription,
                               DeploymentFileData deploymentFileData) throws AxisFault {

        axisService.addParameter(new Parameter(ServiceConstants.SERVICE_TYPE,
                deployerInformation.getServiceType()));
        axisService.addParameter(new Parameter(deployerInformation.getServicePathKey(),
                deploymentFileData.getFile().getAbsolutePath()));
        if (containsServiceXML(deploymentFileData.getAbsolutePath())) {
            axisService.addParameter(new Parameter(deployerInformation.getServiceArchiveGeneratableKey(), true));
        } else {
            axisService.addParameter(new Parameter(deployerInformation.getServiceArchiveGeneratableKey(), false));
        }
        axisService.setTargetNamespace(ruleServiceDescription.getTargetNamespace());
        axisService.setTargetNamespacePrefix(ruleServiceDescription.getTargetNSPrefix());

        ServiceEngineFactory serviceEngineFactory = deployerInformation.getServiceProvider();
        ServiceEngine serviceEngine =
                serviceEngineFactory.createServiceEngine(ruleServiceDescription, axisService, resourceLoader);
        // Start WSDL generation
        ServiceWSDLBuilder ruleServiceWSDLBuilder = new ServiceWSDLBuilder(axisService,
                ruleServiceDescription);
        ruleServiceWSDLBuilder.startBuild();
        Iterator<OperationDescription> iterator =
                ruleServiceDescription.getOperationDescriptions();
        MessageReceiverFactory messageReceiverFactory =
                deployerInformation.getMessageReceiverFactory();
        while (iterator.hasNext()) {
            OperationDescription opDes = iterator.next();
            AxisOperation axisOperation = axisService.getOperation(opDes.getName());
            // creates a rule service message receiver
            List<ResourceDescription> inputs = opDes.getFactDescriptions();
            List<ResourceDescription> outputs = opDes.getResultDescriptions();

            // if the operation is in-out but there is no result
            if (!(axisOperation instanceof InOnlyAxisOperation)) {

                if (outputs.isEmpty()) {

                    // this is because opDes.getResultDescriptions does not return a view
                    // which is wrong and should fix properly in the next release TODO
                    outputs = new ArrayList<ResourceDescription>();

                    if (log.isDebugEnabled()) {
                        log.debug("There is no results for the operation " +
                                axisOperation.getName() + ". It is not an in-only operation.");
                    }

                    ResourceDescription description = new ResourceDescription();
                    description.setType(OMElementResourceAdapter.TYPE);
                    description.setName(ServiceConstants.DEFAULT_WRAPPER_NAME);
                    outputs.add(description);
                }
            }

            // create input and output managers
            InputManager inputManager =
                    inputOutputAdaptersService.createInputManager(
                            prepareInputs(inputs, axisService.getClassLoader()),
                            INTERCEPTOR);
            OutputManager outputManager =
                    inputOutputAdaptersService.createOutputManager(outputs, INTERCEPTOR);


            // build the in-message
            ruleServiceWSDLBuilder.buildInMessage(axisOperation, inputs,
                    inputOutputAdaptersService.getFactAdapterFactory());

            //selectively create the message receiver
            MessageReceiver messageReceiver;
            if (axisOperation instanceof InOnlyAxisOperation) {
                messageReceiver = messageReceiverFactory.createInOnlyMessageReceiver(serviceEngine,
                        inputManager, opDes);
            } else {
                ruleServiceWSDLBuilder.buildOutMessage(axisOperation, outputs,
                        inputOutputAdaptersService.getResultAdapterFactory());
                messageReceiver = messageReceiverFactory.createInOutMessageReceiver(serviceEngine,
                        inputManager, outputManager, opDes);
            }

            if (serviceEngine.canListenForResult()) {
                serviceEngine.registerResultListener(outputManager, opDes);
            }

            axisOperation.setMessageReceiver(messageReceiver);
        }

        if (this.deployerInformation.getDeploymentExtenstion() != null){
            this.deployerInformation.getDeploymentExtenstion().doDeploy(axisService,
                    ruleServiceDescription);
        }

        ruleServiceWSDLBuilder.endBuild();
    }

    /**
     * Checks the existence of the service XML
     *
     * @param fileName archive file name
     * @return <code>true</code> if there is a services.xml
     * @throws DeploymentException for any error during operation
     */
    private boolean containsServiceXML(String fileName) throws DeploymentException {
        ZipInputStream zin = null;
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(fileName);
            zin = new ZipInputStream(fin);
            ZipEntry entry;
            while ((entry = zin.getNextEntry()) != null) {
                if (entry.getName().equalsIgnoreCase(DeploymentConstants.SERVICES_XML)) {
                    return true;
                }
            }
        } catch (FileNotFoundException e) {
            handleException("Cannot find the file : " + fileName, e);
        } catch (IOException e) {
            handleException("IO error reading the file : " + fileName, e);
        } finally {
            if (zin != null) {
                try {
                    zin.close();
                } catch (IOException ignored) {

                }
            }
            if (fin != null) {
                try {
                    fin.close();
                } catch (IOException ignored) {
                }
            }
        }
        return false;
    }


    private void handleException(String msg) throws DeploymentException {
        log.error(msg);
        throw new DeploymentException(msg);
    }

    private void handleException(String msg, Throwable e) throws DeploymentException {
        log.error(msg, e);
        throw new DeploymentException(msg, e);
    }
}
TOP

Related Classes of org.wso2.carbon.rulecep.service.ServiceBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.