diff --git a/osgi/.gitignore b/osgi/.gitignore
index 85e312f..4695fd1 100644
--- a/osgi/.gitignore
+++ b/osgi/.gitignore
@@ -1,3 +1,4 @@
generated/
klighd-linux
-spviz.cli.jar
\ No newline at end of file
+spviz.cli.jar
+**/dependencies.txt
\ No newline at end of file
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/.project b/osgi/de.cau.cs.kieler.spviz.osgi.generate/.project
index 9a7b7c6..0a36457 100644
--- a/osgi/de.cau.cs.kieler.spviz.osgi.generate/.project
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/.project
@@ -5,6 +5,11 @@
+
+ org.eclipse.xtext.ui.shared.xtextBuilder
+
+
+
org.eclipse.jdt.core.javabuilder
@@ -19,5 +24,6 @@
org.eclipse.m2e.core.maven2Nature
org.eclipse.jdt.core.javanature
+ org.eclipse.xtext.ui.shared.xtextNature
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/pom.xml b/osgi/de.cau.cs.kieler.spviz.osgi.generate/pom.xml
index 56a0739..4508e27 100644
--- a/osgi/de.cau.cs.kieler.spviz.osgi.generate/pom.xml
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/pom.xml
@@ -14,8 +14,24 @@
de.cau.cs.kieler.spviz.osgi.generate
de.cau.cs.kieler.spviz.osgi.generate
0.0.1-SNAPSHOT
+ maven-plugin
+
+ org.apache.maven
+ maven-plugin-api
+ 3.9.6
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ 3.9.0
+
+
+ org.eclipse.emf
+ org.eclipse.emf.ecore.xmi
+ 2.16.0
+
org.eclipse.emf
org.eclipse.emf.ecore.xmi
@@ -50,6 +66,20 @@
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ 3.9.0
+
+
+ default-descriptor
+ process-classes
+
+ descriptor
+
+
+
+
maven-compiler-plugin
3.10.0
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFiles.java b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFiles.java
index 7745c34..fad057b 100644
--- a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFiles.java
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFiles.java
@@ -3,17 +3,17 @@
// A part of Kieler
// https://github.com/kieler
//
-// Copyright (c) 2018-2022 by
+// Copyright (c) 2018-2025 by
// Scheidt & Bachmann System Technik GmbH, 24145 Kiel
-// and
+// and
// + Christian-Albrechts-University of Kiel
-// + Department of Computer Science
-// + Real-Time and Embedded Systems Group
+// + Department of Computer Science
+// + Real-Time and Embedded Systems Group
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
-//
+//
// SPDX-License-Identifier: EPL-2.0
//
// ******************************************************************************
@@ -28,9 +28,11 @@
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
@@ -43,6 +45,9 @@
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
+import de.cau.cs.kieler.spviz.osgi.generate.util.EdgeType;
+import de.cau.cs.kieler.spviz.osgi.generate.util.FileUtil;
+import de.cau.cs.kieler.spviz.osgi.generate.util.ReadProjectFilesUtility;
import de.cau.cs.kieler.spviz.osgi.model.Bundle;
import de.cau.cs.kieler.spviz.osgi.model.Feature;
import de.cau.cs.kieler.spviz.osgi.model.OSGiFactory;
@@ -74,10 +79,14 @@ public class ReadProjectFiles {
static final java.lang.System.Logger LOGGER = System.getLogger(OsgiModelDataGenerator.class.getName());
final OSGiProject project = OSGiFactory.eINSTANCE.createOSGiProject();
-// private final List packageDependencies = new ArrayList();
+
private final List filePaths = new ArrayList();
+
private final Map componentPaths = new HashMap<>();
+ private List tempFolders = new ArrayList<>();
+
+ private List>> labeledPackageDependencyEdges = new ArrayList<>();
/**
* Generates the HashMaps with Data for bundles, features, services and
@@ -89,34 +98,161 @@ public class ReadProjectFiles {
*/
public OSGiProject generateData(final File projectPath, final String projectName) {
project.setProjectName(projectName);
-
// Parsing of manifest data
filePaths.clear();
findFiles(StaticVariables.MANIFEST_FILE, projectPath);
- for (final Path manifestPath : filePaths) {
- extractBundleData(manifestPath);
+ try {
+ for (final Path manifestPath : filePaths) {
+ extractBundleData(manifestPath);
+ }
+
+ // parsing of feature data
+ filePaths.clear();
+ findFiles(StaticVariables.FEATURE_FILE, projectPath);
+ for (final Path featurePath : filePaths) {
+ extractFeatureData(featurePath);
+ }
+
+ // parsing of service data
+ project.getServiceComponents().forEach(elem -> extractServiceData(elem));
+
+ // parsing of product data
+ filePaths.clear();
+ findFiles(StaticVariables.PRODUCT_FILE, projectPath);
+ for (final Path productPath : filePaths) {
+ extractProductData(productPath);
+ }
+ connectBundlesViaPackages();
+ tempFolders.forEach(f -> FileUtil.deleteTempFolder(f));
+ for (LabeledEdge> edge : labeledPackageDependencyEdges) {
+ // This map contains information about the origin and amount of imported
+ // packages for the edge.
+ // In the future it can be used to label the edges like in OSGiViz.
+ Map extraInfo = edge.getExtraInfo();
+ }
+ } catch (Exception e) {
+ // In case something goes wrong, delete temporary folders, then explode.
+ tempFolders.forEach(f -> FileUtil.deleteTempFolder(f));
+ throw e;
}
-
- // parsing of feature data
- filePaths.clear();
- findFiles(StaticVariables.FEATURE_FILE, projectPath);
- for (final Path featurePath : filePaths) {
- extractFeatureData(featurePath);
+ return project;
+ }
+
+ private void connectBundlesViaPackages() {
+ project.getPackages().forEach(p -> connectBundlesViaSinglePackageDependency(p));
+ }
+
+ private void connectBundlesViaSinglePackageDependency(Package inputPackage) {
+ if (inputPackage.getConnectingPackageExportDependencyBundles().isEmpty()) {
+ LOGGER.log(System.Logger.Level.DEBUG, inputPackage.getName() + " has no exported package");
+ return;
}
- // parsing of service data
- project.getServiceComponents().forEach(elem -> extractServiceData(elem));
-
- // parsing of product data
- filePaths.clear();
- findFiles(StaticVariables.PRODUCT_FILE, projectPath);
- for (final Path productPath : filePaths) {
- extractProductData(productPath);
+ Bundle exportedBundle = inputPackage.getConnectingPackageExportDependencyBundles().get(0);
+ inputPackage.getConnectingPackageImportDependencyBundles().forEach(bundle -> {
+ bundle.getConnectedPackageDependencyBundles().add(exportedBundle);
+ getCommonProductsForBundles(bundle, exportedBundle)
+ .forEach(product -> addOrUpdatePackageDependencyEdgeLabel(bundle, exportedBundle, product));
+ });
+
+ }
+
+ // TODO: Integrate this label to package edges once edge labels are possible.
+ private String getLabel(Product prod, Map map) {
+ return String.format("%s: %s packages", prod.getName(), map.get(prod));
+ }
+
+ private void addOrUpdatePackageDependencyEdgeLabel(Bundle bundleA, Bundle bundleB, Product product) {
+ Optional>> optionalLabelEntry = labeledPackageDependencyEdges
+ .stream() //
+ .filter(l -> l.getSource().equals(bundleA)) //
+ .filter(l -> l.getTarget().equals(bundleB)).findFirst();
+ optionalLabelEntry.ifPresent(entr -> {
+ if (entr.getExtraInfo().keySet().contains(product)) {
+ entr.getExtraInfo().put(product, entr.getExtraInfo().get(product) + 1);
+ } else {
+ entr.getExtraInfo().put(product, 1);
+ }
+ return;
+ });
+ Map productPackageCountMap = new HashMap<>();
+ productPackageCountMap.put(product, 1);
+ labeledPackageDependencyEdges
+ .add(new LabeledEdge<>(EdgeType.PACKAGE_DEPENDENCY, bundleA, bundleB, productPackageCountMap));
+
+ }
+
+ private Set getCommonProductsForBundles(Bundle bundleA, Bundle bundleB) {
+ Set outputSet = new HashSet<>();
+ project.getProducts().stream() //
+ .filter(pr -> pr.getBundles().contains(bundleA) && pr.getBundles().contains(bundleB)) //
+ .forEach(prod -> outputSet.add(prod));
+ return outputSet;
+ }
+
+ /**
+ * Returns the value of the attribute "key" out of an attribute list and removes
+ * it from the list.
+ *
+ * @param attributes the list of attributes
+ * @param key the attribute asked for
+ * @return the value of the attribute, if the attribute does not exist, return
+ * is null.
+ */
+ private static String getAndRemove(final Attributes attributes, final String key) {
+ final String value = attributes.getValue(key);
+ attributes.remove(new Attributes.Name(key));
+ if (null == value) {
+ return StaticVariables.NOT_SET;
}
-
-
- return project;
+ return value.split(";")[0];
+ }
+
+ /**
+ * Returns the value (comma separated list) of the attribute "key" out of an
+ * attribute list and removes it from the list. Splits the comma separated
+ * String of Strings into a list of Strings.
+ *
+ * @param attributes
+ * @param key
+ * @return
+ */
+ private static List getList(final Attributes attributes, final String key) {
+ final String list = attributes.getValue(key);
+ attributes.remove(new Attributes.Name(key));
+ final List result = new ArrayList();
+ if (null == list) {
+ return result;
+ }
+ for (final String b : list.replaceAll("\"(.*?)\"", "") // remove all characters between '"'
+ .replaceAll("\\s", "") // remove all whitespaces
+ .split(",")) {
+ result.add(b.split(";")[0]);
+ }
+ return result;
+ }
+
+ private void addServiceComponentFiles(final Path manifestPath, Path bundleRoot, final Bundle bundle) {
+ final File serviceComponentsFolder = new File(String.format("%s/OSGI-INF/", bundleRoot));
+ if (!serviceComponentsFolder.exists()) {
+ LOGGER.log(System.Logger.Level.INFO,
+ "The MANIFEST-INF folder and the OSGI-INF folder are not in the same path."
+ + manifestPath.toString());
+ }
+ final File[] serviceComponentFiles = serviceComponentsFolder
+ .listFiles((dir, name) -> name.toLowerCase().endsWith(".xml"));
+ if (serviceComponentFiles != null) {
+ for (final File serviceComponentFile : serviceComponentFiles) {
+
+ String componentName = serviceComponentFile.getName().replace(".xml", StaticVariables.EMPTY_STRING);
+ final ServiceComponent serviceComponent = getOrCreateServiceComponent(componentName);
+ serviceComponent.getBundles().add(bundle);
+ bundle.getServiceComponents().add(serviceComponent);
+ componentPaths.put(serviceComponent,
+ FilenameUtils.separatorsToUnix(serviceComponentFile.getAbsolutePath()));
+ }
+ }
}
/**
@@ -131,50 +267,42 @@ private void extractBundleData(final Path manifestPath) {
if (manifestFolder != null) {
bundleRoot = manifestFolder.getParent();
}
-
- try (final InputStream is = new FileInputStream(manifestPath.toString())){
+ try (final InputStream is = new FileInputStream(manifestPath.toString())) {
final Manifest manifest = new Manifest(is);
+ try {
+ if (bundleRoot != null && !bundleRoot.resolve("OSGI-INF").toFile().exists()) {
+ FileUtil.createTemporaryOSGiInfDirectory(bundleRoot, manifest);
+ tempFolders.add(bundleRoot.toFile());
+ }
+ } catch (IOException e) {
+ FileUtil.deleteTempFolder(bundleRoot.toFile());
+
+ }
final Attributes attributes = manifest.getMainAttributes();
-
+
symbolicName = getAndRemove(attributes, StaticVariables.BUNDLE_SYMBOLIC_NAME);
-
+
// check, if bundle is already existing
final Bundle bundle = getOrCreateBundle(symbolicName);
bundle.setExternal(false);
extractPackages(bundle, attributes);
-
+
// check all required bundles and create them, if not existing
for (final String requiredBundleName : getList(attributes, StaticVariables.REQUIRE_BUNDLE)) {
final Bundle requiredBundle = getOrCreateBundle(requiredBundleName);
requiredBundle.getConnectingDependencyBundles().add(bundle);
}
-
+
final List serviceComponents = getList(attributes, StaticVariables.SERVICE_COMPONENT);
-
+
if (serviceComponents.contains("OSGI-INF/*.xml")) {
- if (!new File(bundleRoot + "/OSGI-INF").exists()) {
- LOGGER.log(System.Logger.Level.INFO, "The MANIFEST-INF folder and the OSGI-INF folder are not in the same path."
- + manifestPath.toString());
- }
- final File serviceComponentsFolder = new File(bundleRoot + "/OSGI-INF/");
- final File[] serviceComponentFiles = serviceComponentsFolder
- .listFiles((dir, name) -> name.toLowerCase().endsWith(".xml"));
-
- if (serviceComponentFiles != null) {
- for (final File serviceComponentFile : serviceComponentFiles) {
-
- String componentName = serviceComponentFile.getName()
- .replace(".xml", StaticVariables.EMPTY_STRING);
- final ServiceComponent serviceComponent = getOrCreateServiceComponent(componentName);
- serviceComponent.getBundles().add(bundle);
- bundle.getServiceComponents().add(serviceComponent);
- componentPaths.put(serviceComponent, FilenameUtils.separatorsToUnix(serviceComponentFile.getAbsolutePath()));
- }
- }
+ addServiceComponentFiles(manifestPath, bundleRoot, bundle);
+ } else if (serviceComponents.contains("/OSGI-INF/*.xml/")) {
+ addServiceComponentFiles(manifestPath, bundleRoot, bundle);
} else {
for (final String service : serviceComponents) {
- final String serviceName = service.replace(".xml", StaticVariables.EMPTY_STRING).replace(
- "OSGI-INF/", StaticVariables.EMPTY_STRING);
+ final String serviceName = service.replace(".xml", StaticVariables.EMPTY_STRING)
+ .replace("OSGI-INF/", StaticVariables.EMPTY_STRING);
final ServiceComponent serviceComponent = OSGiFactory.eINSTANCE.createServiceComponent();
serviceComponent.setName(serviceName);
serviceComponent.setEcoreId(StaticVariables.SERVICE_COMPONENT_PREFIX + toAscii(serviceName));
@@ -182,116 +310,158 @@ private void extractBundleData(final Path manifestPath) {
project.getServiceComponents().add(serviceComponent);
if (service.contains(StaticVariables.XML_FILE) && !service.contains("*.xml")
&& bundleRoot != null) {
- componentPaths.put(serviceComponent, FilenameUtils.separatorsToUnix(
- bundleRoot + service.replace("OSGI-INF/", "/OSGI-INF/")));
+ componentPaths.put(serviceComponent, FilenameUtils
+ .separatorsToUnix(bundleRoot + service.replace("OSGI-INF/", "/OSGI-INF/")));
}
}
}
-
+
} catch (final IOException e) {
LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the manifest file " + e);
}
}
/**
- * Returns the bundle with the given identifying name. Will be created if the
- * bundle does not exist yet.
+ * extracts information out of the feature xml file in featurepath, and adds it
+ * to the feature HashMap
*
- * @param name The unique name of the bundle.
- * @return The bundle for the given name.
+ * @param featurePath is the path to the feature.xml file
*/
- private Bundle getOrCreateBundle(final String name) {
- final Optional bundleAlreadyPresent = project.getBundles()//
- .stream()//
- .filter(elem -> elem.getEcoreId().equals(StaticVariables.BUNDLE_PREFIX + toAscii(name)))//
- .findFirst();
- if (bundleAlreadyPresent.isPresent()) {
- return bundleAlreadyPresent.get();
- } else {
- final Bundle bundle = OSGiFactory.eINSTANCE.createBundle();
- bundle.setName(name);
- bundle.setEcoreId(StaticVariables.BUNDLE_PREFIX + toAscii(name));
- bundle.setExternal(true);
- project.getBundles().add(bundle);
- return bundle;
+ private void extractFeatureData(final Path featurePath) {
+ final File xmlFile = featurePath.toFile();
+ final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder;
+
+ try {
+ dBuilder = dbFactory.newDocumentBuilder();
+ final Document doc = dBuilder.parse(xmlFile);
+ final NodeList pluginNodeList = doc.getElementsByTagName(StaticVariables.PLUGIN);
+
+ String featureName = doc.getDocumentElement().getAttribute(StaticVariables.ID);
+ final Feature feature = getOrCreateFeature(featureName);
+ feature.setExternal(false);
+
+ for (int x = 0, size = pluginNodeList.getLength(); x < size; x++) {
+ final String plugin = pluginNodeList.item(x).getAttributes().getNamedItem(StaticVariables.ID)
+ .getNodeValue();
+ feature.getBundles().add(getOrCreateBundle(plugin));
+ }
+
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the feature.xml file " + e);
}
}
/**
- * Returns the feature with the given identifying name. Will be created if the
- * feature does not exist yet.
+ * Generates a list of {@link PackageObject} for a bundle. Packages can be
+ * exported or imported packages of a bundle
*
- * @param name The unique name of the feature.
- * @return The feature for the given name.
+ * @param bundle is the bundle which exports/imports the packages
+ * @param attributes is the String of packages
+ * @param key describes whether the packages are imported or exported
+ * @return
*/
- private Feature getOrCreateFeature(final String name) {
- final Optional featureAlreadyPresent = project.getFeatures()//
- .stream()//
- .filter(elem -> elem.getEcoreId().equals(StaticVariables.FEATURE_PREFIX + toAscii(name)))//
- .findFirst();
- if (featureAlreadyPresent.isPresent()) {
- return featureAlreadyPresent.get();
- } else {
- final Feature feature = OSGiFactory.eINSTANCE.createFeature();
- feature.setName(name);
- feature.setEcoreId(StaticVariables.FEATURE_PREFIX + toAscii(name));
- feature.setExternal(true);
- project.getFeatures().add(feature);
- return feature;
+ private void extractPackages(final Bundle bundle, final Attributes attributes) {
+ for (final String importOrExport : new String[] { StaticVariables.EXPORT_PACKAGE,
+ StaticVariables.IMPORT_PACKAGE }) {
+
+ final String packageIds = attributes.getValue(importOrExport);
+ attributes.remove(new Attributes.Name(importOrExport));
+
+ if (null == packageIds) {
+ continue;
+ }
+
+ for (final String b : packageIds.replaceAll("\\s", "").replaceAll("\"(.*?)\"", "").split(",")) {
+ final String packageName = b.split(";")[0];
+
+ if (importOrExport.equals(StaticVariables.EXPORT_PACKAGE)) {
+ addExportedPackage(bundle, packageName);
+ } else {
+ addImportedPackage(bundle, packageName);
+ }
+ }
}
}
-
- /**
- * Returns the service component with the given identifying name. Will be created if the
- * component does not exist yet.
- *
- * @param name The unique name of the service component.
- * @return The service component for the given name.
- */
- private ServiceComponent getOrCreateServiceComponent(final String name) {
- final Optional serviceComponentOptional = project.getServiceComponents()//
+
+ private void addImportedPackage(final Bundle bundle, final String packageName) {
+ final Optional ownProjectPackage = project.getPackages()//
.stream()//
- .filter(elem -> elem.getName().equals(StaticVariables.SERVICE_COMPONENT_PREFIX + toAscii(name)))//
+ .filter(elem -> elem.getName().equals(packageName))//
.findFirst();
- if (serviceComponentOptional.isPresent()) {
- return serviceComponentOptional.get();
+ if (ownProjectPackage.isPresent()) {
+ ownProjectPackage.get().getConnectingPackageImportDependencyBundles().add(bundle);
+ bundle.getConnectedPackageImportDependencyPackages().add(ownProjectPackage.get());
} else {
- final ServiceComponent serviceComponent = OSGiFactory.eINSTANCE.createServiceComponent();
- serviceComponent.setName(name);
- serviceComponent.setEcoreId(StaticVariables.SERVICE_COMPONENT_PREFIX + toAscii(name));
- project.getServiceComponents().add(serviceComponent);
- return serviceComponent;
+ final Package newImportedPackage = OSGiFactory.eINSTANCE.createPackage();
+ newImportedPackage.setName(packageName);
+ newImportedPackage.setEcoreId(StaticVariables.PACKAGE_PREFIX + toAscii(packageName));
+ newImportedPackage.getConnectingPackageImportDependencyBundles().add(bundle);
+ // newImportedPackage.getConnectedImportedByBundles().add(bundle);
+ bundle.getConnectedPackageImportDependencyPackages().add(newImportedPackage);
+ project.getPackages().add(newImportedPackage);
}
}
+ private void addExportedPackage(final Bundle bundle, final String packageName) {
+ project.getPackages().stream().filter(p -> p.getName().equals(packageName)).findFirst()
+ .ifPresent(exportedPackage -> {
+ bundle.getConnectedPackageExportDependencyPackages().add(exportedPackage);
+ bundle.getPackages().add(exportedPackage);
+ return;
+ });
+ final Package newExportedPackage = OSGiFactory.eINSTANCE.createPackage();
+ newExportedPackage.setName(packageName);
+ newExportedPackage.setEcoreId(StaticVariables.PACKAGE_PREFIX + bundle.getEcoreId() + toAscii(packageName));
+ newExportedPackage.getConnectingPackageExportDependencyBundles().add(bundle);
+ bundle.getConnectedPackageExportDependencyPackages().add(newExportedPackage);
+ project.getPackages().add(newExportedPackage);
+ project.getProducts().stream() //
+ .filter(prod -> prod.getBundles().contains(bundle)) //
+ .forEach(productWithPackage -> productWithPackage.getPackages().add(newExportedPackage));
+ bundle.getPackages().add(newExportedPackage);
+ }
+
/**
- * extracts information out of the feature xml file in featurepath, and adds it
- * to the feature HashMap
+ * extracts information out of the product file, and adds it to productData.
*
- * @param featurePath is the path to the feature.xml file
+ * @param productPath is the path to the product file
*/
- private void extractFeatureData(final Path featurePath) {
- final File xmlFile = featurePath.toFile();
+ private void extractProductData(final Path productPath) {
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
-
try {
dBuilder = dbFactory.newDocumentBuilder();
- final Document doc = dBuilder.parse(xmlFile);
- final NodeList pluginNodeList = doc.getElementsByTagName(StaticVariables.PLUGIN);
-
- String featureName = doc.getDocumentElement().getAttribute(StaticVariables.ID);
- final Feature feature = getOrCreateFeature(featureName);
- feature.setExternal(false);
-
- for (int x = 0, size = pluginNodeList.getLength(); x < size; x++) {
- final String plugin = pluginNodeList.item(x).getAttributes().getNamedItem(StaticVariables.ID)
+ final Document doc = dBuilder.parse(productPath.toString());
+ String productName = doc.getDocumentElement().getAttribute(StaticVariables.UNIQUE_ID);
+ if (productName.equals("")) {
+ productName = productPath.getFileName().toString();
+ }
+ final Product product = OSGiFactory.eINSTANCE.createProduct();
+ product.setName(productName);
+ product.setEcoreId(StaticVariables.PRODUCT_PREFIX + toAscii(productName));
+
+ project.getProducts().add(product);
+
+ final NodeList featureNodeList = doc.getElementsByTagName(StaticVariables.FEATURE);
+ for (int x = 0, size = featureNodeList.getLength(); x < size; x++) {
+ final String featureName = featureNodeList.item(x).getAttributes().getNamedItem(StaticVariables.ID)
.getNodeValue();
- feature.getBundles().add(getOrCreateBundle(plugin));
+ final Feature feature = getOrCreateFeature(featureName);
+ feature.getProducts().add(product);
+ product.getFeatures().add(feature);
+ }
+
+ final NodeList bundleNodeList = doc.getElementsByTagName(StaticVariables.PLUGIN);
+ for (int x = 0, size = bundleNodeList.getLength(); x < size; x++) {
+ final String bundleName = bundleNodeList.item(x).getAttributes().getNamedItem(StaticVariables.ID)
+ .getNodeValue();
+ final Bundle bundle = getOrCreateBundle(bundleName);
+ bundle.getProducts().add(product);
+ product.getBundles().add(bundle);
}
-
} catch (ParserConfigurationException | SAXException | IOException e) {
- LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the feature.xml file " + e);
+ LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the product xml file " + e);
}
}
@@ -306,18 +476,16 @@ private void extractServiceData(final ServiceComponent serviceComponent) {
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
dBuilder = dbFactory.newDocumentBuilder();
-
final File xmlFile = new File(componentPaths.get(serviceComponent));
final Document doc = dBuilder.parse(xmlFile);
final NodeList referenceList = doc.getElementsByTagName(StaticVariables.REFERENCE);
final NodeList interfaceList = doc.getElementsByTagName(StaticVariables.PROVIDE);
-
+
// read interface
if (interfaceList.getLength() != 0) {
for (int x = 0, size = interfaceList.getLength(); x < size; x++) {
final String interfaceName = interfaceList.item(x).getAttributes()
.getNamedItem(StaticVariables.INTERFACE).getNodeValue();
-
final Optional serviceInterfaceOptional = project.getServiceInterfaces()//
.stream()//
.filter(elem -> elem.getName().equals(interfaceName))//
@@ -340,12 +508,12 @@ private void extractServiceData(final ServiceComponent serviceComponent) {
// read references
for (int x = 0, size = referenceList.getLength(); x < size; x++) {
-
+
final String interfaceName = (referenceList.item(x).getAttributes()
.getNamedItem(StaticVariables.REFERENCE_INTERFACE) == null ? StaticVariables.NOT_SET
: referenceList.item(x).getAttributes()
.getNamedItem(StaticVariables.REFERENCE_INTERFACE).getNodeValue());
-
+
// check if interface is already existing, else create it.
final Optional serviceInterfaceOptional = project.getServiceInterfaces()//
.stream()//
@@ -366,51 +534,10 @@ private void extractServiceData(final ServiceComponent serviceComponent) {
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
- LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the service xml file " + e);
- }
- }
-
- /**
- * extracts information out of the product file, and adds it to productData.
- *
- * @param productPath is the path to the product file
- */
- private void extractProductData(final Path productPath) {
- final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder dBuilder;
- try {
- dBuilder = dbFactory.newDocumentBuilder();
- final Document doc = dBuilder.parse(productPath.toString());
- final String productName = doc.getDocumentElement().getAttribute(StaticVariables.UNIQUE_ID);
-
- final Product product = OSGiFactory.eINSTANCE.createProduct();
- product.setName(productName);
- product.setEcoreId(StaticVariables.PRODUCT_PREFIX + toAscii(productName));
-
- project.getProducts().add(product);
-
- final NodeList featureNodeList = doc.getElementsByTagName(StaticVariables.FEATURE);
- for (int x = 0, size = featureNodeList.getLength(); x < size; x++) {
- final String featureName = featureNodeList.item(x).getAttributes().getNamedItem(StaticVariables.ID)
- .getNodeValue();
- final Feature feature = getOrCreateFeature(featureName);
- feature.getProducts().add(product);
- product.getFeatures().add(feature);
- }
-
- final NodeList bundleNodeList = doc.getElementsByTagName(StaticVariables.PLUGIN);
- for (int x = 0, size = bundleNodeList.getLength(); x < size; x++) {
- final String bundleName = bundleNodeList.item(x).getAttributes().getNamedItem(StaticVariables.ID)
- .getNodeValue();
- final Bundle bundle = getOrCreateBundle(bundleName);
- bundle.getProducts().add(product);
- product.getBundles().add(bundle);
- }
- } catch (ParserConfigurationException | SAXException | IOException e) {
- LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the product xml file " + e);
+ LOGGER.log(System.Logger.Level.ERROR, "There was an error with reading the service xml file ", e);
}
}
-
+
/**
* Finds all files in a directory and all its subdirectories. Adds the path to
* the files to List filePaths
@@ -436,113 +563,83 @@ private void findFiles(final String name, final File file) {
}
}
}
-
+
/**
- * Generates a list of {@link PackageObject} for a bundle. Packages can be
- * exported or imported packages of a bundle
+ * Returns the bundle with the given identifying name. Will be created if the
+ * bundle does not exist yet.
*
- * @param bundle is the bundle which exports/imports the packages
- * @param attributes is the String of packages
- * @param key describes whether the packages are imported or exported
- * @return
+ * @param name The unique name of the bundle.
+ * @return The bundle for the given name.
*/
- private void extractPackages(final Bundle bundle, final Attributes attributes) {
- for (final String importOrExport : new String[] { StaticVariables.EXPORT_PACKAGE,
- StaticVariables.IMPORT_PACKAGE }) {
-
- final String packageIds = attributes.getValue(importOrExport);
- attributes.remove(new Attributes.Name(importOrExport));
-
- if (null == packageIds) {
- continue;
- }
-
- for (final String b : packageIds.replaceAll("\\s", "").replaceAll("\"(.*?)\"", "").split(",")) {
- final String packageName = b.split(";")[0];
-
- if (importOrExport.equals(StaticVariables.EXPORT_PACKAGE)) {
- final Package newExportedPackage = OSGiFactory.eINSTANCE.createPackage();
- newExportedPackage.setName(packageName);
- newExportedPackage.setEcoreId(StaticVariables.PACKAGE_PREFIX + bundle.getEcoreId() + toAscii(packageName));
- newExportedPackage.getBundles().add(bundle);
- bundle.getPackages().add(newExportedPackage);
- project.getPackages().add(newExportedPackage);
- } else {
-// final Optional knownImportedPackage = packageDependencies//
-// .stream()//
-// .filter(elem -> elem.getName().equals(packageName))//
-// .findFirst();
- final Optional ownProjectPackage = project.getPackages()//
- .stream()//
- .filter(elem -> elem.getName().equals(packageName))//
- .findFirst();
- if (ownProjectPackage.isPresent()) {
- ownProjectPackage.get().getConnectingPackageDependencyBundles().add(bundle);
- bundle.getConnectedPackageDependencyPackages().add(ownProjectPackage.get());
-// } else if (knownImportedPackage.isPresent()) {
-// bundle.getPackageDependency().add(knownImportedPackage.get());
- } else {
- final Package newImportedPackage = OSGiFactory.eINSTANCE.createPackage();
- newImportedPackage.setName(packageName);
- newImportedPackage.setEcoreId(StaticVariables.PACKAGE_PREFIX + toAscii(packageName));
- newImportedPackage.getConnectingPackageDependencyBundles().add(bundle);
- bundle.getConnectedPackageDependencyPackages().add(newImportedPackage);
-// packageDependencies.add(newImportedPackage);
- project.getPackages().add(newImportedPackage);
- }
- }
- }
+ private Bundle getOrCreateBundle(final String name) {
+ final Optional bundleAlreadyPresent = project.getBundles()//
+ .stream()//
+ .filter(elem -> elem.getEcoreId().equals(StaticVariables.BUNDLE_PREFIX + toAscii(name)))//
+ .findFirst();
+ if (bundleAlreadyPresent.isPresent()) {
+ return bundleAlreadyPresent.get();
+ } else {
+ final Bundle bundle = OSGiFactory.eINSTANCE.createBundle();
+ bundle.setName(name);
+ bundle.setEcoreId(StaticVariables.BUNDLE_PREFIX + toAscii(name));
+ bundle.setExternal(true);
+ project.getBundles().add(bundle);
+ return bundle;
}
}
/**
- * Returns the value of the attribute "key" out of an attribute list and removes
- * it from the list.
+ * Returns the feature with the given identifying name. Will be created if the
+ * feature does not exist yet.
*
- * @param attributes the list of attributes
- * @param key the attribute asked for
- * @return the value of the attribute, if the attribute does not exist, return
- * is null.
+ * @param name The unique name of the feature.
+ * @return The feature for the given name.
*/
- private static String getAndRemove(final Attributes attributes, final String key) {
- final String value = attributes.getValue(key);
- attributes.remove(new Attributes.Name(key));
- if (null == value) {
- return StaticVariables.NOT_SET;
+ private Feature getOrCreateFeature(final String name) {
+ final Optional featureAlreadyPresent = project.getFeatures()//
+ .stream()//
+ .filter(elem -> elem.getEcoreId().equals(StaticVariables.FEATURE_PREFIX + toAscii(name)))//
+ .findFirst();
+ if (featureAlreadyPresent.isPresent()) {
+ return featureAlreadyPresent.get();
+ } else {
+ final Feature feature = OSGiFactory.eINSTANCE.createFeature();
+ feature.setName(name);
+ feature.setEcoreId(StaticVariables.FEATURE_PREFIX + toAscii(name));
+ feature.setExternal(true);
+ project.getFeatures().add(feature);
+ return feature;
}
-
- return value.split(";")[0];
}
/**
- * Returns the value (comma separated list) of the attribute "key" out of an
- * attribute list and removes it from the list. Splits the comma separated
- * String of Strings into a list of Strings.
+ * Returns the service component with the given identifying name. Will be
+ * created if the component does not exist yet.
*
- * @param attributes
- * @param key
- * @return
+ * @param name The unique name of the service component.
+ * @return The service component for the given name.
*/
- private static List getList(final Attributes attributes, final String key) {
- final String list = attributes.getValue(key);
- attributes.remove(new Attributes.Name(key));
- final List result = new ArrayList();
- if (null == list) {
- return result;
- }
- for (final String b : list.replaceAll("\"(.*?)\"", "") // remove all characters between '"'
- .replaceAll("\\s", "") // remove all whitespaces
- .split(",")) {
- result.add(b.split(";")[0]);
+ private ServiceComponent getOrCreateServiceComponent(final String name) {
+ final Optional serviceComponentOptional = project.getServiceComponents()//
+ .stream()//
+ .filter(elem -> elem.getName().equals(StaticVariables.SERVICE_COMPONENT_PREFIX + toAscii(name)))//
+ .findFirst();
+ if (serviceComponentOptional.isPresent()) {
+ return serviceComponentOptional.get();
+ } else {
+ final ServiceComponent serviceComponent = OSGiFactory.eINSTANCE.createServiceComponent();
+ serviceComponent.setName(name);
+ serviceComponent.setEcoreId(StaticVariables.SERVICE_COMPONENT_PREFIX + toAscii(name));
+ project.getServiceComponents().add(serviceComponent);
+ return serviceComponent;
}
- return result;
}
/**
* Converts the given name to an ACII string save for using in an Ecore ID.
* German umlauts are converted to their long form counterparts (e.g., ä->ae)
* and special characters not in the alphabet are replaced by underscores (_).
- *
+ *
* @param name The name to convert to an ASCII string
* @return An ASCII-only version of the string.
*/
@@ -556,22 +653,61 @@ private String toAscii(String name) {
mappings.put('ü', "ue");
mappings.put('ẞ', "Ss");
mappings.put('ß', "ss");
-
+
StringBuilder sb = new StringBuilder();
name.chars().forEachOrdered((int character) -> {
// Replace all known mappings to readable allowable ID substrings
if (mappings.containsKey((char) character)) {
sb.append(mappings.get((char) character));
- // Keep all A-Z,a-z and .- the same.
- } else if (character >= 'A' && character <= 'Z' || character >= 'a' && character <= 'z' || character == '.' || character == '-') {
+ // Keep all A-Z,a-z and .- the same.
+ } else if (character >= 'A' && character <= 'Z' || character >= 'a' && character <= 'z' || character == '.'
+ || character == '-') {
sb.append((char) character);
- // Replace all other characters by _
+ // Replace all other characters by _
} else {
sb.append('_');
}
});
-
+
return sb.toString();
}
+ class LabeledEdge {
+ EdgeType type;
+ private T source;
+ private U target;
+ private V extraInfo;
+
+ public LabeledEdge(EdgeType type, T source, U target, V extraInfo) {
+ super();
+ this.type = type;
+ this.source = source;
+ this.target = target;
+ this.extraInfo = extraInfo;
+ }
+
+ public EdgeType getType() {
+ return type;
+ }
+
+ public T getSource() {
+ return source;
+ }
+
+ public U getTarget() {
+ return target;
+ }
+
+ public V getExtraInfo() {
+ return extraInfo;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("src: %s %ntarget: %s %nextraInfo: %s", source.toString(), target.toString(),
+ extraInfo.toString());
+ }
+
+ }
+
}
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/mvn/MavenMojo.java b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/mvn/MavenMojo.java
new file mode 100644
index 0000000..4a5ff89
--- /dev/null
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/mvn/MavenMojo.java
@@ -0,0 +1,66 @@
+// ******************************************************************************
+//
+// Copyright (c) 2018-2025 by
+// Scheidt & Bachmann System Technik GmbH, 24145 Kiel
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License 2.0 which is available at
+// http://www.eclipse.org/legal/epl-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0
+//
+// ******************************************************************************
+
+package de.cau.cs.kieler.spviz.osgi.generate.mvn;
+
+import java.io.File;
+import java.lang.System.Logger;
+import java.util.Optional;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+
+import de.cau.cs.kieler.spviz.osgi.generate.OsgiModelDataGenerator;
+
+/**
+ *
+ */
+@Mojo(name = "generate-spviz-osgi")
+public class MavenMojo extends AbstractMojo {
+ static final Logger LOGGER = System.getLogger(MavenMojo.class.getName());
+ @Parameter(name = "name", property = "SPVizName")
+ private String name;
+
+ @Parameter(name = "sourceDir", property = "SPVizSource")
+ private String sourceDir;
+
+ @Parameter(name = "targetDir", property = "SPVizTarget")
+ private String targetDir;
+
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ System.out.println(String.format("%s -> %s -> %s", name, sourceDir, targetDir));
+ File src = new File(sourceDir);
+ File trg = new File(targetDir);
+ if (!src.exists()) {
+ LOGGER.log(System.Logger.Level.ERROR, "Specify a valid source directory.");
+ throw new MojoFailureException("Invalid source directory");
+ }
+ if (!trg.exists()) {
+ LOGGER.log(System.Logger.Level.ERROR, "Specify a valid target directory.");
+ throw new MojoFailureException("Invalid target directory");
+ }
+ if (name == null || name.isBlank()) {
+ LOGGER.log(System.Logger.Level.ERROR, "Specify a valid name.");
+ throw new MojoFailureException("Invalid name");
+ }
+ OsgiModelDataGenerator.generateData(sourceDir, name, Optional.of(targetDir));
+
+ LOGGER.log(System.Logger.Level.INFO,
+ "OSGi model generation has finished. The files can be found in " + targetDir);
+ }
+
+}
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/EdgeType.java b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/EdgeType.java
new file mode 100644
index 0000000..d5e5abe
--- /dev/null
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/EdgeType.java
@@ -0,0 +1,18 @@
+// ******************************************************************************
+//
+// Copyright (c) 2018-2025 by
+// Scheidt & Bachmann System Technik GmbH, 24145 Kiel
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License 2.0 which is available at
+// http://www.eclipse.org/legal/epl-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0
+//
+// ******************************************************************************
+
+package de.cau.cs.kieler.spviz.osgi.generate.util;
+
+public enum EdgeType {
+ BUNDLE_DEPENDENCY, PACKAGE_DEPENDENCY
+}
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/FileUtil.java b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/FileUtil.java
new file mode 100644
index 0000000..cb419bc
--- /dev/null
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/FileUtil.java
@@ -0,0 +1,144 @@
+// ******************************************************************************
+//
+// Copyright (c) 2018-2025 by
+// Scheidt & Bachmann System Technik GmbH, 24145 Kiel
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License 2.0 which is available at
+// http://www.eclipse.org/legal/epl-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0
+//
+// ******************************************************************************
+
+package de.cau.cs.kieler.spviz.osgi.generate.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.DirectoryStream;
+import java.nio.file.DirectoryStream.Filter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+
+/**
+ * Extractor for OSGI_INF folder from jar.
+ *
+ */
+public class FileUtil {
+ protected static final String BUNDLE_SYMBOLIC_NAME_TAG = "Bundle-SymbolicName";
+
+ /**
+ * Copys the xml files from the jar to the temporary folder.
+ *
+ * @param entry the jar entry with everything included in the jar file
+ * @param jarFile needed to create the input stream
+ * @param tempFilePath the path of the temporary file
+ */
+ private static void copyXmlFileFromJarToDirectory(final JarEntry entry, final JarFile jarFile,
+ final Path tempFilePath) {
+ try (final InputStream stream = jarFile.getInputStream(entry);) {
+ final String fileName = entry.getName();
+ final Path file = tempFilePath.resolve(fileName);
+ Files.createDirectories(file.getParent());
+ Files.createFile(file);
+ Files.copy(stream, file, StandardCopyOption.REPLACE_EXISTING);
+ } catch (final IOException e) {
+ // NOOP if the file is unsuitable.
+ }
+ }
+
+ /**
+ * Creates a OSGI-INF directory extracted from the jar file.
+ *
+ * @param rootPath the bundle path
+ * @param manifest the manifest for obtaining the name of the jar
+ * @throws IOException in case the rootPath is wrong
+ */
+ // CHECKSTYLE IGNORE AbbreviationAsWordInNameCheck FOR NEXT 1 LINES - OSG is
+ // what it is called.
+ public static void createTemporaryOSGiInfDirectory(final Path rootPath, final Manifest manifest)
+ throws IOException {
+ final String symbolicName = getSymbolicName(manifest);
+ final List jarList = listFilesWithExtensionRecursively(rootPath, ".jar").stream() //
+ .map(Path::toFile) //
+ .filter(path -> path.getName().contains(symbolicName + "-")) //
+ .collect(Collectors.toList());
+ for (final File fileWithJarEnding : jarList) {
+ extractXmlsFromJarIntoTempFolder(rootPath, fileWithJarEnding);
+ }
+ }
+
+ private static final void deleteDirectory(final File file) {
+ if (file.isDirectory()) {
+ Arrays.stream(file.listFiles()) //
+ .forEach(FileUtil::deleteDirectory);
+ }
+ file.delete();
+ }
+
+ public static void deleteTempFolder(final File rootFile) {
+ final Path tempFolder = Paths.get(String.format("%s/%s", rootFile.getAbsolutePath(), "OSGI-INF"));
+ deleteDirectory(tempFolder.toFile());
+ }
+
+ /**
+ * Extracts the OSGI-INF directory from a jar, if it exists, and puts it into
+ * the temporary folder.
+ *
+ * @param rootPath root of the bundle
+ * @param fileWithJarEnding the jar which the OSGI-INF files are being extracted
+ * from
+ * @throws IOException in case there are file issues.
+ *
+ */
+ private static void extractXmlsFromJarIntoTempFolder(final Path rootPath, final File fileWithJarEnding)
+ throws IOException {
+ final ArrayList osgiInfFiles = new ArrayList<>();
+ try (JarFile jarFile = new JarFile(fileWithJarEnding.getAbsolutePath())) {
+ jarFile.entries().asIterator().forEachRemaining(entry -> { //
+ if (entry.getName().startsWith("OSGI-INF/") && entry.getName().endsWith(".xml")) {
+ osgiInfFiles.add(entry);
+ }
+ });
+ osgiInfFiles.stream().forEach(entry -> copyXmlFileFromJarToDirectory(entry, jarFile, rootPath));
+ }
+ }
+
+ private static String getSymbolicName(final Manifest manifest) {
+ final String symbolicName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLIC_NAME_TAG).trim();
+ return symbolicNameFromDeclaration(symbolicName);
+ }
+
+ private static List listFilesWithExtensionRecursively(final Path path, final String fileExtension)
+ throws IOException {
+ final Filter filter = filterPath -> filterPath.toString().endsWith(fileExtension)
+ || filterPath.toFile().isDirectory();
+ final List paths = new LinkedList<>();
+ try (DirectoryStream stream = Files.newDirectoryStream(path, filter)) {
+ for (final Path entry : stream) {
+ if (Files.isDirectory(entry)) {
+ paths.addAll(listFilesWithExtensionRecursively(entry, fileExtension));
+ } else {
+ paths.add(entry);
+ }
+ }
+ }
+ return paths;
+ }
+
+ private static String symbolicNameFromDeclaration(final String symbolicNameDeclaration) {
+ return symbolicNameDeclaration.split(";")[0];
+ }
+
+}
diff --git a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFilesUtility.java b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/ReadProjectFilesUtility.java
similarity index 90%
rename from osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFilesUtility.java
rename to osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/ReadProjectFilesUtility.java
index 6e9fd99..363c89b 100644
--- a/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/ReadProjectFilesUtility.java
+++ b/osgi/de.cau.cs.kieler.spviz.osgi.generate/src/de/cau/cs/kieler/spviz/osgi/generate/util/ReadProjectFilesUtility.java
@@ -15,7 +15,7 @@
//
// ******************************************************************************
-package de.cau.cs.kieler.spviz.osgi.generate;
+package de.cau.cs.kieler.spviz.osgi.generate.util;
import java.lang.System.Logger;
import java.util.Comparator;
@@ -38,7 +38,7 @@ public class ReadProjectFilesUtility {
* This method takes an interface name, and returns the belonging bundle.
*
*/
- static Bundle getBundleFromInterface(String interfaceName, OSGiProject project) {
+ public static Bundle getBundleFromInterface(String interfaceName, OSGiProject project) {
return project.getBundles().stream()//
.filter(bundle -> interfaceName.startsWith(bundle.getName()))//
.max(Comparator.comparingInt(x -> x.getEcoreId().length()))
diff --git a/osgi/osgi.spviz b/osgi/osgi.spviz
index e5ed160..8c61f09 100644
--- a/osgi/osgi.spviz
+++ b/osgi/osgi.spviz
@@ -14,19 +14,34 @@ SPViz OSGiViz {
connect OSGi.ServiceComponent.Required via OSGi.Bundle in Services
connect OSGi.ServiceInterface.ProvidedBy via OSGi.Bundle in Services
}
- BundleDependencies {
+
+ RequireBundleDependencies {
+ show OSGi.Bundle
+ connect OSGi.Bundle.Dependency
+ }
+
+ BundlePackageDependencies {
+ show OSGi.Bundle
+ show OSGi.Package
+ connect OSGi.Bundle.PackageExportDependency
+ connect OSGi.Bundle.PackageImportDependency
+ connect OSGi.Bundle.PackageDependency
+ }
+
+ AllDependencies {
show OSGi.Bundle
connect OSGi.Bundle.Dependency
-// connect OSGi.Bundle via OSGi.Bundle.PackageDependency
+ // connect OSGi.Bundle via OSGi.Bundle.PackageDependency
+ connect OSGi.Bundle.PackageDependency
}
+
Products {
show OSGi.Product
-// connect OSGi.Bundle.Dependency via OSGi.Product>OSGi.Feature>OSGi.Bundle
+ // connect OSGi.Bundle.Dependency via OSGi.Product>OSGi.Feature>OSGi.Bundle
}
Features {
show OSGi.Feature
- connect OSGi.Bundle.Dependency via OSGi.Feature in BundleDependencies
- // connect Feature to Feature via source Feature>Bundle and target Feature>Bundle >Dep
+ connect OSGi.Bundle.Dependency via OSGi.Feature in RequireBundleDependencies
}
OSGi.Product shows {
@@ -34,15 +49,33 @@ SPViz OSGiViz {
OSGi.ServiceInterface from OSGi.Product>OSGi.Bundle>OSGi.ServiceInterface
OSGi.ServiceComponent from OSGi.Product>OSGi.Bundle>OSGi.ServiceComponent
}
- BundleDependencies with {
+ RequireBundleDependencies with {
OSGi.Bundle from OSGi.Product>OSGi.Bundle
}
+ BundlePackageDependencies with {
+ OSGi.Bundle from OSGi.Product>OSGi.Bundle
+ OSGi.Package from OSGi.Product>OSGi.Package
+ }
+ AllDependencies with {
+ OSGi.Bundle from OSGi.Product>OSGi.Bundle
+ }
+ Features with {
+ OSGi.Feature from OSGi.Product>OSGi.Feature
+ }
}
OSGi.Feature shows {
- BundleDependencies with {
+ RequireBundleDependencies with {
OSGi.Bundle from OSGi.Feature>OSGi.Bundle
}
+ BundlePackageDependencies with {
+ OSGi.Bundle from OSGi.Feature>OSGi.Bundle
+ OSGi.Package from OSGi.Feature>OSGi.Bundle>OSGi.Package
+ }
+ AllDependencies with {
+ OSGi.Bundle from OSGi.Feature>OSGi.Bundle
+ }
+
}
OSGi.Bundle shows {
diff --git a/osgi/osgi.spvizmodel b/osgi/osgi.spvizmodel
index 9ceb846..d282353 100644
--- a/osgi/osgi.spvizmodel
+++ b/osgi/osgi.spvizmodel
@@ -4,16 +4,19 @@ SPVizModel OSGi {
Product {
contains Feature
contains Bundle
+ contains Package
}
Feature {
contains Bundle
}
Bundle {
Dependency connects Bundle
- PackageDependency connects Package
+ PackageExportDependency connects Package
+ PackageImportDependency connects Package
+ PackageDependency connects Bundle
+ contains Package
contains ServiceInterface
contains ServiceComponent
- contains Package
}
ServiceInterface {
ProvidedBy connects ServiceComponent