Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.io;
import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.gemini.blueprint.io.internal.OsgiHeaderUtils;
import org.eclipse.gemini.blueprint.io.internal.OsgiResourceUtils;
import org.eclipse.gemini.blueprint.io.internal.OsgiUtils;
import org.eclipse.gemini.blueprint.io.internal.resolver.DependencyResolver;
import org.eclipse.gemini.blueprint.io.internal.resolver.ImportedBundle;
import org.eclipse.gemini.blueprint.io.internal.resolver.PackageAdminResolver;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.springframework.core.io.ContextResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.PathMatcher;
import org.springframework.util.StringUtils;
/**
* OSGi-aware {@link ResourcePatternResolver}.
*
* Can find resources in the bundle jar and bundle space. See {@link OsgiBundleResource} for more
* information.
*
* ClassPath support
*
* As mentioned by {@link PathMatchingResourcePatternResolver}, class-path pattern matching needs to resolve the
* class-path structure to a file-system location (be it an actual folder or a jar). Inside the OSGi environment this is
* problematic as the bundles can be loaded in memory directly from input streams. To avoid relying on each platform
* bundle storage structure, this implementation tries to determine the bundles that assemble the given bundle
* class-path and analyze each of them individually. This involves the bundle archive (including special handling of the
* Bundle-Classpath as it is computed at runtime), the bundle required packages and its attached fragments.
*
* Depending on the configuration of running environment, this might cause significant IO activity which can affect
* performance.
*
* Note: Currently, static imports as well as Bundle-Classpath and
* Required-Bundle entries are supported. Support for DynamicPackage-Import depends on
* how/when the underlying platform does the wiring between the dynamically imported bundle and the given bundle.
*
* Portability Note: Since it relies only on the OSGi API, this implementation depends heavily on how
* closely the platform implements the OSGi spec. While significant tests have been made to ensure compatibility, one
* might experience different behaviour especially when dealing with jars with missing folder entries or
* boot-path delegation. It is strongly recommended that wildcard resolution be thoroughly tested before switching to a
* different platform before you rely on it.
*
* @see Bundle
* @see OsgiBundleResource
* @see PathMatchingResourcePatternResolver
*
* @author Costin Leau
*
* TODO: Rework to use WIRE Admin
*/
public class OsgiBundleResourcePatternResolver extends PathMatchingResourcePatternResolver {
/**
* Our own logger to protect against incompatible class changes.
*/
private static final Log logger = LogFactory.getLog(OsgiBundleResourcePatternResolver.class);
/**
* The bundle on which this resolver works on.
*/
private final Bundle bundle;
/**
* The bundle context associated with this bundle.
*/
private final BundleContext bundleContext;
private static final String FOLDER_SEPARATOR = "/";
private static final String FOLDER_WILDCARD = "**";
private static final String JAR_EXTENSION = ".jar";
private static final String BUNDLE_DEFAULT_CP = ".";
private static final char SLASH = '/';
private static final char DOT = '.';
// use the default package admin version
private final DependencyResolver resolver;
public OsgiBundleResourcePatternResolver(Bundle bundle) {
this(new OsgiBundleResourceLoader(bundle));
}
public OsgiBundleResourcePatternResolver(ResourceLoader resourceLoader) {
super(resourceLoader);
if (resourceLoader instanceof OsgiBundleResourceLoader) {
this.bundle = ((OsgiBundleResourceLoader) resourceLoader).getBundle();
} else {
this.bundle = null;
}
this.bundleContext = (bundle != null ? OsgiUtils.getBundleContext(this.bundle) : null);
this.resolver = (bundleContext != null ? new PackageAdminResolver(bundleContext) : null);
}
/**
* Finds existing resources. This method returns the actual resources found w/o adding any extra decoration (such as
* non-existing resources).
*
* @param locationPattern location pattern
* @return found resources (w/o any decoration)
* @throws IOException in case of I/O errors
*/
protected Resource[] findResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
int type = OsgiResourceUtils.getSearchType(locationPattern);
// look for patterns (includes classpath*:)
if (getPathMatcher().isPattern(locationPattern)) {
// treat classpath as a special case
if (OsgiResourceUtils.isClassPathType(type))
return findClassPathMatchingResources(locationPattern, type);
return findPathMatchingResources(locationPattern, type);
}
// even though we have no pattern
// the OSGi space can return multiple entries for the same resource name
// - treat this case below
else {
Resource[] result = null;
OsgiBundleResource resource = new OsgiBundleResource(bundle, locationPattern);
switch (type) {
// same as bundle space
case OsgiResourceUtils.PREFIX_TYPE_NOT_SPECIFIED:
// consider bundle-space which can return multiple URLs
case OsgiResourceUtils.PREFIX_TYPE_BUNDLE_SPACE:
result = resource.getAllUrlsFromBundleSpace(locationPattern);
break;
// for the rest go with the normal resolving
default:
if (!resource.exists())
result = new Resource[] { resource };
break;
}
return result;
}
}
// add a non-existing resource, if none was found and no pattern was specified
public Resource[] getResources(final String locationPattern) throws IOException {
Resource[] resources = findResources(locationPattern);
// check whether we found something or we should fall-back to a
// non-existing resource
if (ObjectUtils.isEmpty(resources) && (!getPathMatcher().isPattern(locationPattern))) {
return new Resource[] { getResourceLoader().getResource(locationPattern) };
}
// return the original array
return resources;
}
/**
* Special classpath method. Will try to detect the imported bundles (which are part of the classpath) and look for
* resources in all of them. This implementation will try to determine the bundles that compose the current bundle
* classpath and then it will inspect the bundle space of each of them individually.
*
* Since the bundle space is considered, runtime classpath entries such as dynamic imports are not supported
* (yet).
*
* @param locationPattern
* @param type
* @return classpath resources
*/
@SuppressWarnings("unchecked")
private Resource[] findClassPathMatchingResources(String locationPattern, int type) throws IOException {
if (resolver == null)
throw new IllegalArgumentException(
"PackageAdmin service/a started bundle is required for classpath matching");
final ImportedBundle[] importedBundles = resolver.getImportedBundles(bundle);
// eliminate classpath path
final String path = OsgiResourceUtils.stripPrefix(locationPattern);
final Collection foundPaths = new LinkedHashSet();
// 1. search the imported packages
// find folder path matching
final String rootDirPath = determineFolderPattern(path);
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction