All Downloads are FREE. Search and download functionalities are using the official Maven repository.

aQute.bnd.repository.osgi.OSGiIndex Maven / Gradle / Ivy

Go to download

This command line utility is the Swiss army knife of OSGi. It provides you with a breadth of tools to understand and manage OSGi based systems. This project basically uses bndlib.

There is a newer version: 7.1.0
Show newest version
package aQute.bnd.repository.osgi;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
import org.osgi.util.function.Function;
import org.osgi.util.promise.Deferred;
import org.osgi.util.promise.Failure;
import org.osgi.util.promise.Promise;
import org.osgi.util.promise.Promises;
import org.osgi.util.promise.Success;

import aQute.bnd.http.HttpClient;
import aQute.bnd.http.HttpRequest;
import aQute.bnd.osgi.repository.BridgeRepository;
import aQute.bnd.osgi.repository.ResourcesRepository;
import aQute.bnd.osgi.repository.XMLResourceParser;
import aQute.bnd.osgi.resource.ResourceUtils;
import aQute.bnd.osgi.resource.ResourceUtils.ContentCapability;
import aQute.bnd.service.url.TaggedData;
import aQute.bnd.version.Version;
import aQute.lib.exceptions.Exceptions;
import aQute.libg.reporter.slf4j.Slf4jReporter;
import aQute.service.reporter.Reporter;

class OSGiIndex {
	private final Reporter					log	= new Slf4jReporter(OSGiIndex.class);
	private final Promise	repository;
	private final HttpClient				client;
	private final long						staleTime;
	private final File						cache;
	private final String					name;
	private final Collection			uris;

	OSGiIndex(String name, HttpClient client, File cache, Collection uris, int staleTime, boolean refresh)
			throws Exception {
		this.name = name;
		this.uris = uris;
		this.client = client;
		this.cache = checkCache(cache);
		this.staleTime = staleTime * 1000L;
		this.repository = readIndexes(refresh);
	}

	private Promise readIndexes(boolean refresh) throws Exception {
		List>> promises = new ArrayList<>(getURIs().size());

		for (URI uri : getURIs()) {
			promises.add(download(uri, refresh));
		}

		Promise>> all = Promises.all(promises);
		return all.map(new Function>,BridgeRepository>() {
			@Override
			public BridgeRepository apply(List> resources) {
				try {
					ResourcesRepository rr = new ResourcesRepository();
					for (List p : resources) {
						rr.addAll(p);
					}
					return new BridgeRepository(rr);
				} catch (Exception e) {
					throw Exceptions.duck(e);
				}
			}
		});
	}

	private static File checkCache(File cache) {
		cache.mkdirs();
		if (!cache.isDirectory())
			throw new IllegalArgumentException("Cannot create directory for " + cache);
		return cache;
	}

	private Promise> download(final URI uri, boolean refresh) throws Exception {
		HttpRequest req = client.build().useCache(refresh ? -1 : staleTime);

		return req.async(uri).map(new Function>() {
			@Override
			public List apply(File file) {
				try {
					if (file == null) {
						log.trace("%s: No file downloaded for %s", name, uri);
						return Collections.emptyList();
					}
					try (InputStream in = new FileInputStream(file)) {
						try (XMLResourceParser xmlp = new XMLResourceParser(in, name, uri);) {
							return xmlp.parse();
						}
					}
				} catch (Exception e) {
					throw Exceptions.duck(e);
				}
			}
		});
	}

	Promise get(String bsn, Version version, File file) throws Exception {
		Resource resource = getBridge().get(bsn, version);
		if (resource == null)
			return null;

		ContentCapability content = ResourceUtils.getContentCapability(resource);
		if (content == null) {
			log.warning("%s: No content capability for %s", name, resource);
			return null;
		}

		URI url = content.url();
		if (url == null) {
			log.warning("%s: No content capability for %s", name, resource);
			return null;
		}

		return client.build().useCache(file, staleTime).async(url);
	}

	BridgeRepository getBridge() throws Exception {
		return repository.getValue();
	}

	File getCache() {
		return cache;
	}

	/**
	 * Check any of the URL indexes are stale.
	 * 
	 * @return
	 * @throws Exception
	 */
	boolean isStale() throws Exception {
		final Deferred> freshness = new Deferred<>();
		List> promises = new ArrayList<>(getURIs().size());
		for (final URI uri : getURIs()) {
			if (freshness.getPromise().isDone()) {
				break; // early exit if staleness already detected
			}
			try {
				Promise async = client.build().useCache().asTag().async(uri);
				promises.add(async.then(new Success() {
					@Override
					public Promise call(Promise resolved) throws Exception {
						switch (resolved.getValue().getState()) {
							case OTHER :
								// in the offline case
								// ignore might be best here
								log.trace("Could not verify %s", uri);
								break;

							case UNMODIFIED :
								break;

							case NOT_FOUND :
							case UPDATED :
							default :
								log.trace("Found %s to be stale", uri);
								freshness.fail(new Exception("stale"));
						}
						return null;
					}
				}, new Failure() {
					@Override
					public void fail(Promise< ? > resolved) throws Exception {
						log.trace("Could not verify %s: %s", uri, resolved.getFailure());
						freshness.fail(resolved.getFailure());
					}
				}));
			} catch (Exception e) {
				log.trace("Checking stale status: %s: %s", uri, e);
			}
		}

		// Resolve when all uris checked
		Promise> all = Promises.all(promises);
		freshness.resolveWith(all);

		// Block until freshness is resolved
		return freshness.getPromise().getFailure() != null;
	}

	Collection getURIs() {
		return uris;
	}

	Map> findProviders(Collection< ? extends Requirement> requirements)
			throws Exception {
		return getBridge().getRepository().findProviders(requirements);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy