All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.petals.activitibpmn.incoming.integration.AbstractOperation Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/**
 * Copyright (c) 2015-2016 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see http://www.gnu.org/licenses/
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.activitibpmn.incoming.integration;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jbi.messaging.Fault;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.ow2.petals.activitibpmn.incoming.ActivitiService;
import org.ow2.petals.activitibpmn.incoming.integration.exception.EmptyRequestException;
import org.ow2.petals.activitibpmn.incoming.integration.exception.InvalidRequestException;
import org.ow2.petals.activitibpmn.incoming.integration.exception.OperationInitializationException;
import org.ow2.petals.component.framework.api.message.Exchange;
import org.ow2.petals.components.activiti.generic._1.InvalidRequest;

import com.ebmwebsourcing.easycommons.lang.ExceptionHelper;

public abstract class AbstractOperation implements ActivitiService {

    /**
     * A pool of marshallers for Java-->XML binding of the operation responses
     */
    protected final ObjectPool marshalerPool;

    /**
     * A pool of unmarshallers for XML-->Java binding of the operation request
     */
    protected final ObjectPool unmarshalerPool;

    protected final Logger log;

    private final QName operationName;

    private final URI faultActor;

    /**
     * @param operationName
     * @param faultActor
     * @param classesToBeBound
     *            Classes that can be (un)marshalled by this integration operation
     * @param log
     * @throws OperationInitializationException
     */
    public AbstractOperation(final QName operationName, final URI faultActor, final Class[] classesToBeBound,
            final Logger log)
            throws OperationInitializationException {
        this.log = log;
        this.operationName = operationName;
        this.faultActor = faultActor;

        try {
            final JAXBContext jaxbContext = JAXBContext.newInstance(classesToBeBound);

            this.marshalerPool = new GenericObjectPool(new MarshalerFactory(jaxbContext));
            this.unmarshalerPool = new GenericObjectPool(new UnmarshalerFactory(jaxbContext));

        } catch (final JAXBException e) {
            throw new OperationInitializationException(this.operationName, e);
        }
    }

    @Override
    public void execute(final Exchange exchange) {

        try {
            try {
                final Source incomingPayload = exchange.getInMessageContentAsSource();
                if (incomingPayload != null) {
                    // Unmarshal incoming request
                    final Unmarshaller unmarshaller = this.unmarshalerPool.borrowObject();
                    final Object incomingObject;
                    try {
                        incomingObject = unmarshaller.unmarshal(incomingPayload);
                    } catch (final Exception e) {
                        throw new InvalidRequestException(this.operationName, e);
                    } finally {
                        this.unmarshalerPool.returnObject(unmarshaller);
                    }
                    
                    try {
                        final V response = this.doExecute((T) incomingObject);
                        
                        try (final InputStream isResponse = this.object2InputStream(response)) {
                            exchange.setOutMessageContent(new StreamSource(isResponse));
                        }
                    } catch (final ClassCastException e) {
                        throw new InvalidRequestException(this.operationName, e);
                    }
                } else {
                    throw new EmptyRequestException(this.operationName);
                }
            } catch (final InvalidRequestException e) {
                this.log.log(Level.WARNING, "Exchange " + exchange.getExchangeId() + " encountered a problem.", e);
                final Fault fault = exchange.createFault();
                final InvalidRequest invalidRequest = new InvalidRequest();
                invalidRequest.setMessage(e.getMessage());
                invalidRequest.setStacktrace(ExceptionHelper.getStackTrace(e));
                try (final InputStream isFault = this.object2InputStream(invalidRequest)) {
                    fault.setContent(new StreamSource(isFault));
                }
                exchange.setFault(fault);
            }
        } catch (final Exception e) {
            this.log.log(Level.SEVERE, "Exchange " + exchange.getExchangeId() + " encountered a problem.", e);
            exchange.setError(e);
        }
    }

    /**
     * Convert an Java object (associated to a WSDL element) to an {@link InputStream} 
     * @param response The Java object to convert
     * @return
     * @throws Exception
     */
    private InputStream object2InputStream(final Object response) throws Exception {
        // TODO: Avoid to use ByteArray(In|Out)put stream, try to pipe streams because of memory problem
        // with big payloads
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            final Marshaller marshaller = this.marshalerPool.borrowObject();
            try {
                marshaller.marshal(response, baos);
            } finally {
                this.marshalerPool.returnObject(marshaller);
            }
        } finally {
            baos.close();
        }

        return new ByteArrayInputStream(baos.toByteArray());

    }

    /**
     * 
     * @param incomingObject
     *            Incoming payload as {@link Object}, not null
     * @return The response as {@link Object}
     */
    public abstract V doExecute(final T incomingObject);

    @Override
    public void log(final Logger logger, final Level logLevel) {
        // NOP: We have nothing to log
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy