org.talend.sdk.component.runtime.manager.ComponentManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of component-runtime-manager Show documentation
Show all versions of component-runtime-manager Show documentation
Core of the framework, the manager allows to access components and instantiate them.
/**
* Copyright (C) 2006-2020 Talend Inc. - www.talend.com
*
* 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.talend.sdk.component.runtime.manager;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.list;
import static java.util.Comparator.comparing;
import static java.util.Locale.ROOT;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
import static org.apache.xbean.finder.archive.FileArchive.decode;
import static org.talend.sdk.component.classloader.ConfigurableClassLoader.NESTED_MAVEN_REPOSITORY;
import static org.talend.sdk.component.runtime.base.lang.exception.InvocationExceptionWrapper.toRuntimeException;
import static org.talend.sdk.component.runtime.manager.ComponentManager.ComponentType.MAPPER;
import static org.talend.sdk.component.runtime.manager.ComponentManager.ComponentType.PROCESSOR;
import static org.talend.sdk.component.runtime.manager.reflect.Constructors.findConstructor;
import static org.talend.sdk.component.runtime.manager.util.Lazy.lazy;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.instrument.ClassFileTransformer;
import java.lang.management.ManagementFactory;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.jar.JarInputStream;
import java.util.logging.Level;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.json.JsonBuilderFactory;
import javax.json.JsonReaderFactory;
import javax.json.JsonWriterFactory;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbConfig;
import javax.json.bind.config.BinaryDataStrategy;
import javax.json.bind.spi.JsonbProvider;
import javax.json.spi.JsonProvider;
import javax.json.stream.JsonGeneratorFactory;
import javax.json.stream.JsonParserFactory;
import org.apache.xbean.asm7.Type;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.ClassFinder;
import org.apache.xbean.finder.archive.Archive;
import org.apache.xbean.finder.archive.ClassesArchive;
import org.apache.xbean.finder.archive.ClasspathArchive;
import org.apache.xbean.finder.archive.CompositeArchive;
import org.apache.xbean.finder.archive.FileArchive;
import org.apache.xbean.finder.archive.FilteredArchive;
import org.apache.xbean.finder.archive.JarArchive;
import org.apache.xbean.finder.filter.ExcludeIncludeFilter;
import org.apache.xbean.finder.filter.Filter;
import org.apache.xbean.finder.filter.FilterList;
import org.apache.xbean.finder.filter.Filters;
import org.apache.xbean.finder.filter.IncludeExcludeFilter;
import org.apache.xbean.finder.filter.PrefixFilter;
import org.apache.xbean.finder.util.Files;
import org.apache.xbean.propertyeditor.Converter;
import org.talend.sdk.component.api.component.Components;
import org.talend.sdk.component.api.component.MigrationHandler;
import org.talend.sdk.component.api.component.Version;
import org.talend.sdk.component.api.input.Emitter;
import org.talend.sdk.component.api.input.PartitionMapper;
import org.talend.sdk.component.api.internationalization.Internationalized;
import org.talend.sdk.component.api.processor.AfterGroup;
import org.talend.sdk.component.api.processor.Processor;
import org.talend.sdk.component.api.service.ActionType;
import org.talend.sdk.component.api.service.Service;
import org.talend.sdk.component.api.service.configuration.LocalConfiguration;
import org.talend.sdk.component.api.service.http.HttpClient;
import org.talend.sdk.component.api.service.http.HttpClientFactory;
import org.talend.sdk.component.api.service.http.Request;
import org.talend.sdk.component.api.service.injector.Injector;
import org.talend.sdk.component.api.service.record.RecordBuilderFactory;
import org.talend.sdk.component.classloader.ConfigurableClassLoader;
import org.talend.sdk.component.container.Container;
import org.talend.sdk.component.container.ContainerListener;
import org.talend.sdk.component.container.ContainerManager;
import org.talend.sdk.component.dependencies.EmptyResolver;
import org.talend.sdk.component.dependencies.maven.Artifact;
import org.talend.sdk.component.dependencies.maven.MvnDependencyListLocalRepositoryResolver;
import org.talend.sdk.component.jmx.JmxManager;
import org.talend.sdk.component.path.PathFactory;
import org.talend.sdk.component.runtime.base.Delegated;
import org.talend.sdk.component.runtime.impl.Mode;
import org.talend.sdk.component.runtime.input.LocalPartitionMapper;
import org.talend.sdk.component.runtime.input.Mapper;
import org.talend.sdk.component.runtime.input.PartitionMapperImpl;
import org.talend.sdk.component.runtime.internationalization.InternationalizationServiceFactory;
import org.talend.sdk.component.runtime.manager.asm.ProxyGenerator;
import org.talend.sdk.component.runtime.manager.builtinparams.MaxBatchSizeParamBuilder;
import org.talend.sdk.component.runtime.manager.extension.ComponentContextImpl;
import org.talend.sdk.component.runtime.manager.extension.ComponentContexts;
import org.talend.sdk.component.runtime.manager.interceptor.InterceptorHandlerFacade;
import org.talend.sdk.component.runtime.manager.json.TalendAccessMode;
import org.talend.sdk.component.runtime.manager.proxy.JavaProxyEnricherFactory;
import org.talend.sdk.component.runtime.manager.reflect.IconFinder;
import org.talend.sdk.component.runtime.manager.reflect.MigrationHandlerFactory;
import org.talend.sdk.component.runtime.manager.reflect.ParameterModelService;
import org.talend.sdk.component.runtime.manager.reflect.ReflectionService;
import org.talend.sdk.component.runtime.manager.reflect.parameterenricher.BaseParameterEnricher;
import org.talend.sdk.component.runtime.manager.service.DefaultServiceProvider;
import org.talend.sdk.component.runtime.manager.service.record.RecordBuilderFactoryProvider;
import org.talend.sdk.component.runtime.manager.spi.ContainerListenerExtension;
import org.talend.sdk.component.runtime.manager.util.Lazy;
import org.talend.sdk.component.runtime.manager.util.LazyMap;
import org.talend.sdk.component.runtime.manager.xbean.KnownClassesFilter;
import org.talend.sdk.component.runtime.manager.xbean.NestedJarArchive;
import org.talend.sdk.component.runtime.manager.xbean.registry.EnrichedPropertyEditorRegistry;
import org.talend.sdk.component.runtime.output.ProcessorImpl;
import org.talend.sdk.component.runtime.record.RecordBuilderFactoryImpl;
import org.talend.sdk.component.runtime.serialization.LightContainer;
import org.talend.sdk.component.runtime.visitor.ModelListener;
import org.talend.sdk.component.runtime.visitor.ModelVisitor;
import org.talend.sdk.component.spi.component.ComponentExtension;
import org.talend.sdk.component.spi.component.GenericComponentExtension;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ComponentManager implements AutoCloseable {
private static class SingletonHolder {
protected static final AtomicReference CONTEXTUAL_INSTANCE = new AtomicReference<>();
static {
final Thread shutdownHook =
new Thread(ComponentManager.class.getName() + "-" + ComponentManager.class.hashCode()) {
@Override
public void run() {
ofNullable(CONTEXTUAL_INSTANCE.get()).ifPresent(ComponentManager::close);
}
};
ComponentManager manager = new ComponentManager(findM2()) {
private final AtomicBoolean closed = new AtomicBoolean(false);
{
info("Creating the contextual ComponentManager instance " + getIdentifiers());
parallelIf(Boolean.getBoolean("talend.component.manager.plugins.parallel"),
container.getDefinedNestedPlugin().stream().filter(p -> !hasPlugin(p)))
.forEach(this::addPlugin);
info("Components: " + availablePlugins());
}
@Override
public void close() {
if (!closed.compareAndSet(false, true)) {
return;
}
try {
synchronized (CONTEXTUAL_INSTANCE) {
if (CONTEXTUAL_INSTANCE.compareAndSet(this, null)) {
try {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
} catch (final IllegalStateException ise) {
// already shutting down
}
}
}
} finally {
CONTEXTUAL_INSTANCE.set(null);
super.close();
info("Released the contextual ComponentManager instance " + getIdentifiers());
}
}
Object readResolve() throws ObjectStreamException {
return new SerializationReplacer();
}
};
Runtime.getRuntime().addShutdownHook(shutdownHook);
manager.info("Created the contextual ComponentManager instance " + getIdentifiers());
if (!CONTEXTUAL_INSTANCE.compareAndSet(null, manager)) { // unlikely it fails in a synch block
manager = CONTEXTUAL_INSTANCE.get();
}
}
}
private static final Components DEFAULT_COMPONENT = new Components() {
@Override
public Class extends Annotation> annotationType() {
return Components.class;
}
@Override
public String family() {
return "";
}
@Override
public String[] categories() {
return new String[] { "Misc" };
}
};
@Getter
protected final ContainerManager container;
// tcomp (org.talend + javax.annotation + jsonp) + logging (slf4j) are/can be provided service
// + tcomp "runtime" indeed (invisible from the components but required for the runtime
private final Filter classesFilter;
private final ParameterModelService parameterModelService;
private final InternationalizationServiceFactory internationalizationServiceFactory;
@Getter
private final JsonProvider jsonpProvider;
@Getter
private final JsonGeneratorFactory jsonpGeneratorFactory;
@Getter
private final JsonReaderFactory jsonpReaderFactory;
@Getter
private final JsonBuilderFactory jsonpBuilderFactory;
@Getter
private final JsonParserFactory jsonpParserFactory;
@Getter
private final JsonWriterFactory jsonpWriterFactory;
@Getter
private final JsonbProvider jsonbProvider;
private final ProxyGenerator proxyGenerator = new ProxyGenerator();
private final JavaProxyEnricherFactory javaProxyEnricherFactory = new JavaProxyEnricherFactory();
// kind of extracted to ensure we can switch it later if needed
// (like using a Spring/CDI context and something else than xbean)
private final ReflectionService reflections;
@Getter // for extensions
private final MigrationHandlerFactory migrationHandlerFactory;
private final Collection extensions;
private final Collection transformers;
private final Collection localConfigurations;
// org.slf4j.event but https://issues.apache.org/jira/browse/MNG-6360
private final Level logInfoLevelMapping;
@Getter // use with caution
private final List customizers;
@Getter
private final Function recordBuilderFactoryProvider;
@Getter
private final JsonbConfig jsonbConfig = new JsonbConfig()
.withBinaryDataStrategy(BinaryDataStrategy.BASE_64)
.setProperty("johnzon.cdi.activated", false)
.setProperty("johnzon.accessModeDelegate", new TalendAccessMode());
private final EnrichedPropertyEditorRegistry propertyEditorRegistry;
private final List classpathContributors;
private final IconFinder iconFinder = new IconFinder();
private final DefaultServiceProvider defaultServiceProvider;
public ComponentManager(final File m2) {
this(m2.toPath());
}
public ComponentManager(final File m2, final String dependenciesResource, final String jmxNamePattern) {
this(m2.toPath(), dependenciesResource, jmxNamePattern);
}
public ComponentManager(final Path m2) {
this(m2, "TALEND-INF/dependencies.txt", "org.talend.sdk.component:type=component,value=%s");
}
/**
* @param m2 the maven repository location if on the file system.
* @param dependenciesResource the resource path containing dependencies.
* @param jmxNamePattern a pattern to register the plugins (containers) in JMX, null
* otherwise.
*/
public ComponentManager(final Path m2, final String dependenciesResource, final String jmxNamePattern) {
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
internationalizationServiceFactory = new InternationalizationServiceFactory(getLocalSupplier());
customizers = toStream(loadServiceProviders(Customizer.class, tccl)).collect(toList()); // must stay first
if (!customizers.isEmpty()) {
customizers.forEach(c -> c.setCustomizers(customizers));
}
if (!Boolean.getBoolean("talend.component.manager.classpathcontributor.skip")) {
classpathContributors =
toStream(loadServiceProviders(ContainerClasspathContributor.class, tccl)).collect(toList());
} else {
classpathContributors = emptyList();
}
classesFilter = new FilterList(Stream
.concat(Stream
.of("org.talend.sdk.component.api.", "org.talend.sdk.component.spi.", "javax.annotation.",
"javax.json.", "org.talend.sdk.component.classloader.",
"org.talend.sdk.component.runtime.", "org.slf4j.", "org.apache.johnzon."),
additionalContainerClasses())
.distinct()
.map(PrefixFilter::new)
.toArray(Filter[]::new));
jsonpProvider = loadJsonProvider();
jsonbProvider = loadJsonbProvider();
// these factories have memory caches so ensure we reuse them properly
jsonpGeneratorFactory = JsonGeneratorFactory.class
.cast(javaProxyEnricherFactory
.asSerializable(tccl, null, JsonGeneratorFactory.class.getName(),
jsonpProvider.createGeneratorFactory(emptyMap())));
jsonpReaderFactory = JsonReaderFactory.class
.cast(javaProxyEnricherFactory
.asSerializable(tccl, null, JsonReaderFactory.class.getName(),
jsonpProvider.createReaderFactory(emptyMap())));
jsonpBuilderFactory = JsonBuilderFactory.class
.cast(javaProxyEnricherFactory
.asSerializable(tccl, null, JsonBuilderFactory.class.getName(),
jsonpProvider.createBuilderFactory(emptyMap())));
jsonpParserFactory = JsonParserFactory.class
.cast(javaProxyEnricherFactory
.asSerializable(tccl, null, JsonParserFactory.class.getName(),
jsonpProvider.createParserFactory(emptyMap())));
jsonpWriterFactory = JsonWriterFactory.class
.cast(javaProxyEnricherFactory
.asSerializable(tccl, null, JsonWriterFactory.class.getName(),
jsonpProvider.createWriterFactory(emptyMap())));
logInfoLevelMapping = findLogInfoLevel();
propertyEditorRegistry = createPropertyEditorRegistry();
localConfigurations = createRawLocalConfigurations();
parameterModelService = new ParameterModelService(propertyEditorRegistry);
reflections = new ReflectionService(parameterModelService, propertyEditorRegistry);
migrationHandlerFactory = new MigrationHandlerFactory(reflections);
final Predicate isContainerClass = name -> isContainerClass(classesFilter, name);
final ContainerManager.ClassLoaderConfiguration defaultClassLoaderConfiguration =
ContainerManager.ClassLoaderConfiguration
.builder()
.parent(tccl)
.parentClassesFilter(isContainerClass)
.classesFilter(isContainerClass.negate())
.supportsResourceDependencies(true)
.create();
this.container = new ContainerManager(ContainerManager.DependenciesResolutionConfiguration
.builder()
.resolver(customizers.stream().noneMatch(Customizer::ignoreDefaultDependenciesDescriptor)
? new MvnDependencyListLocalRepositoryResolver(dependenciesResource, this::resolve)
: new EmptyResolver())
.rootRepositoryLocation(m2)
.create(), defaultClassLoaderConfiguration, container -> {
}, logInfoLevelMapping) {
@Override
public Path resolve(final String path) {
return classpathContributors
.stream()
.filter(it -> it.canResolve(path))
.map(it -> it.resolve(path))
.filter(Objects::nonNull)
.findFirst()
.orElseGet(() -> super.resolve(path));
}
};
this.container.registerListener(new Updater(dependenciesResource));
if (!Boolean.getBoolean("talend.component.manager.jmx.skip")) {
ofNullable(jmxNamePattern)
.map(String::trim)
.filter(n -> !n.isEmpty())
.ifPresent(p -> this.container
.registerListener(
new JmxManager(container, p, ManagementFactory.getPlatformMBeanServer())));
}
toStream(loadServiceProviders(ContainerListenerExtension.class, tccl))
.peek(e -> e.setComponentManager(ComponentManager.this))
.sorted(comparing(ContainerListenerExtension::order))
.forEach(container::registerListener);
this.extensions = toStream(loadServiceProviders(ComponentExtension.class, tccl))
.filter(ComponentExtension::isActive)
.sorted(comparing(ComponentExtension::priority))
.collect(toList());
this.transformers = extensions.stream().flatMap(e -> e.getTransformers().stream()).collect(toList());
final Iterator recordBuilderFactoryIterator =
ServiceLoader.load(RecordBuilderFactoryProvider.class, tccl).iterator();
if (recordBuilderFactoryIterator.hasNext()) {
final RecordBuilderFactoryProvider factory = recordBuilderFactoryIterator.next();
recordBuilderFactoryProvider = factory::apply;
if (recordBuilderFactoryIterator.hasNext()) {
throw new IllegalArgumentException(
"Ambiguous recordBuilderFactory: " + factory + "/" + recordBuilderFactoryIterator.next());
}
} else {
recordBuilderFactoryProvider = RecordBuilderFactoryImpl::new;
}
this.defaultServiceProvider = new DefaultServiceProvider(reflections, jsonpProvider, jsonpGeneratorFactory,
jsonpReaderFactory, jsonpBuilderFactory, jsonpParserFactory, jsonpWriterFactory, jsonbConfig,
jsonbProvider, proxyGenerator, javaProxyEnricherFactory, localConfigurations,
recordBuilderFactoryProvider, propertyEditorRegistry);
}
private JsonbProvider loadJsonbProvider() {
try {
return new org.apache.johnzon.jsonb.JohnzonProvider();
} catch (final RuntimeException re) {
return JsonbProvider.provider();
}
}
private JsonProvider loadJsonProvider() {
try {
return new org.apache.johnzon.core.JsonProviderImpl();
} catch (final RuntimeException re) {
return JsonProvider.provider();
}
}
protected Supplier getLocalSupplier() {
return Locale::getDefault;
}
private Path resolve(final String artifact) {
return container.resolve(artifact);
}
private EnrichedPropertyEditorRegistry createPropertyEditorRegistry() {
return new EnrichedPropertyEditorRegistry();
}
private Level findLogInfoLevel() {
if (Boolean.getBoolean("talend.component.manager.log.info")) {
return Level.INFO;
}
try {
ComponentManager.class.getClassLoader().loadClass("routines.TalendString");
return Level.FINE;
} catch (final NoClassDefFoundError | ClassNotFoundException e) {
return Level.INFO;
}
}
/**
* Creates a default manager with default maven local repository,
* TALEND-INF/dependencies.txt file to find the dependencies of the plugins and
* a default JMX pattern for plugins. It also adds the caller as a plugin.
*
* @return the contextual manager instance.
*/
public static ComponentManager instance() {
return SingletonHolder.CONTEXTUAL_INSTANCE.get();
}
/**
* For test purpose only.
*
* @return
*/
protected static AtomicReference contextualInstance() {
return SingletonHolder.CONTEXTUAL_INSTANCE;
}
public static Path findM2() {
return ofNullable(System.getProperty("talend.component.manager.m2.repository"))
.map(PathFactory::get)
.orElseGet(() -> {
// check if we are in the studio process if so just grab the the studio config
final String m2Repo = System.getProperty("maven.repository");
if (!"global".equals(m2Repo)) {
final Path localM2 = PathFactory
.get(System.getProperty("osgi.configuration.area", ""))
.resolve(".m2/repository");
if (java.nio.file.Files.exists(localM2)) {
return localM2;
}
}
return findDefaultM2();
});
}
private static Stream parallelIf(final boolean condition, final Stream stringStream) {
return condition ? stringStream.parallel() : stringStream;
}
protected void info(final String msg) {
switch (logInfoLevelMapping.intValue()) {
case 500: // FINE
log.debug(msg);
break;
case 800: // INFo
default:
log.info(msg);
}
}
private Stream additionalContainerClasses() {
return Stream
.concat(customizers.stream().flatMap(Customizer::containerClassesAndPackages),
ofNullable(
System.getProperty("talend.component.manager.classloader.container.classesAndPackages"))
.map(s -> s.split(","))
.map(Stream::of)
.orElseGet(Stream::empty));
}
private static Path findDefaultM2() {
// check out settings.xml first
final Path settings = PathFactory
.get(System
.getProperty("talend.component.manager.m2.settings",
System.getProperty("user.home") + "/.m2/settings.xml"));
if (java.nio.file.Files.exists(settings)) {
try {
// faster to do that than previous code (commented after)
final String content = new String(java.nio.file.Files.readAllBytes(settings), StandardCharsets.UTF_8);
final int start = content.indexOf("");
String localM2RepositoryFromSettings = null;
if (start > 0) {
final int end = content.indexOf(" ", start);
if (end > 0) {
localM2RepositoryFromSettings = content.substring(start + "".length(), end);
}
}
if (localM2RepositoryFromSettings != null && !localM2RepositoryFromSettings.isEmpty()) {
return PathFactory.get(localM2RepositoryFromSettings);
}
} catch (final Exception ignore) {
// fallback on default local path
}
}
return PathFactory.get(System.getProperty("user.home", "")).resolve(".m2/repository");
}
private static String getIdentifiers() {
return "(classloader=" + ComponentManager.class.getClassLoader() + ", jvm="
+ ManagementFactory.getRuntimeMXBean().getName() + ")";
}
private static Stream toStream(final Iterator iterator) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.IMMUTABLE), false);
}
private static Iterator loadServiceProviders(final Class service, final ClassLoader classLoader) {
return ServiceLoader.load(service, classLoader).iterator();
}
private static Path toFile(final String classFileName, final URL url) {
String path = url.getFile();
path = path.substring(0, path.length() - classFileName.length());
return PathFactory.get(decode(path));
}
public void addCallerAsPlugin() {
try {
final ClassLoader tmpLoader = ofNullable(Thread.currentThread().getContextClassLoader())
.orElseGet(ClassLoader::getSystemClassLoader);
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
final Class> jarMarker = tmpLoader
.loadClass(Stream
.of(stackTrace)
.filter(c -> !c.getClassName().startsWith("org.talend.sdk.component.runtime.manager.")
&& !c.getClassName().startsWith("org.talend.sdk.component.runtime.beam.dsl.")
&& !c.getClassName().startsWith("org.talend.sdk.component.runtime.standalone.")
&& !c.getClassName().startsWith("org.talend.sdk.component.runtime.avro.")
&& !c.getClassName().startsWith("org.talend.daikon.")
&& !c.getClassName().startsWith("org.talend.designer.")
&& !c.getClassName().startsWith("org.eclipse.")
&& !c.getClassName().startsWith("java.") && !c.getClassName().startsWith("javax.")
&& !c.getClassName().startsWith("sun.") && !c.getClassName().startsWith("com.sun.")
&& !c.getClassName().startsWith("com.oracle."))
.findFirst()
.map(StackTraceElement::getClassName)
.orElse(ComponentManager.class.getName()));
if (jarMarker == ComponentManager.class) {
return;
}
addJarContaining(tmpLoader, jarMarker.getName().replace(".", "/") + ".class");
} catch (final ClassNotFoundException e) {
// ignore, not important. if we can't do it then the plugins should be
// registered normally
}
}
protected List addJarContaining(final ClassLoader loader, final String resource) {
final URL url = loader.getResource(resource);
if (url != null) {
Path plugin = null;
switch (url.getProtocol()) {
case "bundleresource": // studio on equinox, this is the definition part so we don't register it
break;
case "file":
plugin = toFile(resource, url);
break;
case "jar":
if (url.getPath() != null && url.getPath().startsWith("mvn:")) { // pax mvn
// studio temporary integration, to drop when studio integrates correctly tcomp
break;
}
final String spec = url.getFile();
final int separator = spec.indexOf('!');
if (separator > 0) {
try {
plugin = PathFactory.get(decode(new URL(spec.substring(0, separator)).getFile()));
} catch (final MalformedURLException e) {
// no-op
}
}
break;
default:
}
if (plugin == null) {
log.warn("Can't find " + url);
return null;
}
return Stream
.of(plugin)
// just a small workaround for maven/gradle
.flatMap(this::toPluginLocations)
.filter(path -> !container.find(path.getFileName().toString()).isPresent())
.map(file -> {
final String id = addPlugin(file.toAbsolutePath().toString());
if (container.find(id).get().get(ContainerComponentRegistry.class).getComponents().isEmpty()) {
removePlugin(id);
return null;
}
return id;
})
.filter(Objects::nonNull)
.collect(toList());
}
return emptyList();
}
private Stream toPluginLocations(final Path src) {
final String filename = src.getFileName().toString();
if ("test-classes".equals(filename) && src.getParent() != null) { // maven
return Stream.of(src.getParent().resolve("classes"), src);
}
// gradle (v3 & v4)
if ("classes".equals(filename) && src.getParent() != null
&& "test".equals(src.getParent().getFileName().toString()) && src.getParent().getParent() != null) {
return Stream
.of(src.getParent().getParent().resolve("production/classes"), src)
.filter(java.nio.file.Files::exists);
}
if ("test".equals(filename) && src.getParent() != null
&& "java".equals(src.getParent().getFileName().toString())) {
return Stream.of(src.getParent().resolve("main"), src).filter(java.nio.file.Files::exists);
}
return Stream.of(src);
}
public Stream find(final Function> mapper) {
return container.findAll().stream().flatMap(mapper);
}
// really a DIY entry point for custom flow, it creates component instances but
// nothing more
public Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy