/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you 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.openengsb.core.workflow.drools.internal;
import java.lang.reflect.Proxy;
import java.util.Dictionary;
import java.util.Hashtable;
import org.openengsb.core.api.Constants;
import org.openengsb.core.api.DomainEvents;
import org.openengsb.core.workflow.api.WorkflowService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.BundleTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Registers a {@link BundleTracker} to automatically inject an appropriate {@link DomainEvents}-service into
* domain-bundles. A {@link ForwardHandler} is used to provide an implementation for the service. It forwards all
* invocation to the {@link WorkflowService}. It uses the {@link Constants#DOMAIN_NAME_HEADER} field in bundle-headers
* to determine the classname for the events-interface. Services are registered to the domain-bundle's bundleContext, so
* they are stopped automatically when the bundle is stopped.
*/
public class DomainEventsServicesManager {
private static final Logger LOGGER = LoggerFactory.getLogger(DomainEventsServicesManager.class);
private BundleContext bundleContext;
private WorkflowService workflowService;
private BundleTracker bundleTracker;
public void start() {
bundleTracker = new BundleTracker(bundleContext, Bundle.ACTIVE, new BundleTrackerCustomizer() {
@Override
public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
}
@Override
public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
}
@Override
public Object addingBundle(Bundle bundle, BundleEvent event) {
return startDomainServices(bundle);
}
});
bundleTracker.open();
}
public void stop() {
bundleTracker.close();
}
private synchronized ServiceRegistration<?> startDomainServices(Bundle bundle) {
LOGGER.trace("checking whether Bundle {} is a Domain", bundle);
Dictionary<String, String> headers = bundle.getHeaders();
String domainname = headers.get(Constants.DOMAIN_NAME_HEADER);
if (domainname == null) {
LOGGER.trace("Bundle {} is not a domain, ignoring", bundle);
return null;
}
String interfacename = headers.get(Constants.DOMAIN_EVENTS_INTERFACE_HEADER);
if (interfacename == null) {
LOGGER.info(
"Domain-bundle {} has not DomainEvents-interface. There are no Events to be thrown in this domain",
bundle);
return null;
}
LOGGER.debug("Registering DomainEvents-service {} for Domain-bundle {}.", interfacename, bundle);
try {
return doRegisterService(bundle, interfacename, domainname);
} catch (ClassNotFoundException e) {
LOGGER.error("unable to register DomainEventsService for bundle {}", bundle, e);
}
return null;
}
private ServiceRegistration<?> doRegisterService(Bundle bundle, String interfacename, String domainname)
throws ClassNotFoundException {
Object proxy = createProxy(bundle, interfacename);
Hashtable<String, Object> props = new Hashtable<String, Object>();
props.put(org.osgi.framework.Constants.SERVICE_PID, String.format("domain.%s.events", domainname));
props.put("openengsb.service.type", "domain-events");
LOGGER.debug("Registering DomainEvents-service for Bundle {} with properties {}", bundle, props);
return bundle.getBundleContext().registerService(interfacename, proxy, props);
}
private Object createProxy(Bundle bundle, String interfacename) throws ClassNotFoundException {
Class<?> interfaceClass = bundle.loadClass(interfacename);
ClassLoader classLoader = interfaceClass.getClassLoader();
Class<?>[] classes = new Class<?>[]{ DomainEvents.class, interfaceClass };
ForwardHandler forwardHandler = new ForwardHandler(workflowService);
return Proxy.newProxyInstance(classLoader, classes, forwardHandler);
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
public void setWorkflowService(WorkflowService workflowService) {
this.workflowService = workflowService;
}
}