
org.fabric3.plugin.contribution.PluginContributionProcessor Maven / Gradle / Ivy
The newest version!
/*
* Fabric3
* Copyright (c) 2009-2015 Metaform Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.fabric3.plugin.contribution;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.fabric3.api.host.contribution.InstallException;
import org.fabric3.api.host.stream.Source;
import org.fabric3.api.host.stream.UrlSource;
import org.fabric3.api.host.util.FileHelper;
import org.fabric3.plugin.api.runtime.PluginHostInfo;
import org.fabric3.spi.contribution.ContentTypeResolutionException;
import org.fabric3.spi.contribution.ContentTypeResolver;
import org.fabric3.spi.contribution.Contribution;
import org.fabric3.spi.contribution.ContributionManifest;
import org.fabric3.spi.contribution.ContributionProcessor;
import org.fabric3.spi.contribution.JavaArtifactIntrospector;
import org.fabric3.spi.contribution.ProcessorRegistry;
import org.fabric3.spi.contribution.Resource;
import org.fabric3.spi.contribution.ResourceState;
import org.fabric3.spi.contribution.archive.ArtifactResourceCallback;
import org.fabric3.spi.introspection.DefaultIntrospectionContext;
import org.fabric3.spi.introspection.IntrospectionContext;
import org.fabric3.spi.introspection.xml.Loader;
import org.fabric3.spi.introspection.xml.LoaderException;
import org.oasisopen.sca.annotation.EagerInit;
import org.oasisopen.sca.annotation.Init;
import org.oasisopen.sca.annotation.Reference;
/**
* Processes a build module or project directory as a contribution.
*/
@EagerInit
public class PluginContributionProcessor implements ContributionProcessor {
private static final String CONTENT_TYPE = "application/vnd.fabric3.plugin-project";
private ProcessorRegistry registry;
private ContentTypeResolver contentTypeResolver;
private List artifactIntrospectors = Collections.emptyList();
private Loader loader;
private PluginHostInfo info;
public PluginContributionProcessor(@Reference ProcessorRegistry registry,
@Reference ContentTypeResolver contentTypeResolver,
@Reference Loader loader,
@Reference PluginHostInfo info) {
this.registry = registry;
this.contentTypeResolver = contentTypeResolver;
this.loader = loader;
this.info = info;
}
@Reference
public void setArtifactIntrospectors(List introspectors) {
this.artifactIntrospectors = introspectors;
}
public boolean canProcess(Contribution contribution) {
return CONTENT_TYPE.equals(contribution.getContentType());
}
@Init
public void init() {
registry.register(this);
}
public void process(Contribution contribution, IntrospectionContext context) throws InstallException {
ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = context.getClassLoader();
try {
Thread.currentThread().setContextClassLoader(loader);
List copy = new ArrayList<>(contribution.getResources()); // copy the list since processors may add resources
for (Resource resource : copy) {
if (ResourceState.UNPROCESSED == resource.getState()) {
registry.processResource(resource, context);
}
}
} finally {
Thread.currentThread().setContextClassLoader(oldClassloader);
}
}
public void processManifest(Contribution contribution, final IntrospectionContext context) throws InstallException {
ClassLoader cl = getClass().getClassLoader();
URI uri = contribution.getUri();
IntrospectionContext childContext = new DefaultIntrospectionContext(uri, cl);
ContributionManifest manifest = null;
try {
URL manifestUrl = new File(info.getResourcesDir(), "META-INF" + File.separator + "sca-contribution.xml").toURI().toURL();
manifest = loadManifest(manifestUrl, childContext);
} catch (MalformedURLException e) {
// ignore no manifest found
}
if (manifest == null) {
// try test classes
try {
URL manifestUrl = new File(info.getTestResourcesDir(), "META-INF" + File.separator + "sca-contribution.xml").toURI().toURL();
manifest = loadManifest(manifestUrl, childContext);
} catch (MalformedURLException e) {
// ignore no manifest found
}
}
if (manifest != null) {
contribution.setManifest(manifest);
}
if (childContext.hasErrors()) {
context.addErrors(childContext.getErrors());
}
if (childContext.hasWarnings()) {
context.addWarnings(childContext.getWarnings());
}
}
public void index(Contribution contribution, final IntrospectionContext context) throws InstallException {
ClassLoader oldClassloader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = context.getClassLoader();
try {
Thread.currentThread().setContextClassLoader(loader);
iterateArtifacts(contribution, context, new ArtifactResourceCallback() {
public void onResource(Resource resource) throws InstallException {
registry.indexResource(resource, context);
}
});
} finally {
Thread.currentThread().setContextClassLoader(oldClassloader);
}
}
/**
* Attempts to load a manifest, returning null if one is not found at the given location.
*
* @param manifestUrl the manifest location
* @param childContext the current context
* @return the manifest or null if not found
* @throws InstallException if there is an error loading the manifest
*/
private ContributionManifest loadManifest(URL manifestUrl, IntrospectionContext childContext) throws InstallException {
try {
Source source = new UrlSource(manifestUrl);
return loader.load(source, ContributionManifest.class, childContext);
} catch (LoaderException e) {
if (e.getCause() instanceof FileNotFoundException) {
// ignore no manifest found
} else {
throw new InstallException(e);
}
}
return null;
}
private void iterateArtifacts(Contribution contribution, final IntrospectionContext context, ArtifactResourceCallback callback) throws InstallException {
File root = FileHelper.toFile(contribution.getLocation());
assert root.isDirectory();
iterateArtifactsRecursive(contribution, context, callback, root);
}
private void iterateArtifactsRecursive(Contribution contribution, final IntrospectionContext context, ArtifactResourceCallback callback, File dir)
throws InstallException {
File[] files = dir.listFiles();
if (files == null) {
return;
}
for (File file : files) {
if (file.isDirectory()) {
iterateArtifactsRecursive(contribution, context, callback, file);
} else {
try {
if (file.getName().endsWith(".class")) {
try {
String name = calculateClassName(file);
if (name == null) {
continue; // ignore: not a contribution class or test class
}
URL entryUrl = file.toURI().toURL();
name = name.replace(File.separator, ".").substring(0, name.length() - 6);
Class> clazz = context.getClassLoader().loadClass(name);
Resource resource = null;
for (JavaArtifactIntrospector introspector : artifactIntrospectors) {
resource = introspector.inspect(clazz, entryUrl, contribution, context);
if (resource != null) {
break;
}
}
if (resource == null) {
continue;
}
contribution.addResource(resource);
callback.onResource(resource);
} catch (ClassNotFoundException | NoClassDefFoundError e) {
// ignore since the class may reference another class not present in the contribution
}
} else {
String contentType = contentTypeResolver.getContentType(file.getName());
// skip entry if we don't recognize the content type
if (contentType == null) {
continue;
}
URL entryUrl = file.toURI().toURL();
UrlSource source = new UrlSource(entryUrl);
Resource resource = new Resource(contribution, source, contentType);
contribution.addResource(resource);
callback.onResource(resource);
}
} catch (MalformedURLException | ContentTypeResolutionException e) {
context.addWarning(new ContributionIndexingFailure(file, e));
}
}
}
}
private String calculateClassName(File file) {
String name = null;
File classesDir = info.getClassesDir();
File testDir = info.getTestClassesDir();
if (file.getPath().startsWith(classesDir.getPath())) {
name = file.getPath().substring(classesDir.getPath().length() + 1);
} else if (file.getPath().startsWith(testDir.getPath())) {
name = file.getPath().substring(testDir.getPath().length() + 1);
}
return name;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy