com.github.dynamicextensionsalfresco.osgi.JavaPackageScanner Maven / Gradle / Ivy
Show all versions of alfresco-integration Show documentation
package com.github.dynamicextensionsalfresco.osgi;
import com.springsource.util.osgi.manifest.BundleManifest;
import com.springsource.util.osgi.manifest.ExportedPackage;
import com.springsource.util.osgi.manifest.internal.StandardBundleManifest;
import com.springsource.util.osgi.manifest.parse.BundleManifestParseException;
import com.springsource.util.osgi.manifest.parse.DummyParserLogger;
import org.alfresco.service.descriptor.DescriptorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.util.Assert;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
import javax.servlet.ServletContext;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import static com.github.dynamicextensionsalfresco.osgi.ManifestUtils.getImplementationVersion;
import static java.util.Arrays.asList;
/**
* Provides operations for discovering Java packages.
*
* @author Laurens Fridael
*
*/
public class JavaPackageScanner implements ServletContextAware {
private static final String OSGI_PACKAGE = "org.osgi";
private static final String FELIX_PACKAGE = "org.apache.felix";
private static final Collection frameworkPackages = asList(OSGI_PACKAGE, FELIX_PACKAGE);
private final Logger logger = LoggerFactory.getLogger(getClass());
/* Dependencies */
private ServletContextResourcePatternResolver resourcePatternResolver;
private ServletContext servletContext;
private DescriptorService descriptorService;
/* Main operations */
/**
*
* Obtains the Java packages by scanning JARs in /WEB-INF/lib.
*
* This implementation uses a {@link MetadataReader} to obtain class information, without actually loading the
* classses into the VM.
*
* Note: calling this for a second time during Framework restart will currently fail.
*/
public Set scanWebApplicationPackages() {
if (resourcePatternResolver == null) {
if (logger.isWarnEnabled()) {
logger.warn("ResourcePatternResolver was not configured. This is normal during a unit test.");
}
return Collections.emptySet();
}
logger.debug("Scanning for Java packages.");
final long before = System.currentTimeMillis();
final Set systemPackages = new LinkedHashSet(4500, 0.1f);
try {
for (final Resource jarResource : resourcePatternResolver.getResources("/WEB-INF/lib/*.jar")) {
final String jarPath = servletContext.getRealPath(String.format("/WEB-INF/lib/%s",
jarResource.getFilename()));
final JarFile jarFile = new JarFile(jarPath);
final Set exportPackages = scanBundleExportPackages(jarFile);
if (exportPackages != null) {
systemPackages.addAll(exportPackages);
} else {
final Set javaPackages = scanJavaPackages(jarFile);
systemPackages.addAll(javaPackages);
}
}
final long after = System.currentTimeMillis();
if (logger.isInfoEnabled()) {
logger.info("Found {} Java packages. Time taken: {}ms.", systemPackages.size(), (after - before));
}
} catch (final IOException e) {
if (logger.isWarnEnabled()) {
logger.warn("Error scanning Java packages. This will cause Dynamic Extensions framework not to work!",
e);
}
}
return systemPackages;
}
protected boolean isFrameworkPackage(final String packageName) {
for (final String frameworkPackage : frameworkPackages) {
if (packageName.startsWith(frameworkPackage)) {
return true;
}
}
return false;
}
/**
* Scans the given {@link JarFile} for an OSGi-compliant manifest and uses the 'Export-Package' header to determine
* the {@link SystemPackage}s.
*
* @param jarFile
* @return
* @throws IOException
*/
protected Set scanBundleExportPackages(final JarFile jarFile) throws IOException {
Set exportPackages = null;
final Manifest manifest = jarFile.getManifest();
if (manifest != null) {
final Map contents = convertAttributesToMap(manifest.getMainAttributes());
try {
final BundleManifest bundleManifest = new StandardBundleManifest(new DummyParserLogger(), contents);
if (bundleManifest.getBundleName() != null) {
final List exportedPackages = bundleManifest.getExportPackage().getExportedPackages();
exportPackages = new LinkedHashSet(exportedPackages.size());
for (final ExportedPackage exportedPackage : exportedPackages) {
final SystemPackage exportPackage = new SystemPackage(exportedPackage.getPackageName(),
exportedPackage.getVersion().toString());
exportPackages.add(exportPackage);
}
}
} catch (BundleManifestParseException e) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Failed to parse manifest for %s, reverting to content scanning.", jarFile.getName()), e);
}
}
}
return exportPackages;
}
protected Map convertAttributesToMap(final Attributes attributes) {
final Map map = new HashMap();
for (final Entry