blob: 074a613bbc9a0ca4c3d0b31da8d01f60fe28aace [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 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.equinox.internal.transforms;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import org.osgi.framework.*;
import org.osgi.util.tracker.ServiceTracker;
/**
* Class that represents a dynamic list of TransformTuples that have been registered against a particular transform type.
*/
public class TransformInstanceListData extends ServiceTracker {
/**
* Used when there are no transform data types
*/
private static final String[] EMPTY_TYPES = new String[0];
/**
* Stale state of the transform list. Set to true whenever one of the ServiceTrackerCustomization methods are invoked.
*/
private volatile boolean stale = true;
/**
* Map from transformer class -> tuple array
*/
private Map transformerToTuple = new HashMap();
/**
* List of all tuples in the system.
*/
private List rawTuples = new ArrayList();
/**
* Map from bundle ID -> boolean representing whether or not a given bundle currently has any transforms registered against it.
*/
private Map bundleIdToTransformPresence = new HashMap();
/**
* Create a new transform list bound to the given context. If new transforms are registered against the given context the contents of this list will change.
* @param context the bundle context
* @throws InvalidSyntaxException thrown if there's an issue listening for changes to the given transformer type
*/
public TransformInstanceListData(BundleContext context) throws InvalidSyntaxException {
super(context, context.createFilter("(&(objectClass=" //$NON-NLS-1$
+ URL.class.getName() + ")(" + TransformTuple.TRANSFORMER_TYPE //$NON-NLS-1$
+ "=*))"), null); //$NON-NLS-1$
open();
}
/**
* Return the transforms types currently held by this list. If a change has been detected since the last request this list will be rebuilt.
* @return the transforms types currently held by this list
*/
public synchronized String[] getTransformTypes() {
if (stale)
rebuildTransformMap();
if (transformerToTuple.size() == 0)
return EMPTY_TYPES;
return (String[]) transformerToTuple.keySet().toArray(new String[transformerToTuple.size()]);
}
/**
* Return the transforms of a particular type currently held by this list. If a change has been detected since the last request this list will be rebuilt.
* @return the transforms currently held by this list
*/
public synchronized TransformTuple[] getTransformsFor(String type) {
if (stale)
rebuildTransformMap();
return (TransformTuple[]) transformerToTuple.get(type);
}
/**
* Return whether or not there are any transforms who's bundle pattern matches the ID of the provided bundle. Only transforms with a present transform handler are considered during the invocation of this method.
* @param bundle the bundle to test
* @return the presence of associated transforms.
*/
public synchronized boolean hasTransformsFor(Bundle bundle) {
if (stale)
rebuildTransformMap();
String bundleName = bundle.getSymbolicName();
Boolean hasTransformsFor = (Boolean) bundleIdToTransformPresence.get(bundleName);
if (hasTransformsFor == null) {
hasTransformsFor = Boolean.FALSE;
for (Iterator i = rawTuples.iterator(); i.hasNext();) {
TransformTuple tuple = (TransformTuple) i.next();
if (tuple.bundlePattern.matcher(bundleName).matches()) {
hasTransformsFor = Boolean.TRUE;
}
}
bundleIdToTransformPresence.put(bundleName, hasTransformsFor);
}
return hasTransformsFor.booleanValue();
}
/**
* Consults the bundle context for services of the transformer type type and builds the internal cache.
*/
private void rebuildTransformMap() {
transformerToTuple.clear();
rawTuples.clear();
bundleIdToTransformPresence.clear();
ServiceReference[] serviceReferences = getServiceReferences();
stale = false;
if (serviceReferences == null)
return;
for (int i = 0; i < serviceReferences.length; i++) {
ServiceReference serviceReference = serviceReferences[i];
String type = serviceReference.getProperty(TransformTuple.TRANSFORMER_TYPE).toString();
URL url = (URL) getService(serviceReference);
TransformTuple[] transforms;
try {
transforms = CSVParser.parse(url);
TransformTuple[] existing = (TransformTuple[]) transformerToTuple.get(type);
if (existing != null) {
TransformTuple[] newTransforms = new TransformTuple[existing.length + transforms.length];
System.arraycopy(existing, 0, newTransforms, 0, existing.length);
System.arraycopy(transforms, 0, newTransforms, existing.length, transforms.length);
transformerToTuple.put(type, newTransforms);
} else
transformerToTuple.put(type, transforms);
for (int j = 0; j < transforms.length; j++) {
rawTuples.add(transforms[j]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public Object addingService(ServiceReference reference) {
try {
return super.addingService(reference);
} finally {
stale = true;
}
}
public void modifiedService(ServiceReference reference, Object service) {
super.modifiedService(reference, service);
stale = true;
}
public void removedService(ServiceReference reference, Object service) {
super.removedService(reference, service);
stale = true;
}
}