/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.util.resource.internal; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.util.Enumeration; import org.eclipse.core.runtime.IConfigurationElement; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import de.fhg.igd.slf4jplus.ALogger; import de.fhg.igd.slf4jplus.ALoggerFactory; import eu.esdihumboldt.util.io.InputSupplier; import eu.esdihumboldt.util.resource.ResourceNotFoundException; import eu.esdihumboldt.util.resource.ResourceResolver; /** * Resource resolver that attempts to find a resource at the URI path in the * bundle that registered the resolver as extension. * * @author Simon Templer */ public class BundleResolver implements ResourceResolver { private final Bundle bundle; private final ALogger log = ALoggerFactory.getLogger(BundleResolver.class); /** * Create a bundle resolver. * * @param conf the configuration element */ public BundleResolver(IConfigurationElement conf) { String bundleName = conf.getContributor().getName(); BundleContext context = ResourceBundle.getBundleContext(); if (context != null) { // OSGi is available Bundle contributor = null; for (Bundle bundle : ResourceBundle.getBundleContext().getBundles()) { if (bundle.getSymbolicName().equals(bundleName)) { contributor = bundle; break; } } if (contributor == null) { throw new IllegalStateException("Contributing bundle not found: " + bundleName); } this.bundle = contributor; } else { // no OSGi available this.bundle = null; } } /** * @see ResourceResolver#resolve(URI) */ @Override public InputSupplier<? extends InputStream> resolve(URI uri) throws ResourceNotFoundException { if (bundle != null) { // OSGi final URL entry = bundle.getEntry(uri.getPath()); if (entry == null) { throw new ResourceNotFoundException("Resource with path " + uri.getPath() + " not contained in bundle " + bundle.getSymbolicName()); } preventDirectoryMatch(uri, entry); return new InputSupplier<InputStream>() { @Override public InputStream getInput() throws IOException { return entry.openStream(); } }; } else { // no OSGi final ClassLoader loader = getClass().getClassLoader(); // ClassLoader.getSystemClassLoader(); String pathCandidate = uri.getPath(); final String path = (pathCandidate != null && pathCandidate.startsWith("/")) ? (pathCandidate.substring(1)) : (pathCandidate); Enumeration<URL> resources; try { resources = loader.getResources(path); } catch (IOException e) { log.error("Error accessing classpath resource", e); throw new ResourceNotFoundException(e); } if (resources.hasMoreElements()) { URL entry = resources.nextElement(); // XXX not sure if this is needed here preventDirectoryMatch(uri, entry); return new InputSupplier<InputStream>() { @Override public InputStream getInput() throws IOException { return loader.getResourceAsStream(path); } }; } else { throw new ResourceNotFoundException(); } } } private void preventDirectoryMatch(URI uri, URL candidate) throws ResourceNotFoundException { if (uri != null && candidate != null) { String path1 = uri.getPath(); String path2 = candidate.getPath(); if (path2.endsWith("/") && !path1.endsWith("/")) { throw new ResourceNotFoundException("Found only directory match for resource"); } } } }