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

org.fabric3.implementation.pojo.manager.ImplementationManagerImpl Maven / Gradle / Ivy

The newest version!
/*
 * Fabric3
 * Copyright (c) 2009-2015 Metaform Systems
 *
 * 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.
 *
 * Portions originally based on Apache Tuscany 2007
 * licensed under the Apache 2.0 license.
 */
package org.fabric3.implementation.pojo.manager;

import java.net.URI;
import java.util.HashSet;
import java.util.Set;

import org.fabric3.api.model.type.java.Injectable;
import org.fabric3.implementation.pojo.spi.reflection.LifecycleInvoker;
import org.fabric3.implementation.pojo.spi.reflection.ObjectCallbackException;
import org.fabric3.spi.container.component.InstanceDestructionException;
import org.fabric3.spi.container.component.InstanceInitException;
import org.fabric3.spi.container.component.InstanceLifecycleException;
import org.fabric3.spi.container.invocation.Message;
import org.fabric3.spi.container.invocation.MessageCache;
import org.fabric3.spi.container.objectfactory.Injector;
import org.fabric3.spi.container.objectfactory.ObjectCreationException;
import org.fabric3.spi.container.objectfactory.ObjectFactory;

/**
 *
 */
public class ImplementationManagerImpl implements ImplementationManager {
    private URI componentUri;
    private final ObjectFactory constructor;
    private Injectable[] injectables;
    private final Injector[] injectors;
    private final LifecycleInvoker initInvoker;
    private final LifecycleInvoker destroyInvoker;
    private final ClassLoader cl;
    private final boolean reinjectable;
    private Set> updatedInjectors;

    public ImplementationManagerImpl(URI componentUri,
                                     ObjectFactory constructor,
                                     Injectable[] injectables,
                                     Injector[] injectors,
                                     LifecycleInvoker initInvoker,
                                     LifecycleInvoker destroyInvoker,
                                     boolean reinjectable,
                                     ClassLoader cl) {
        this.componentUri = componentUri;
        this.constructor = constructor;
        this.injectables = injectables;
        this.injectors = injectors;
        this.initInvoker = initInvoker;
        this.destroyInvoker = destroyInvoker;
        this.reinjectable = reinjectable;
        this.cl = cl;
        if (reinjectable) {
            this.updatedInjectors = new HashSet<>();
        } else {
            this.updatedInjectors = null;
        }
    }

    public Object newInstance() throws ObjectCreationException {
        ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(cl);
        try {
            // FABRIC-40: if a component invokes services from a setter, the message content will be over-written. Save so it can be restored after instance
            // injection.
            Message message = MessageCache.getMessage();
            Object content = message.getBody();
            Object instance = constructor.getInstance();
            if (injectors != null) {
                for (Injector injector : injectors) {
                    injector.inject(instance);
                }
            }
            // restore the original contents
            message.setBody(content);
            return instance;
        } finally {
            Thread.currentThread().setContextClassLoader(oldCl);
        }
    }

    public void start(Object instance) throws InstanceInitException {
        if (initInvoker != null) {
            ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
            try {
                Thread.currentThread().setContextClassLoader(cl);
                initInvoker.invoke(instance);
            } catch (ObjectCallbackException e) {
                throw new InstanceInitException("Error initializing instance for: " + componentUri, e);
            } finally {
                Thread.currentThread().setContextClassLoader(oldCl);
            }
        }
    }

    public void stop(Object instance) throws InstanceDestructionException {
        try {
            if (destroyInvoker != null) {
                ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
                try {
                    Thread.currentThread().setContextClassLoader(cl);
                    destroyInvoker.invoke(instance);
                } finally {
                    Thread.currentThread().setContextClassLoader(oldCl);
                }
            }
        } catch (ObjectCallbackException e) {
            throw new InstanceDestructionException("Error destroying instance for: " + componentUri, e);
        }
    }

    public void reinject(Object instance) throws InstanceLifecycleException {
        if (!reinjectable) {
            throw new IllegalStateException("Implementation is not reinjectable:" + componentUri);
        }
        try {
            for (Injector injector : updatedInjectors) {
                injector.inject(instance);
            }
            updatedInjectors.clear();
        } catch (ObjectCreationException ex) {
            throw new InstanceLifecycleException("Unable to reinject references on component: " + componentUri, ex);
        }
    }

    public void updated(Object instance, String referenceName) {
        if (instance != null && !reinjectable) {
            throw new IllegalStateException("Implementation is not reinjectable: " + componentUri);
        }
        for (int i = 0; i < injectables.length; i++) {
            Injectable attribute = injectables[i];
            if (attribute.getName().equals(referenceName)) {
                Injector injector = injectors[i];
                if (instance != null) {
                    updatedInjectors.add(injector);
                }
            }
        }
    }

    public void removed(Object instance, String referenceName) {
        if (instance != null && !reinjectable) {
            throw new IllegalStateException("Implementation is not reinjectable: " + componentUri);
        }
        for (int i = 0; i < injectables.length; i++) {
            Injectable attribute = injectables[i];
            if (attribute.getName().equals(referenceName)) {
                Injector injector = injectors[i];
                injector.clearObjectFactory();
                if (instance != null) {
                    updatedInjectors.add(injector);
                }
            }
        }

    }

}