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

org.csc.phynixx.connection.DynaPhynixxManagedConnectionFactory Maven / Gradle / Ivy

The newest version!
package org.csc.phynixx.connection;

/*
 * #%L
 * phynixx-connection
 * %%
 * Copyright (C) 2014 csc
 * %%
 * 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.
 * #L%
 */


import org.csc.phynixx.common.exceptions.DelegatedRuntimeException;
import org.csc.phynixx.common.generator.IDGenerator;
import org.csc.phynixx.common.generator.IDGenerators;
import org.csc.phynixx.common.logger.IPhynixxLogger;
import org.csc.phynixx.common.logger.PhynixxLogManager;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**

 * provided generic proxies on base of java DynaProxies

 * This proxy
 *
 * @param 
 */
class DynaPhynixxManagedConnectionFactory extends AbstractDynaProxyFactory {

    private static final IDGenerator idGenerator = IDGenerators.createLongGenerator(1,true);

    private Class connectionInterface;
    private CloseStrategy closeStrategy=null;

    DynaPhynixxManagedConnectionFactory(Class connectionInterface, CloseStrategy closeStrategy, boolean synchronize) {
        super(new Class[]{connectionInterface},
                new Class[]{IPhynixxConnection.class, IPhynixxManagedConnection.class},
                new Class[]{IXADataRecorderAware.class, ICloseable.class, IAutoCommitAware.class},
                synchronize);
        this.connectionInterface = connectionInterface;
        this.closeStrategy= closeStrategy;


    }

    DynaPhynixxManagedConnectionFactory(Class connectionInterface,CloseStrategy closeStrategy) {
        this(connectionInterface, closeStrategy, true);
    }

    IPhynixxManagedConnection getManagedConnection(C coreConnection) {

        Long connectionId = null;
        synchronized (idGenerator) {
            connectionId = idGenerator.generate();
        }
        ConnectionPhynixxGuard proxy = new ConnectionPhynixxGuard(connectionId, connectionInterface, coreConnection,closeStrategy);

        IPhynixxManagedConnection proxied = (IPhynixxManagedConnection)
                Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                        this.getImplementedInterfaces(), proxy);
        proxy.proxiedObject = proxied;
        return proxied;
    }


    class ConnectionPhynixxGuard extends PhynixxManagedConnectionGuard implements InvocationHandler {




        private final IPhynixxLogger log = PhynixxLogManager.getLogger(ConnectionPhynixxGuard.class);
        /**
         * As the proxy contains more information than the current implentation we have to store
         * the proxy an use it in all call backs
         */
        private IPhynixxManagedConnection proxiedObject;

        ConnectionPhynixxGuard(long id, Class connectionInterface, C connection, CloseStrategy closeStrategy) {
            super(id, connectionInterface, connection,closeStrategy);
        }

        /**
         * if the interface method is decorated with {@link org.csc.phynixx.connection.RequiresTransaction}
         *
         * @param method
         * @return
         */
        private boolean requiresTransaction(Method method) {

            Annotation[] annotations = method.getDeclaredAnnotations();
            if (annotations == null || annotations.length == 0) {
                return false;
            }
            for (int i = 0; i < annotations.length; i++) {
                if (RequiresTransaction.class.isAssignableFrom(annotations[i].annotationType())) {
                    RequiresTransaction requiresTransactionAnnotation = (RequiresTransaction) annotations[i];
                    return requiresTransactionAnnotation.value();
                }
            }

            return false;

        }


        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {


            /**
             * methods of the IConnectionProxy are redirected to the current object
             */

            // execute
            try {
                if (DynaPhynixxManagedConnectionFactory.this.declaredBySystemInterface(method)) {
                    // System.out.println("Thread " + Thread.currentThread()+" Connection IF expected to " + this+" on "+method);
                    Object obj = null;
                    if (this.isSynchronized()) {
                        synchronized (this) {
                            obj = method.invoke(this, args);
                        }
                    } else {
                        obj = method.invoke(this, args);
                    }
                    return obj;
                } else if (DynaPhynixxManagedConnectionFactory.this.declaredBySupportedInterface(method)) {

                    Object target = this.getCoreConnection();

                    // System.out.println("Thread " + Thread.currentThread()+" Delegated to Connection " + target+" on "+method);

                    Object obj = null;
                    boolean requireTransaction = this.requiresTransaction(method);
                    try {
                        if (this.isSynchronized()) {
                            synchronized (this) {
                                if (requireTransaction) {
                                    this.fireConnectionRequiresTransaction();
                                }
                                obj = method.invoke(target, args);
                                if (requireTransaction) {
                                    fireConnectionRequiresTransactionExecuted();
                                }
                            }
                        } else {
                            if (requireTransaction) {
                                this.fireConnectionRequiresTransaction();
                            }
                            obj = method.invoke(target, args);
                            if (requireTransaction) {
                                fireConnectionRequiresTransactionExecuted();
                            }
                        }
                        return obj;
                    } catch (InvocationTargetException targetException) {
                        if (requireTransaction) {
                            Exception e = null;
                            if (!(targetException.getTargetException() instanceof Exception)) {
                                e = new Exception(targetException.getCause());
                            } else {
                                e = (Exception) (targetException.getTargetException());
                            }
                            fireConnectionRequiresTransactionExecuted(e);
                        }


                        // rethrow;
                        throw targetException;

                    }
                } else {
                    Object obj = null;
                    if (this.isSynchronized()) {
                        synchronized (this) {
                            obj = method.invoke(this, args);
                        }
                    } else {
                        obj = method.invoke(this, args);
                    }
                    return obj;
                }
            } catch (InvocationTargetException targetEx) {
                // log.fatal("Error calling method " + method + " on " + target + " :: " + targetEx.getMessage() + "\n" + ExceptionUtils.getStackTrace(targetEx.getTargetException()));
                throw new DelegatedRuntimeException("Invoking " + method, targetEx.getTargetException());
            } catch (Throwable ex) {
                // log.fatal("Error calling method " + method + " on " + target + " :: " + ex + "\n" + ExceptionUtils.getStackTrace(ex));
                throw new DelegatedRuntimeException("Invoking " + method, ex);
            }
        }

        protected IPhynixxManagedConnection getObservableProxy() {
            return (IPhynixxManagedConnection) proxiedObject;
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy