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

org.picocontainer.behaviors.HiddenImplementation Maven / Gradle / Ivy

There is a newer version: 2.15
Show newest version
/*****************************************************************************
 * Copyright (C) PicoContainer Organization. All rights reserved.            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *                                                                           *
 * Original code by                                                          *
 *****************************************************************************/
package org.picocontainer.behaviors;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;

import org.picocontainer.ComponentAdapter;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.PicoContainer;
import org.picocontainer.PicoCompositionException;

/**
 * This component adapter makes it possible to hide the implementation
 * of a real subject (behind a proxy) provided the key is an interface.
 * 

* This class exists here, because a) it has no deps on external jars, b) dynamic proxy is quite easy. * The user is prompted to look at picocontainer-gems for alternate and bigger implementations. * * @author Aslak Hellesøy * @author Paul Hammant * @see org.picocontainer.gems.adapters.HotSwappingComponentAdapter for a more feature-rich version of this class. */ @SuppressWarnings("serial") public class HiddenImplementation extends AbstractBehavior { /** * Creates an ImplementationHidingComponentAdapter with a delegate * @param delegate the component adapter to which this adapter delegates */ public HiddenImplementation(ComponentAdapter delegate) { super(delegate); } public T getComponentInstance(final PicoContainer container, Type into) throws PicoCompositionException { ComponentAdapter delegate = getDelegate(); Object componentKey = delegate.getComponentKey(); Class[] classes; if (componentKey instanceof Class && ((Class) delegate.getComponentKey()).isInterface()) { classes = new Class[]{(Class) delegate.getComponentKey()}; } else if (componentKey instanceof Class[]) { classes = (Class[]) componentKey; } else { return delegate.getComponentInstance(container, into); } verifyInterfacesOnly(classes); return createProxy(classes, container, delegate.getComponentImplementation().getClassLoader()); } public String getDescriptor() { return "Hidden"; } @SuppressWarnings("unchecked") protected T createProxy(Class[] interfaces, final PicoContainer container, final ClassLoader classLoader) { final PicoContainer container1 = container; return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() { private final PicoContainer container = container1; private volatile Object instance; public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { if (instance == null) { synchronized (HiddenImplementation.this) { if (instance == null) { instance = getDelegate().getComponentInstance(container, NOTHING.class); } } } return invokeMethod(instance, method, args, container); } }); } protected Object invokeMethod(Object componentInstance, Method method, Object[] args, PicoContainer container) throws Throwable { ComponentMonitor componentMonitor = currentMonitor(); try { componentMonitor.invoking(container, this, method, componentInstance, args); long startTime = System.currentTimeMillis(); Object rv = method.invoke(componentInstance, args); componentMonitor.invoked(container, this, method, componentInstance, System.currentTimeMillis() - startTime, args, rv); return rv; } catch (final InvocationTargetException ite) { componentMonitor.invocationFailed(method, componentInstance, ite); throw ite.getTargetException(); } } private void verifyInterfacesOnly(Class[] classes) { for (Class clazz : classes) { if (!clazz.isInterface()) { throw new PicoCompositionException( "Class keys must be interfaces. " + clazz + " is not an interface."); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy