| /******************************************************************************* |
| * Copyright (c) 2009, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.e4.core.services.context.spi; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.e4.core.services.IDisposable; |
| import org.eclipse.e4.core.services.context.IEclipseContext; |
| import org.eclipse.e4.core.services.context.IEclipseContextAware; |
| import org.eclipse.e4.core.services.injector.AbstractObjectSupplier; |
| import org.eclipse.e4.core.services.injector.IInjector; |
| import org.eclipse.e4.core.services.injector.InjectorFactory; |
| import org.eclipse.e4.core.services.internal.context.ContextObjectSupplier; |
| import org.eclipse.e4.core.services.internal.context.EclipseContext; |
| |
| /** |
| * An injection factory is used to inject data and services from a context into a domain object. The |
| * injection will try to find fields and methods in the user objects that correspond to the names of |
| * the services present in the context. Subsequent changes to the context after injection will cause |
| * the affected items to be re-injected into the object. Thus the object will remain synchronized |
| * with the context once it has been injected. |
| * <p> |
| * The matching is done using {@link IContextConstants#INJECTION_PREFIX} for fields and methods. For |
| * a context key called "Log", injection will attempt to find field "inject_Log" or method |
| * "inject__method_name(Log log)" that will accept the associated service. Name matching is |
| * case-sensitive. |
| * </p> |
| * <p> |
| * If annotations are supported by the runtime, matching of methods and fields to be injected is |
| * also performed using the annotations defined in packages javax.inject and |
| * org.eclipse.e4.core.services.annotations. |
| * </p> |
| * <p> |
| * The injection of values is generally done as a number of calls. User objects that want to |
| * finalize the injected data (for instance, to perform calculations based on multiple injected |
| * values) can place such calculations in a method with one of the following signatures: |
| * <ul> |
| * <li><code>public void contextSet(IEquinoxContext context);</code></li> |
| * <li><code>public void contextSet();</code></li> |
| * <li>A method with the <code>org.eclipse.e4.core.services.annotations.PostConstruct</code> |
| * annotation.</li> |
| * </ul> |
| * </p> |
| * <p> |
| * This method will be called as a last step in the injection process. For convenience, the |
| * signature of <code>contextSet</code> can be found in the {@link IEclipseContextAware} interface. |
| * User objects don't have to implement this interface for the method to be called, but might find |
| * it convenient to have the method's signature. |
| * </p> |
| * <p> |
| * When injecting values, all fields are injected prior to injection of methods. When values are |
| * removed from the context or the context is disposed, injection of null values occurs in the |
| * reverse order: methods and then fields. As a result, injection methods can safely make use of |
| * injected field values. The order in which methods and fields are injected is undefined, so |
| * injection methods should not rely on other injection methods having been run already. |
| * </p> |
| * <p> |
| * When a context is disposed, the injection factory will attempt to notify all injected objects by |
| * calling a disposal method. Disposal methods are: |
| * <ul> |
| * <li>Methods identified by the "@PreDestory" annotations, and</li> |
| * <li>Methods implementing {@link IDisposable#dispose()}.</li> |
| * </ul> |
| * |
| * @noextend This class is not intended to be extended by clients. |
| * @noinstantiate This class is not intended to be instantiated by clients. |
| */ |
| final public class ContextInjectionFactory { |
| |
| final private static IInjector injector = InjectorFactory.getInjector(); |
| |
| private ContextInjectionFactory() { |
| // prevents instantiations |
| } |
| |
| /** |
| * Injects a context into a domain object. See the class comment for details on the injection |
| * algorithm that is used. |
| * |
| * @param object |
| * The object to perform injection on |
| * @param context |
| * The context to obtain injected values from |
| * @return Returns the injected object |
| */ |
| static public Object inject(Object object, IEclipseContext context) { |
| AbstractObjectSupplier supplier = ContextObjectSupplier.getObjectSupplier(context, |
| injector); |
| injector.inject(object, supplier); |
| return object; |
| } |
| |
| /** |
| * Call a method, injecting the parameters from the context. |
| * |
| * @param object |
| * The object to perform injection on |
| * @param methodName |
| * The method to call |
| * @param context |
| * The context to obtain injected values from |
| * @return the return value of the method call, or <code>null</code> |
| * @throws InvocationTargetException |
| * if an exception was thrown by the invoked method |
| * @throws CoreException |
| * if no matching method was found |
| */ |
| static public Object invoke(Object object, String methodName, IEclipseContext context) |
| throws InvocationTargetException, CoreException { |
| AbstractObjectSupplier supplier = ContextObjectSupplier.getObjectSupplier(context, |
| injector); |
| return injector.invoke(object, methodName, supplier); |
| } |
| |
| /** |
| * Call a method, injecting the parameters from the context. |
| * |
| * @param object |
| * The object to perform injection on |
| * @param methodName |
| * The method to call |
| * @param context |
| * The context to obtain injected values from |
| * @param defaultValue |
| * A value to be returned if the method cannot be called |
| * @return the return value of the method call, or <code>null</code> |
| * @throws InvocationTargetException |
| * if an exception was thrown by the invoked method |
| */ |
| static public Object invoke(Object object, String methodName, IEclipseContext context, |
| Object defaultValue) throws InvocationTargetException { |
| AbstractObjectSupplier supplier = ContextObjectSupplier.getObjectSupplier(context, |
| injector); |
| return injector.invoke(object, methodName, defaultValue, supplier); |
| } |
| |
| /** |
| * Un-injects the context from the object. |
| * |
| * @param object |
| * the object previously injected into the context |
| * @param context |
| * the context previously injected into the object |
| */ |
| static public void uninject(Object object, IEclipseContext context) { |
| ((EclipseContext) context).removeListenersTo(object); |
| } |
| |
| /** |
| * Obtain an instance of the specified class and inject it with the context. |
| * <p> |
| * Class'es scope dictates if a new instance of the class will be created, or existing instance |
| * will be reused. |
| * </p> |
| * |
| * @param clazz |
| * the class to be instantiated |
| * @return an instance of the specified class |
| * @throws InstantiationException |
| * if the class is abstract (or an interface) and can not instantiated |
| * @throws InvocationTargetException |
| * if invoked constructor generated an exception |
| */ |
| static public Object make(Class clazz, final IEclipseContext context) |
| throws InvocationTargetException, InstantiationException { |
| AbstractObjectSupplier supplier = ContextObjectSupplier.getObjectSupplier(context, |
| injector); |
| return injector.make(clazz, supplier); |
| } |
| } |