/** * Copyright OPS4J * * 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. */ package org.ops4j.pax.wicket.spi.support; import static org.ops4j.lang.NullArgumentException.validateNotNull; import static org.ops4j.pax.wicket.api.Constants.APPLICATION_NAME; import static org.osgi.framework.Constants.SERVICE_PID; import java.util.Dictionary; import java.util.Hashtable; import org.ops4j.pax.wicket.api.PaxWicketBeanInjectionSource; import org.ops4j.pax.wicket.api.PaxWicketInjector; import org.ops4j.pax.wicket.internal.injection.BundleAnalysingComponentInstantiationListener; import org.ops4j.pax.wicket.spi.ProxyTargetLocatorFactory; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedService; import org.osgi.util.tracker.ServiceTracker; /** * {@code BundleClassResolverHelper} is a helper to register {@code IClassResolver}. * * @author nmw * @version $Id: $Id */ public final class BundleInjectionProviderHelper { private static final String[] SERVICE_NAMES = { PaxWicketInjector.class.getName(), ManagedService.class.getName() }; private final BundleContext bundleContext; private final Hashtable<String, Object> serviceProperties; private BundleAnalysingComponentInstantiationListener bundleAnalysingComponentInstantiationListener; private final Object lock = new Object(); private final String injectionSource; private ServiceRegistration<?> serviceRegistration; private final ServiceTracker<ProxyTargetLocatorFactory, ProxyTargetLocatorFactory> factoryTracker; /** * Construct an instance of {@code BundleClassResolver}. The injectionSource is defined as constant in * {@link org.ops4j.pax.wicket.api.PaxWicketBeanInjectionSource}. * * @param bundleContext a {@link org.osgi.framework.BundleContext} object. * @param applicationName a {@link java.lang.String} object. * @param injectionSource a {@link java.lang.String} object. * @param factoryTracker a {@link org.osgi.util.tracker.ServiceTracker} object. * @throws java.lang.IllegalArgumentException if any. */ public BundleInjectionProviderHelper(BundleContext bundleContext, String applicationName, String injectionSource, ServiceTracker<ProxyTargetLocatorFactory, ProxyTargetLocatorFactory> factoryTracker) throws IllegalArgumentException { this.injectionSource = injectionSource; this.factoryTracker = factoryTracker; validateNotNull(bundleContext, "bundle"); this.bundleContext = bundleContext; serviceProperties = new Hashtable<String, Object>(); setApplicationName(applicationName); } /** * Sets the service pid of this {@code BundleClassResolverHelper} instance. This is useful if this class resolver * needs to be wired to multiple pax-wicket applications. * * @param servicePid a {@link java.lang.String} object. */ public final void setServicePid(String servicePid) { synchronized (lock) { if (servicePid == null) { serviceProperties.remove(SERVICE_PID); } else { serviceProperties.put(SERVICE_PID, servicePid); } if (serviceRegistration != null) { serviceRegistration.setProperties(serviceProperties); } } } /** * <p>getServicePid.</p> * * @return The service pid of this {@code BundleClassResolverHelper}. Returns {@code null} if not set. */ public final String getServicePid() { synchronized (lock) { return (String) serviceProperties.get(SERVICE_PID); } } /** * Sets the application nane. * * @param applicationName a {@link java.lang.String} object. */ public final void setApplicationName(String applicationName) { synchronized (lock) { if (applicationName == null) { serviceProperties.remove(APPLICATION_NAME); bundleAnalysingComponentInstantiationListener = null; } else { serviceProperties.put(APPLICATION_NAME, applicationName); bundleAnalysingComponentInstantiationListener = new BundleAnalysingComponentInstantiationListener(bundleContext, injectionSource, factoryTracker); } if (serviceRegistration != null) { serviceRegistration.setProperties(serviceProperties); } } } /** * Register class resolver. */ public final void register() { synchronized (lock) { if (serviceRegistration == null) { BundleInjectionResolver resolver = new BundleInjectionResolver(); serviceRegistration = bundleContext.registerService(SERVICE_NAMES, resolver, serviceProperties); } } } /** * Unregister class resolver. */ public final void dispose() { synchronized (lock) { if (serviceRegistration != null) { serviceRegistration.unregister(); serviceRegistration = null; } } } private final class BundleInjectionResolver implements PaxWicketInjector, ManagedService { public void inject(Object toInject, Class<?> toHandle) { validateNotNull(bundleAnalysingComponentInstantiationListener, "bundleAnalysingComponentInstantiationListener"); if (bundleAnalysingComponentInstantiationListener.injectionPossible(toHandle)) { bundleAnalysingComponentInstantiationListener.inject(toInject, toHandle); return; } throw new IllegalStateException("no injections source found"); } @SuppressWarnings("rawtypes") public final void updated(Dictionary dictionary) throws ConfigurationException { synchronized (lock) { if (dictionary == null) { return; } Object applicationNames = dictionary.get(APPLICATION_NAME); if (applicationNames != null) { serviceProperties.put(APPLICATION_NAME, applicationNames); } else { serviceProperties.remove(APPLICATION_NAME); } serviceRegistration.setProperties(serviceProperties); } } } }