blob: 8bc866b1eaa219fd87a8645a043dc9da75be9338 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Florian Pirchner - Initial implementation
*
*/
package org.eclipse.osbp.ecview.extension.services;
import java.net.URL;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.URI;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.BundleTrackerCustomizer;
import org.eclipse.osbp.ecview.core.common.extender.IECViewCache;
/**
* This extender scans all bundles about .ecview_xmi files. Any of them will be
* passed to the {@link IECViewCache}. If bundles are being stopped, the
* contained .ecview_xmi files will be unregistered from {@link IECViewCache}.
*/
@Component
public class ECViewCacheBuilder {
/** The Constant FACTORY_MODEL_EXTENDER. */
public static final String FACTORY_MODEL_EXTENDER = "Factory-Model";
/** The context. */
@SuppressWarnings("unused")
private ComponentContext context;
/** The tracker. */
private BundleTracker<List<URL>> tracker;
/** The cache. */
private IECViewCache cache;
/**
* Instantiates a new EC view cache builder.
*/
public ECViewCacheBuilder() {
}
/**
* Activate.
*
* @param context
* the context
*/
@Activate
protected void activate(ComponentContext context) {
this.context = context;
tracker = new BundleTracker<>(context.getBundleContext(),
stateCriteria(), new Customizer());
tracker.open();
}
/**
* State criteria.
*
* @return the int
*/
protected int stateCriteria() {
return Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE
| Bundle.STOPPING;
}
/**
* Deactivate.
*
* @param context
* the context
*/
@Deactivate
protected void deactivate(ComponentContext context) {
tracker.close();
this.context = null;
}
/**
* Returns true, if the bundle contains the header.
*
* @param bundle
* the bundle
* @param header
* the header
* @return true, if successful
*/
private boolean containsHeader(Bundle bundle, String header) {
Dictionary<String, String> headers = bundle.getHeaders();
Enumeration<String> keys = headers.keys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
if (key.equals(header)) {
return true;
}
}
return false;
}
/**
* Searches for all ECView translations in the given bundle.
*
* @param bundle
* the bundle
* @return the list
*/
private List<URL> internalFindURLs(Bundle bundle) {
List<URL> results = new ArrayList<URL>();
BundleWiring wiring = bundle.adapt(BundleWiring.class);
results.addAll(wiring.findEntries("/", "*." + ECViewCache.ECVIEW_XMI,
BundleWiring.LISTRESOURCES_RECURSE));
Set<String> fragments = new HashSet<String>();
for (Iterator<URL> iterator = results.iterator(); iterator.hasNext();) {
URL url = iterator.next();
URI uri = URI.createURI(url.toString());
if (fragments.contains(uri.lastSegment())) {
iterator.remove();
}
fragments.add(uri.lastSegment());
}
return results;
}
/**
* Bind cache.
*
* @param cache
* the cache
*/
@Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC, unbind = "unbindCache")
protected void bindCache(IECViewCache cache) {
this.cache = cache;
}
/**
* Unbind cache.
*
* @param cache
* the cache
*/
protected void unbindCache(IECViewCache cache) {
tracker.close();
tracker = null;
this.cache = null;
}
/**
* The Class Customizer.
*/
private class Customizer implements BundleTrackerCustomizer<List<URL>> {
/* (non-Javadoc)
* @see org.osgi.util.tracker.BundleTrackerCustomizer#addingBundle(org.osgi.framework.Bundle, org.osgi.framework.BundleEvent)
*/
@Override
public List<URL> addingBundle(Bundle bundle, BundleEvent event) {
if (!containsHeader(bundle, FACTORY_MODEL_EXTENDER)) {
return null;
}
List<URL> urls = internalFindURLs(bundle);
cache.registerViews(urls);
return urls;
}
/* (non-Javadoc)
* @see org.osgi.util.tracker.BundleTrackerCustomizer#modifiedBundle(org.osgi.framework.Bundle, org.osgi.framework.BundleEvent, java.lang.Object)
*/
@Override
public void modifiedBundle(Bundle bundle, BundleEvent event,
List<URL> object) {
}
/* (non-Javadoc)
* @see org.osgi.util.tracker.BundleTrackerCustomizer#removedBundle(org.osgi.framework.Bundle, org.osgi.framework.BundleEvent, java.lang.Object)
*/
@Override
public void removedBundle(Bundle bundle, BundleEvent event,
List<URL> urls) {
cache.unregisterViews(urls);
}
}
}