Compare commits

...

1 Commits

Author SHA1 Message Date
undx
0e78d4fa7a feat(TCOMP-1681): Make ESB Studio job export TaCoKit compliant 2020-05-12 13:56:24 +02:00
9 changed files with 447 additions and 14 deletions

View File

@@ -22,6 +22,8 @@
<outputDirectory>${file.separator}</outputDirectory>
<includes>
<include>OSGI-INF/**</include>
<include>TALEND-INF/**</include>
<include>MAVEN-INF/**</include>
</includes>
</fileSet>
<fileSet> <!-- add resources -->

View File

@@ -25,6 +25,8 @@
<outputDirectory>${file.separator}</outputDirectory>
<includes>
<include>OSGI-INF/**</include>
<include>TALEND-INF/**</include>
<include>MAVEN-INF/**</include>
</includes>
</fileSet>

View File

@@ -69,7 +69,7 @@ public abstract class JavaScriptForESBWithMavenManager extends JobJavaScriptOSGI
if ("".equals(resource.getDirectoryName())) { //$NON-NLS-1$
Map<String, Set<URL>> newResourcesMap = new HashMap<String, Set<URL>>();
for (String path : resource.getRelativePathList()) {
if (path.startsWith("OSGI") || path.startsWith(FileConstants.META_INF_FOLDER_NAME)) { //$NON-NLS-1$
if (path.startsWith("OSGI") || path.startsWith(FileConstants.META_INF_FOLDER_NAME)|| path.startsWith("TALEND-INF") || path.startsWith("MAVEN-INF")) { //$NON-NLS-1$
Set<URL> urls = resource.getResourcesByRelativePath(path);
// put OSGI_INF to /src/main/resources/
newResourcesMap.put(IMavenProperties.MAIN_RESOURCES_PATH + path, urls);

View File

@@ -12,6 +12,16 @@
// ============================================================================
package org.talend.repository.ui.wizards.exportjob.scriptsmanager.esb;
import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Clazz;
import aQute.bnd.osgi.Descriptors;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Jar;
import aQute.bnd.service.AnalyzerPlugin;
import aQute.bnd.service.Plugin;
import aQute.service.reporter.Reporter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -37,6 +47,8 @@ import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.MultiKeyMap;
@@ -52,6 +64,7 @@ import org.talend.commons.utils.io.FilesUtils;
import org.talend.core.CorePlugin;
import org.talend.core.GlobalServiceRegister;
import org.talend.core.PluginChecker;
import org.talend.core.model.components.IComponent;
import org.talend.core.model.general.ModuleNeeded;
import org.talend.core.model.general.Project;
import org.talend.core.model.process.IProcess;
@@ -67,6 +80,7 @@ import org.talend.core.repository.model.ProxyRepositoryFactory;
import org.talend.core.runtime.process.ITalendProcessJavaProject;
import org.talend.core.runtime.process.LastGenerationInfo;
import org.talend.core.runtime.repository.build.BuildExportManager;
import org.talend.core.service.ITaCoKitDependencyService;
import org.talend.core.ui.branding.IBrandingService;
import org.talend.designer.core.ICamelDesignerCoreService;
import org.talend.designer.core.IDesignerCoreService;
@@ -86,16 +100,6 @@ import org.talend.repository.ui.wizards.exportjob.scriptsmanager.JobJavaScriptsM
import org.talend.repository.utils.EmfModelUtils;
import org.talend.repository.utils.TemplateProcessor;
import aQute.bnd.header.Attrs;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Clazz;
import aQute.bnd.osgi.Descriptors;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Jar;
import aQute.bnd.service.AnalyzerPlugin;
import aQute.bnd.service.Plugin;
import aQute.service.reporter.Reporter;
/**
* DOC ycbai class global comment. Detailled comment
*/
@@ -220,6 +224,8 @@ public class JobJavaScriptOSGIForESBManager extends JobJavaScriptsManager {
* export current item's dependencies. this used for TDM components specially and need more discussion
* about then
*/
// TCOMP-1681: feature uses this call for feeding a component-runtime compliant MAVEN-INF/repository and
// TALEND-INF/plugins.properties.
BuildExportManager.getInstance().exportOSGIDependencies(osgiResource, processItem);
}
@@ -265,6 +271,15 @@ public class JobJavaScriptOSGIForESBManager extends JobJavaScriptsManager {
if (providedLibResources != null) {
list.add(providedLibResources);
}
// TCOMP-1681: for class isolation and avoid clashes, we remove tacokit dependencies to main classpath.
// However, they're in the scope of ComponentManager.
if (GlobalServiceRegister.getDefault().isServiceRegistered(ITaCoKitDependencyService.class)) {
ITaCoKitDependencyService tckService = (ITaCoKitDependencyService) GlobalServiceRegister.getDefault()
.getService(ITaCoKitDependencyService.class);
if (tckService != null && tckService.hasTaCoKitComponents(tckService.getJobComponents(processItem))) {
list = cleanupResources(tckService.getJobComponents(processItem), list, tckService);
}
}
} catch (ProcessorException e) {
throw e;
} catch (Exception e) {
@@ -301,6 +316,28 @@ public class JobJavaScriptOSGIForESBManager extends JobJavaScriptsManager {
return libResource;
}
private List<ExportFileResource> cleanupResources(Stream<IComponent> components, List<ExportFileResource> resources, ITaCoKitDependencyService service) {
Set<String> tckOnly = service.getTaCoKitOnlyDependencies(components);
final List<ExportFileResource> rmResources = new ArrayList<>();
//This code is nicer but have to reiterate after, so not so efficient
// List<URL> rmDeps = resources.stream()
// .filter(rf -> "lib".equals(rf.getDirectoryName()))
// .map(resource -> resource.getResourcesByRelativePath(""))
// .flatMap(urls -> urls.stream())
// .filter(url -> tckOnly.stream().anyMatch(tck -> url.toString().endsWith(tck)))
// .collect(Collectors.toList());
for (ExportFileResource resource : resources) {
if (!("lib".equals(resource.getDirectoryName()) || "lib-provided".equals(resource.getDirectoryName()))) {
continue;
}
List<URL> rmDeps = resource.getResourcesByRelativePath("").stream()
.filter(url -> tckOnly.stream().anyMatch(tck -> url.toString().endsWith(tck)))
.collect(Collectors.toList());
rmDeps.stream().forEach(dep -> resource.removeResources("", dep));
}
return resources;
}
protected String getIncludeRoutinesPath() {
return USER_ROUTINES_PATH;
}

View File

@@ -118,6 +118,10 @@
class="org.talend.sdk.component.studio.service.TaCoKitUpdateService"
serviceId="ITaCoKitUpdateService">
</Service>
<Service
class="org.talend.sdk.component.studio.service.TaCoKitDependencyService"
serviceId="ITaCoKitDependencyService">
</Service>
</extension>
<extension
point="org.talend.designer.core.generators">
@@ -286,4 +290,7 @@
<Service serviceId="IGenericWizardService" class="org.talend.sdk.component.studio.metadata.WizardRegistry" />
</extension>
-->
<extension point="org.talend.core.runtime.buildExport_provider">
<dependenciesProvider class="org.talend.sdk.component.studio.provider.TacokitExportDependenciesProvider"></dependenciesProvider>
</extension>
</plugin>

View File

@@ -0,0 +1,174 @@
/*
* 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.studio.provider;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static org.talend.sdk.component.studio.util.TaCoKitUtil.findM2Path;
import static org.talend.sdk.component.studio.util.TaCoKitUtil.gavToMvnPath;
import static org.talend.sdk.component.studio.util.TaCoKitUtil.getJobComponents;
import static org.talend.sdk.component.studio.util.TaCoKitUtil.getTaCoKitComponents;
import static org.talend.sdk.component.studio.util.TaCoKitUtil.hasTaCoKitComponents;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.talend.commons.exception.ExceptionHandler;
import org.talend.commons.utils.system.EnvironmentUtils;
import org.talend.core.CorePlugin;
import org.talend.core.model.properties.Item;
import org.talend.core.runtime.process.ITalendProcessJavaProject;
import org.talend.core.runtime.repository.build.BuildExportManager;
import org.talend.core.runtime.repository.build.BuildExportManager.EXPORT_TYPE;
import org.talend.core.runtime.repository.build.IBuildExportDependenciesProvider;
import org.talend.repository.documentation.ExportFileResource;
import org.talend.sdk.component.studio.ComponentModel;
import org.talend.sdk.component.studio.util.TaCoKitConst;
public class TacokitExportDependenciesProvider implements IBuildExportDependenciesProvider {
private final static Logger LOG = LoggerFactory.getLogger(TacokitExportDependenciesProvider.class.getName());
/**
* Called when exporting a job, this is up to the implementor to check that the item should export the dependencies.
*
* We use this interface as a hook to feed MAVEN-INF repository.
*
* Side-note: this method is called every time we have an ESB job export as Microservice export also calls it.
*
* @param exportFileResource resources to export, mainly needed in OSGi.
* @param item <code>ProcessItem</code>
*
* @see org.talend.core.runtime.repository.build.IBuildExportDependenciesProvider
*/
@Override
public void exportDependencies(final ExportFileResource exportFileResource, final Item item) {
if (!BuildExportManager.getInstance().getCurrentExportType()
.equals(EXPORT_TYPE.OSGI) || !hasTaCoKitComponents(getJobComponents(item))) {
return;
}
LOG.debug("[exportDependencies] Searching for TaCoKit components...");
final Map<String, String> plugins = new HashMap<String, String>();
getTaCoKitComponents(getJobComponents(item))
.map(ComponentModel::getId)
.forEach(id -> {
plugins.put(id.getPlugin(), gavToMvnPath(id.getPluginLocation()));
});
LOG.info("[exportDependencies] Found {} TaCoKit components.", plugins.size());
try {
ITalendProcessJavaProject project = CorePlugin.getDefault().getRunProcessService()
.getTalendJobJavaProject(item.getProperty());
final String output = EnvironmentUtils.isWindowsSystem() ?
project.getResourcesFolder().getLocationURI().getPath().substring(1) :
project.getResourcesFolder().getLocationURI().getPath();
final Path m2 = findM2Path();
final Path resM2 = Paths.get(output, TaCoKitConst.MAVEN_INF, "repository");
final Path coordinates = Paths.get(output, TaCoKitConst.TALEND_INF, "plugins.properties");
exportFileResource.addResource("TALEND-INF/", coordinates.toUri().toURL());
Files.createDirectories(resM2);
if (Files.exists(coordinates)) {
Files.readAllLines(coordinates).stream()
.filter(line -> !line.matches("^\\s?#"))
.filter(line -> line.matches(".*=.*"))
.map(line -> line.split("="))
// we assume gav already translated
.forEach((line) -> plugins.putIfAbsent(line[0].trim(), line[1].trim()));
} else {
Files.createDirectories(coordinates.getParent());
}
// Feed MAVEN-INF repository
plugins.forEach((plugin, location) -> {
LOG.info("[exportDependencies] Adding {} to MAVEN-INF.", plugin);
final Path src = m2.resolve(location);
final Path dst = resM2.resolve(location);
try {
// First, cp component jar
copyJar(src, dst, exportFileResource);
// then, find deps for current plugin : This is definitely needed for the microservice case and may
// help to avoid classes collisions as it may happen with azure-dls-gen2 for instance!
JarFile jar = new JarFile(src.toFile());
final JarEntry entry = jar.getJarEntry("TALEND-INF/dependencies.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(jar.getInputStream(entry)));
reader.lines()
.filter(l -> !l.endsWith(":test"))
.map(this::translateGavToJar)
.peek(dep -> LOG.debug("[exportDependencies] Copying dependency {} to MAVEN-INF.", dep))
.forEach(dep -> copyJar(m2.resolve(dep), resM2.resolve(dep), exportFileResource));
reader.close();
jar.close();
} catch (IOException | IllegalStateException e) {
LOG.error("[exportDependencies] Error occurred during artifact copy:", e);
ExceptionHandler.process(e);
}
});
// Finalize by writing our plugins.properties
final StringBuffer coord = new StringBuffer("# component-runtime components coordinates:\n");
plugins.forEach((k, v) -> coord.append(String.format("%s = %s\n", k, v)));
Files.copy(new BufferedInputStream(new ByteArrayInputStream(coord.toString()
.getBytes())), coordinates, REPLACE_EXISTING);
// For microservice m2 extraction, not necessary for real OSGi bundle
System.setProperty("talend.component.manager.components.present", "true");
LOG.info("[exportDependencies] Finished MAVEN-INF feeding.");
} catch (Exception e) {
LOG.error("[exportDependencies] Error occurred:", e);
ExceptionHandler.process(e);
}
}
/**
* Class wrapper for {@link @TaCoKitDependencyUtil#gavToJar(String)}
*
* @param gav see {@link @TaCoKitDependencyUtil#gavToJar(String)}
*
* @return a translated maven path
*/
public String translateGavToJar(String gav) {
return gavToMvnPath(gav);
}
/**
* Copy a jar and update export resources.
*
* @param source m2 jar
* @param destination MAVEN-INF destination jar
* @param exportFileResource file resources for job export build
*/
private void copyJar(Path source, Path destination, ExportFileResource exportFileResource) {
try {
if (!Files.exists(destination.getParent())) {
Files.createDirectories(destination.getParent());
}
if (!Files.exists(destination)) {
Files.copy(source, destination);
}
exportFileResource.addResource(destination.getParent().toString()
.substring(destination.getParent().toString().indexOf("MAVEN-INF")), destination.toUri().toURL());
} catch (IOException e) {
LOG.error("[copyJar] Something went wrong during jar copying...", e);
throw new IllegalStateException(e);
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* 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.studio.service;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.talend.core.model.components.IComponent;
import org.talend.core.model.properties.Item;
import org.talend.core.service.ITaCoKitDependencyService;
import org.talend.sdk.component.studio.ComponentModel;
import org.talend.sdk.component.studio.util.TaCoKitUtil;
public class TaCoKitDependencyService implements ITaCoKitDependencyService {
private final static Logger LOG = LoggerFactory.getLogger(TaCoKitDependencyService.class.getName());
public final static List<String> TACOKIT_JARS_BLACKLIST = Arrays.asList("component-api-",
"component-runtime-design-extension-", "component-runtime-di-", "component-runtime-impl-",
"component-runtime-manager-", "component-spi-", "container-core-", "geronimo-annotation_1.3_spec-",
"geronimo-json_1.1_spec-", "geronimo-jsonb_1.0_spec-", "johnzon-core-", "johnzon-jsonb-", "johnzon-mapper-",
"slf4j-api-", "slf4j-log4j12-", "xbean-asm7-shaded-", "xbean-finder-shaded-", "xbean-reflect-");
/**
* @param components
*
* @return
*/
@Override
public Set<String> getTaCoKitOnlyDependencies(final Stream<IComponent> components) {
LOG.debug("[tckOnlyDependencies] Searching for components dependencies...");
final Set<String> diDeps = new HashSet<>();
final Set<String> tckDeps = new HashSet<>();
components.forEach(component -> {
final Set<String> deps = component.getModulesNeeded()
.stream()
.map(d -> Optional.ofNullable(d.getModuleLocaion())
.map(loc -> loc.substring(loc.lastIndexOf("/") + 1))
.orElseGet(() -> d.getModuleName()))
.filter(jar -> TACOKIT_JARS_BLACKLIST.stream().noneMatch(tck -> jar.contains(tck)))
.collect(Collectors.toSet());
if (ComponentModel.class.isInstance(component)) {
tckDeps.addAll(deps);
} else {
diDeps.addAll(deps);
}
});
tckDeps.removeAll(diDeps);
LOG.info("[tckOnlyDependencies] Found {} TaCoKit components only dependencies.", tckDeps.size());
return tckDeps;
}
@Override
public Stream<IComponent> getJobComponents(final Item item) {
return TaCoKitUtil.getJobComponents(item);
}
@Override
public Path findM2Path() {
return TaCoKitUtil.findM2Path();
}
@Override
public boolean hasTaCoKitComponents(final Stream<IComponent> components) {
return TaCoKitUtil.hasTaCoKitComponents(components);
}
}

View File

@@ -60,4 +60,11 @@ public class TaCoKitConst {
public static final String PROP_REGISTRY = "component.java.registry"; //$NON-NLS-1$
public static final String COMPONENT_NAME_PREFIX = "t"; //$NON-NLS-1$
public static final String BASE_HELP_LINK = "org.talend.help."; //$NON-NLS-1$
public static final String MAVEN_INF = "MAVEN-INF"; //$NON-NLS-1$
public static final String TALEND_INF = "TALEND-INF"; //$NON-NLS-1$
}

View File

@@ -13,25 +13,40 @@
package org.talend.sdk.component.studio.util;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.EList;
import org.talend.commons.utils.data.container.Container;
import org.talend.commons.utils.system.EnvironmentUtils;
import org.talend.core.model.components.ComponentCategory;
import org.talend.core.model.components.IComponent;
import org.talend.core.model.general.Project;
import org.talend.core.model.properties.ConnectionItem;
import org.talend.core.model.properties.Item;
import org.talend.core.model.properties.ProcessItem;
import org.talend.core.model.repository.ERepositoryObjectType;
import org.talend.core.model.repository.IRepositoryViewObject;
import org.talend.core.repository.model.ProxyRepositoryFactory;
import org.talend.core.ui.component.ComponentsFactoryProvider;
import org.talend.designer.core.model.utils.emf.talendfile.NodeType;
import org.talend.designer.core.utils.UnifiedComponentUtil;
import org.talend.repository.ProjectManager;
import org.talend.sdk.component.server.front.model.ConfigTypeNode;
import org.talend.sdk.component.studio.ComponentModel;
import org.talend.sdk.component.studio.Lookups;
import org.talend.sdk.component.studio.metadata.TaCoKitCache;
import org.talend.sdk.component.studio.metadata.WizardRegistry;
@@ -47,8 +62,10 @@ public class TaCoKitUtil {
* Get ConnectionItem from specified project
*
* @param project {@link Project} only search from the given project
* @param itemId item id
* @param itemId item id
*
* @return stored item of the given parameters, or null
*
* @throws Exception unexpected exception occured during searching
*/
public static ConnectionItem getLatestTaCoKitConnectionItem(final Project project, final String itemId)
@@ -65,7 +82,9 @@ public class TaCoKitUtil {
* Get ConnectionItem from main project or it's reference project
*
* @param itemId item id
*
* @return stored item of the given parameters, or null
*
* @throws Exception unexpected exception occured during searching
*/
public static ConnectionItem getLatestTaCoKitConnectionItem(final String itemId) throws Exception {
@@ -168,7 +187,7 @@ public class TaCoKitUtil {
ERepositoryObjectType eType = ERepositoryObjectType.valueOf(type);
if (eType == null) {
eType = new WizardRegistry().createRepositoryObjectType(type, label, alias, folderPathStr, 1,
new String[] { ERepositoryObjectType.PROD_DI });
new String[]{ ERepositoryObjectType.PROD_DI });
TaCoKitCache taCoKitCache = Lookups.taCoKitCache();
ConfigTypeNode parentTypeNode = taCoKitCache.getConfigTypeNodeMap().get(configTypeNode.getParentId());
if (parentTypeNode == null) {
@@ -215,8 +234,9 @@ public class TaCoKitUtil {
/**
* Method to create component name from component's family name and component's name itself.
*
* @param familyName component's family name
* @param familyName component's family name
* @param componentName component's name
*
* @return full component name
*/
public static String getFullComponentName(final String familyName, final String componentName) {
@@ -293,6 +313,103 @@ public class TaCoKitUtil {
}
}
/**
* Find the maven repository path.
*
* @return the configured m2 repository path
*/
public static java.nio.file.Path findM2Path() {
return Optional.ofNullable(System.getProperty("talend.component.manager.m2.repository"))
.map(Paths::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 String m2StudioRepo = EnvironmentUtils.isWindowsSystem()
? System.getProperty("osgi.configuration.area", "").replaceAll("^file:/", "")
: System.getProperty("osgi.configuration.area", "").replaceAll("^file:", "");
final java.nio.file.Path localM2 = Paths.get(m2StudioRepo, ".m2/repository");
if (Files.exists(localM2)) {
return localM2;
}
}
// defaults to user m2
return Paths.get(System.getProperty("user.home", "")).resolve(".m2/repository");
});
}
/**
* Translates a GAV (ie com.tutorial:tutorial-component:0.0.1) to a maven repository path (ie com/tutorial/tutorial-component/0.0.1/tutorial-component-0.0.1.jar).
*
* @param gav GroupId ArtifactId Version. The GAV may have the following forms:
* com.tutorial:tutorial-component:0.0.1
* or
* com.tutorial:tutorial-component:jar:0.0.1:compile
*
* @return a translated maven path
*/
public static String gavToMvnPath(String gav) {
final String jarPathFmt = "%s/%s/%s/%s-%s.jar";
final String[] segments = gav.split(":");
if (segments.length < 3) {
throw new IllegalArgumentException("Bad GAV given!"); // TODO improve message
}
String group = segments[0].replaceAll("\\.", "/");
String artifact = segments[1];
String version = "";
if (segments.length == 3) {
version = segments[2];
} else {
version = segments[3];
}
return String.format(jarPathFmt, group, artifact, version, artifact, version);
}
/**
* Get all components defined in <code>item</code>.
*
* @param item the currently processed <code>ProcessItem</code> during job build export
*
* @return a non-null stream of {@link IComponent}
*/
public static Stream<IComponent> getJobComponents(final Item item) {
final EList<?> nodes = ProcessItem.class.cast(item).getProcess().getNode();
final String DI = ComponentCategory.CATEGORY_4_DI.getName();
return nodes.stream().map(node -> {
final String componentName = ((NodeType) node).getComponentName();
IComponent component = ComponentsFactoryProvider.getInstance().get(componentName, DI);
if (component == null) {
component = UnifiedComponentUtil.getDelegateComponent(componentName, DI);
}
return component;
}).filter(Objects::nonNull);
}
/**
* Get component-runtime components from <code>components</code>.
*
* @param components <code>{@link IComponent}</code>
*
* @return a non-null stream of {@link ComponentModel}
*/
public static Stream<ComponentModel> getTaCoKitComponents(final Stream<IComponent> components) {
return components
.filter(ComponentModel.class::isInstance)
.map(ComponentModel.class::cast);
}
/**
* Check if <code>components</code> holds component-runtime components.
*
* @param components <code>IComponent</code>
*
* @return true if item has some component-runtime components
*/
public static boolean hasTaCoKitComponents(final Stream<IComponent> components) {
return components.anyMatch(ComponentModel.class::isInstance);
}
public static class GAV {
private String groupId;