SHA256
1
0
forked from pool/aqute-bnd
aqute-bnd/0003-Remove-unmet-dependencies.patch

1424 lines
37 KiB
Diff

From eb69b1fbbbac79a99456648c655e17ffd9743dca Mon Sep 17 00:00:00 2001
From: Marian Koncek <mkoncek@redhat.com>
Date: Fri, 24 Jun 2022 14:55:51 +0200
Subject: [PATCH 3/5] Remove unmet dependencies
---
.../src/aQute/lib/bundles/BundleIdentity.java | 65 --
.../startlevel/StartLevelRuntimeHandler.java | 325 ---------
aQute.libg/src/aQute/libg/dtos/DTOMap.java | 143 ----
aQute.libg/src/aQute/libg/dtos/DTOs.java | 211 ------
aQute.libg/src/aQute/libg/dtos/DTOsImpl.java | 615 ------------------
.../src/aQute/bnd/build/ProjectLauncher.java | 1 -
6 files changed, 1360 deletions(-)
delete mode 100644 aQute.libg/src/aQute/lib/bundles/BundleIdentity.java
delete mode 100644 aQute.libg/src/aQute/lib/startlevel/StartLevelRuntimeHandler.java
delete mode 100644 aQute.libg/src/aQute/libg/dtos/DTOMap.java
delete mode 100644 aQute.libg/src/aQute/libg/dtos/DTOs.java
delete mode 100644 aQute.libg/src/aQute/libg/dtos/DTOsImpl.java
diff --git a/aQute.libg/src/aQute/lib/bundles/BundleIdentity.java b/aQute.libg/src/aQute/lib/bundles/BundleIdentity.java
deleted file mode 100644
index dfd4b6af1..000000000
--- a/aQute.libg/src/aQute/lib/bundles/BundleIdentity.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package aQute.lib.bundles;
-
-import java.util.Map;
-import java.util.Objects;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Version;
-import org.osgi.framework.dto.BundleDTO;
-
-public class BundleIdentity {
- final String bsn;
- final Version version;
-
- public BundleIdentity(String bsn, Version version) {
- Objects.requireNonNull(bsn, "bsn must be specified");
- this.bsn = bsn;
- this.version = version == null ? Version.emptyVersion : version;
- }
-
- public BundleIdentity(Bundle bundle) {
- this(bundle.getSymbolicName(), bundle.getVersion());
- }
-
- public BundleIdentity(BundleDTO bundle) {
- this(bundle.symbolicName, bundle.version);
- }
-
- public BundleIdentity(String bsn, String version) {
- this(bsn, version == null ? null : Version.parseVersion(version));
- }
-
- public BundleIdentity(Map.Entry<String, Version> entry) {
- this(entry.getKey(), entry.getValue());
- }
-
- public String getBundleSymbolicName() {
- return bsn;
- }
-
- public Version getVersion() {
- return version;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(bsn, version);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- BundleIdentity other = (BundleIdentity) obj;
- return Objects.equals(bsn, other.bsn) && Objects.equals(version, other.version);
- }
-
- @Override
- public String toString() {
- return bsn + "-" + version;
- }
-}
diff --git a/aQute.libg/src/aQute/lib/startlevel/StartLevelRuntimeHandler.java b/aQute.libg/src/aQute/lib/startlevel/StartLevelRuntimeHandler.java
deleted file mode 100644
index 94dfc350b..000000000
--- a/aQute.libg/src/aQute/lib/startlevel/StartLevelRuntimeHandler.java
+++ /dev/null
@@ -1,325 +0,0 @@
-package aQute.lib.startlevel;
-
-import java.io.Closeable;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.SynchronousBundleListener;
-import org.osgi.framework.launch.Framework;
-import org.osgi.framework.startlevel.BundleStartLevel;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-
-import aQute.lib.bundles.BundleIdentity;
-import aQute.libg.parameters.ParameterMap;
-
-/**
- * Support to handle start levels in a launcher. This code is related to code in
- * the Project Launcher. It is in aQute.lib so it can be included easily in the
- * Launcher, the Remote launcher, and Launchpad.
- * <p>
- * This class is not threadsafe!
- */
-public class StartLevelRuntimeHandler implements Closeable {
-
- /**
- * If this property is set we take on start levels, if this property is not
- * set we ignore the startlevels completely. This is defined in
- * aQute.bnd.osgi.Constants
- */
- public static String LAUNCH_STARTLEVEL_DEFAULT = "launch.startlevel.default";
- public static String LAUNCH_RUNBUNDLES_ATTRS = "launch.runbundles.attrs";
-
- /**
- * Indicate if this class supports start levels or not.
- *
- * @return true if this class supports startlevels
- */
- public boolean hasStartLevels() {
- return false;
- }
-
- /**
- * Set the start level of a bundle
- *
- * @param b the bundle
- */
- public void setStartLevel(Bundle b) {}
-
- /**
- * Answer the current framework start level
- *
- * @param framework the framework
- * @return the current start level of the framework
- */
- public int getFrameworkStartLevel(Framework framework) {
- return framework.adapt(FrameworkStartLevel.class)
- .getStartLevel();
- }
-
- /**
- * Set the default start level of newly installed bundles
- *
- * @param framework the framework
- * @param level the default start level
- */
- public void setDefaultStartlevel(Framework framework, int level) {
- framework.adapt(FrameworkStartLevel.class)
- .setInitialBundleStartLevel(level);
- }
-
- /**
- * Set the framework start level and return previous
- *
- * @param framework the framework
- * @param startlevel the start level to set
- * @param ls listeners
- * @return the previous start level of the framework
- */
- public int setFrameworkStartLevel(Framework framework, int startlevel, FrameworkListener... ls) {
- int previous = getFrameworkStartLevel(framework);
- framework.adapt(FrameworkStartLevel.class)
- .setStartLevel(startlevel, ls);
- return previous;
- }
-
- /**
- * Get a bundle's start level
- *
- * @param bundle the bundle to query
- * @return the start level > 0
- */
- public int getBundleStartLevel(Bundle bundle) {
- return bundle.adapt(BundleStartLevel.class)
- .getStartLevel();
- }
-
- /**
- * Set a bundle's start level
- *
- * @param bundle the bundle to query
- * @param startlevel start level to set, > 0
- */
- public void setBundleStartLevel(Bundle bundle, int startlevel) {
- bundle.adapt(BundleStartLevel.class)
- .setStartLevel(startlevel);
- }
-
- /**
- * Must be called before the framework is started.
- * <p>
- * ensure systemBundle.getState() == INIT and startlevel systemBundle == 0
- *
- * @param systemBundle the framework
- */
- public void beforeStart(Framework systemBundle) {}
-
- /**
- * When the configuration properties have been updated
- *
- * @param configuration the configuration properties
- */
- public void updateConfiguration(Map<String, ?> configuration) {}
-
- /**
- * Called after the framework is started and the launcher is ready
- */
- public void afterStart() {}
-
- /**
- * Wait for the framework to reach its start level. Must be called after the
- * {@link #afterStart()} method. Will return when the framework has
- * traversed all start levels.
- */
- public void sync() {}
-
- /**
- * Close this object
- */
-
- @Override
- public void close() {}
-
- /**
- * Create a start level handler. If the {@link #LAUNCH_STARTLEVEL_DEFAULT}
- * property is set we create an active handler that will direct the
- * framework properly according to the settings in Project Launcher. If not
- * set, a dummy is returned that does not do anything
- *
- * @param outerConfiguration the properties as set by the Project Launcher
- * @return an active or dummy {@link StartLevelRuntimeHandler}
- */
- static public StartLevelRuntimeHandler create(Trace logger, Map<String, String> outerConfiguration) {
-
- String defaultStartlevelString = outerConfiguration.get(LAUNCH_STARTLEVEL_DEFAULT);
- if (defaultStartlevelString == null) {
- logger.trace("startlevel: not handled because %s not set", LAUNCH_STARTLEVEL_DEFAULT);
- return absent();
- }
-
- int tmp = toInt(defaultStartlevelString, 1);
- if (tmp == 0) {
- logger.trace("startlevel: disabled because property %s==%s", LAUNCH_STARTLEVEL_DEFAULT,
- defaultStartlevelString);
- return absent();
- }
-
-
- int defaultStartlevel;
- boolean manageAll;
- if (tmp > 0) {
- manageAll = !Boolean.getBoolean("biz.aQute.launcher.scoped");
- defaultStartlevel = tmp;
- } else {
- manageAll = false;
- defaultStartlevel = -tmp;
- }
-
- int beginningStartlevel = toInt(outerConfiguration.get(Constants.FRAMEWORK_BEGINNING_STARTLEVEL), 1);
- outerConfiguration.put(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, "1");
-
- logger.trace("startlevel: handled begin=%s default=%s managed=%s", beginningStartlevel, defaultStartlevel,
- manageAll ? "all" : "narrow");
-
- //
- // We need to remove it otherwise the framework reacts to it
- //
-
- return new StartLevelRuntimeHandler() {
- CountDownLatch latch = new CountDownLatch(1);
- private Framework systemBundle;
- private Map<BundleIdentity, Integer> startlevels = new HashMap<>();
- private Map<Bundle, BundleIdentity> installed = new HashMap<>();
-
- @Override
- public void beforeStart(Framework systemBundle) {
- assert getFrameworkStartLevel(
- systemBundle) == 0 : "Expects the framework to be in init mode, not yet started";
-
- this.systemBundle = systemBundle;
-
- if (manageAll) {
- manageAll(systemBundle);
- }
-
- updateConfiguration(outerConfiguration);
-
- setDefaultStartlevel(this.systemBundle, defaultStartlevel);
-
- systemBundle.getBundleContext()
- .addBundleListener((SynchronousBundleListener) event -> {
- Bundle bundle = event.getBundle();
- if (bundle.getBundleId() == 0)
- return;
-
- if (bundle.getSymbolicName() == null) {
- logger.trace("Found bundle without a bsn %s, ignoring", bundle);
- return;
- }
-
- BundleIdentity id = installed.computeIfAbsent(bundle, BundleIdentity::new);
- if (event.getType() == BundleEvent.INSTALLED || event.getType() == BundleEvent.UPDATED) {
- setStartlevel(bundle, id);
- } else if (event.getType() == BundleEvent.UNINSTALLED) {
- installed.remove(bundle);
- }
- });
- logger.trace("startlevel: default=%s, beginning=%s", defaultStartlevel, beginningStartlevel);
-
- }
-
- private void manageAll(Framework systemBundle) {
- for (Bundle bundle : systemBundle.getBundleContext()
- .getBundles()) {
- if (bundle.getBundleId() != 0 && bundle.getSymbolicName() != null) {
- installed.put(bundle, new BundleIdentity(bundle));
- }
- }
- }
-
- @Override
- public void afterStart() {
- setFrameworkStartLevel(systemBundle, beginningStartlevel, event -> {
- logger.trace("startlevel: notified reached final level %s : %s", beginningStartlevel, event);
- latch.countDown();
- });
- logger.trace("startlevel change begin: beginning level %s", beginningStartlevel);
- }
-
- @Override
- public void sync() {
- try {
- latch.await();
- } catch (InterruptedException ie) {
- Thread.interrupted();
- throw new RuntimeException(ie);
- }
- }
-
- @Override
- public boolean hasStartLevels() {
- return true;
- }
-
- @Override
- public void updateConfiguration(Map<String, ?> configuration) {
- new ParameterMap((String) configuration.get(LAUNCH_RUNBUNDLES_ATTRS)).entrySet()
- .forEach(entry -> {
- String bsn = ParameterMap.removeDuplicateMarker(entry.getKey());
- String version = entry.getValue()
- .getVersion();
- BundleIdentity id = new BundleIdentity(bsn, version);
-
- int startlevel = toInt(entry.getValue()
- .get("startlevel"), -1);
- if (startlevel > 0) {
- startlevels.put(id, startlevel);
- }
- });
-
- installed.forEach(this::setStartlevel);
- }
-
- private void setStartlevel(Bundle bundle, BundleIdentity id) {
- if (bundle.getState() != Bundle.UNINSTALLED) {
- int level = startlevels.getOrDefault(id, -1);
- if (level == -1)
- level = defaultStartlevel;
-
- setBundleStartLevel(bundle, level);
- logger.trace("startlevel: %s <- %s", bundle, level);
- }
- }
-
- };
- }
-
- static int toInt(Object object, int defltValue) {
- if (object == null)
- return defltValue;
-
- String s = object.toString()
- .trim();
- try {
- return Integer.parseInt(s);
- } catch (NumberFormatException nfe) {
- return defltValue;
- }
- }
-
- public static StartLevelRuntimeHandler absent() {
- return new StartLevelRuntimeHandler() {};
- }
-
- @SuppressWarnings({
- "rawtypes", "unchecked"
- })
- public static StartLevelRuntimeHandler create(Trace reporter, Properties properties) {
- return create(reporter, (Map) properties);
- }
-}
diff --git a/aQute.libg/src/aQute/libg/dtos/DTOMap.java b/aQute.libg/src/aQute/libg/dtos/DTOMap.java
deleted file mode 100644
index f927de5f7..000000000
--- a/aQute.libg/src/aQute/libg/dtos/DTOMap.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package aQute.libg.dtos;
-
-import java.lang.reflect.Field;
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-import org.osgi.dto.DTO;
-
-public class DTOMap extends AbstractMap<String, Object> {
-
- private final DTOsImpl dtos;
- private final Object dto;
- private final Field[] fields;
-
- public DTOMap(DTOsImpl dtos, Object dto) {
- this.dtos = dtos;
- this.dto = dto;
- this.fields = dtos.getFields(dto);
- }
-
- @Override
- public int size() {
- return fields.length;
- }
-
- @Override
- public boolean isEmpty() {
- return fields.length == 0;
- }
-
- @Override
- public boolean containsKey(Object key) {
- if (!(key instanceof String))
- return false;
-
- return dtos.bsearch(fields, 0, fields.length, (String) key) >= 0;
- }
-
- @Override
- public boolean containsValue(Object value) {
- for (Field f : fields) {
- Object o;
- try {
- o = f.get(dto);
-
- if (o == value)
- return true;
- if (o == null)
- return false;
-
- return o.equals(value);
- } catch (IllegalArgumentException | IllegalAccessException e) {
- // Ignore since we only have public fields
- }
- }
- return false;
- }
-
- @Override
- public Object get(Object key) {
- try {
- if (!(key instanceof String))
- return null;
-
- Field field = dtos.getField(fields, (String) key);
- if (field == null)
- return null;
-
- Object o = field.get(dto);
- if (o instanceof DTO) {
- return new DTOMap(dtos, o);
- } else
- return o;
- } catch (IllegalArgumentException | IllegalAccessException e) {
- // cannot happen
- return null;
- }
- }
-
- @Override
- public Set<java.util.Map.Entry<String, Object>> entrySet() {
- return new AbstractSet<Map.Entry<String, Object>>() {
-
- @Override
- public Iterator<java.util.Map.Entry<String, Object>> iterator() {
- return new Iterator<Map.Entry<String, Object>>() {
- int n = 0;
-
- @Override
- public boolean hasNext() {
- return n < fields.length;
- }
-
- @Override
- public java.util.Map.Entry<String, Object> next() {
- final Field field = fields[n];
- n++;
- return new Map.Entry<String, Object>() {
-
- @Override
- public String getKey() {
- return field.getName();
- }
-
- @Override
- public Object getValue() {
- try {
- return field.get(dto);
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public Object setValue(Object value) {
- try {
- Object old = field.get(dto);
- field.set(dto, value);
- return old;
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
- };
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException("A DTO map cannot remove entries");
- }
- };
- }
-
- @Override
- public int size() {
- return DTOMap.this.size();
- }
- };
- }
-}
diff --git a/aQute.libg/src/aQute/libg/dtos/DTOs.java b/aQute.libg/src/aQute/libg/dtos/DTOs.java
deleted file mode 100644
index a8abdb148..000000000
--- a/aQute.libg/src/aQute/libg/dtos/DTOs.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package aQute.libg.dtos;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.osgi.annotation.versioning.ProviderType;
-import org.osgi.dto.DTO;
-
-/**
- * This interface provides a number of utilities to make it easy to work with
- * DTOs. It contains a number of utility functions.
- */
-@ProviderType
-public interface DTOs {
-
- DTOs INSTANCE = new DTOsImpl();
-
- /**
- * Return a partially read only Map object that maps directly to a DTO. I.e.
- * changes are reflected in the DTO. If a field is a DTO, then this field
- * will also become a Map.
- *
- * @param dto the DTO
- * @return a Map where the keys map to the field names and the values to the
- * field values. This map is not modifiable.
- */
- Map<String, Object> asMap(Object dto);
-
- /**
- * Convert a DTO to a human readable string presentation. This is primarily
- * for debugging since the toString can truncate fields. This method must
- * print all public fields, also non primary. Output formats can vary (e.g.
- * YAML like) so the actual output should NOT be treated as standard.
- *
- * @param dto the dto to turn into a string
- * @return a human readable string (not json!)
- */
- String toString(Object dto);
-
- /**
- * Check if two dtos fields are equal. This is shallow equal, that is the
- * fields of this DTO are using the equals() instance method.
- *
- * @param a the first object
- * @param b the second object
- * @return true if both are null or the DTO's primary fields are equal
- */
- boolean equals(Object a, Object b);
-
- /**
- * Check if two DTOs fields are equal. This is deep equal, that is the
- * fields of this DTO are using this method is the object at a field is a
- * DTO, recursively.
- *
- * @param a the first object
- * @param b the second object
- * @return true if both are null or the DTO's primary fields are equal
- */
- boolean deepEquals(Object a, Object b);
-
- /**
- * Calculate a hash Code for the fields in this DTO. The dto must have at
- * least one public field.
- *
- * @param dto the object to calculate the hashcode for, must not be null .
- * @return a hashcode
- */
- int hashCode(Object dto);
-
- /**
- * Access a DTO with a path. A path is a '.' separated string. Each part in
- * the path is either a field name, key in a map, or an index in a list. If
- * the path segments contain dots or backslashes, then these must be escaped
- *
- * @param dto the root
- * @param path the path, should only contain dots as separators
- * @return the value of the object or empty if not found.
- */
-
- Optional<Object> get(Object dto, String path);
-
- /**
- * Access a DTO with a path that consists of an array with segments. Each
- * segment in the path is either a field name, key in a map, or an index in
- * a list.
- *
- * @param dto the root
- * @param path the path
- * @return the value of the object or empty if not found.
- */
- Optional<Object> get(Object dto, String... path);
-
- /**
- * Return a list of paths where the two objects differ. The objects must be
- * of the same class.
- *
- * @param older the older object
- * @param newer the newer object
- * @return A list of differences, if there is no difference, the list is
- * empty.
- */
- List<Difference> diff(Object older, Object newer);
-
- /**
- * The details of a difference
- */
- class Difference extends DTO {
- /**
- * The path where there was a difference
- */
- public String path[];
-
- /**
- * The reason why there was a difference
- */
- public Reason reason;
- }
-
- /**
- * The reason for a difference.
- */
- enum Reason {
- UNEQUAL,
- REMOVED,
- ADDED,
- DIFFERENT_TYPES,
- SIZE,
- KEYS,
- NO_STRING_MAP,
- INVALID_KEY;
- }
-
- /**
- * Takes a path with escaped '.'and '\' and then turns it into an array of
- * unescaped keys
- *
- * @param path the path with escaped \ and .
- * @return a path array with unescaped segments
- */
- String[] fromPathToSegments(String path);
-
- /**
- * Takes a path with unescaped keys and turns it into a string path where
- * the \ and . are escaped.
- *
- * @param segments The unescaped segments of the path
- * @return a string path where the . and \ are escaped.
- */
- String fromSegmentsToPath(String[] segments);
-
- /**
- * Escape a string to be used in a path. This will put a backslash ('\') in
- * front of full stops ('.') and the backslash ('\').
- *
- * @param unescaped the string to be escaped
- * @return a string where all '.' and '\' are escaped with a '\'.
- */
- String escape(String unescaped);
-
- /**
- * Unescapes a string to be used in a path. This will remove a backslash
- * ('\') in front of full stops ('.') and the backslash ('\').
- *
- * @param escaped the string to be unescaped
- * @return a string where all '\.' and '\\' have the preceding backslash
- * removed with a '\'.
- */
- String unescape(String escaped);
-
- /**
- * Return true if the give dto is complex (either Map, Collection, Array, or
- * has public fields.
- *
- * @param object The DTO to check
- * @return <code>true</code> if this is a DTO with fields or length.
- */
-
- boolean isComplex(Object object);
-
- /**
- * An object with public non-static non-synthetic fields.
- *
- * @param dto the object to check
- * @return true if this object has public fields or extends DTO
- */
- boolean isDTO(Object dto);
-
- /**
- * Create a shallow copy of a DTO. This will create a new object of the same
- * type and copy the public fields of the source to the new copy. It will
- * not create a copy for these values.
- *
- * @param object the source object
- * @return a shallow copy of object
- */
-
- <T> T shallowCopy(T object);
-
- /**
- * Create a deep copy of a DTO. This will copy the fields of the DTO. Copied
- * values will also be created anew if they are complex (Map, Collection,
- * DTO, or Array). Other objects are assumed to be immutable unless they
- * implement Cloneable.
- *
- * @param object the object to deep copy
- * @return the deep copied object
- */
-
- <T> T deepCopy(T object);
-}
diff --git a/aQute.libg/src/aQute/libg/dtos/DTOsImpl.java b/aQute.libg/src/aQute/libg/dtos/DTOsImpl.java
deleted file mode 100644
index 6de46b60d..000000000
--- a/aQute.libg/src/aQute/libg/dtos/DTOsImpl.java
+++ /dev/null
@@ -1,615 +0,0 @@
-package aQute.libg.dtos;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Formatter;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Optional;
-import java.util.WeakHashMap;
-import java.util.regex.Pattern;
-
-import org.osgi.dto.DTO;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import aQute.bnd.exceptions.Exceptions;
-
-public class DTOsImpl implements DTOs {
- private final static Logger logger = LoggerFactory.getLogger(DTOsImpl.class);
- private final Field[] EMPTY_FIELDS = new Field[0];
- private final Map<Class<?>, Field[]> cache = Collections
- .synchronizedMap(new WeakHashMap<Class<?>, Field[]>());
-
- private final Link root = new Link(null, null, null);
-
- //
- // The link class is to keep track of cycles traversing and to
- // maintain the path at minimum cost.
- //
-
- static class Link {
- final Link prev;
- final Object object;
- final Object name;
-
- public Link(Link link, Object name, Object object) {
- this.prev = link;
- this.name = name;
- this.object = object;
- }
-
- boolean isCycle(Object t) {
- if (this.object == t)
- return true;
- else if (prev == null)
- return false;
- else
- return prev.isCycle(t);
- }
-
- String[] getPath(int n) {
- if (prev == null) {
- String[] path = new String[n];
- return path;
- }
- String[] path = prev.getPath(n + 1);
- path[path.length - n - 1] = name.toString();
- return path;
- }
-
- void verifyCycle(Object o) {
- if (isCycle(o)) {
- throw new IllegalArgumentException("Cycle in DTO " + Arrays.toString(getPath(0)));
- }
- }
- }
-
- static class Diff extends Difference {
- public Diff(Reason reason, Link link) {
- this.reason = reason;
- this.path = link.getPath(0);
- }
- }
-
- @Override
- public Map<String, Object> asMap(Object dto) {
- return new DTOMap(this, dto);
- }
-
- Field[] getFields(Object o) {
- if (o == null)
- return EMPTY_FIELDS;
- return getFields(o.getClass());
- }
-
- Field[] getFields(Class<?> c) {
- Field fields[] = cache.get(c);
- if (fields == null) {
- List<Field> publicFields = new ArrayList<>();
-
- for (Field field : c.getFields()) {
- if (field.isEnumConstant() || field.isSynthetic() || Modifier.isStatic(field.getModifiers()))
- continue;
- publicFields.add(field);
- }
- Collections.sort(publicFields, new Comparator<Field>() {
-
- @Override
- public int compare(Field o1, Field o2) {
- return o1.getName()
- .compareTo(o2.getName());
- }
- });
-
- cache.put(c.getClass(), fields = publicFields.toArray(new Field[publicFields.size()]));
- }
- return fields;
- }
-
- int bsearch(Field[] a, int fromIndex, int toIndex, String key) {
- int low = fromIndex;
- int high = toIndex - 1;
-
- while (low <= high) {
- int mid = (low + high) >>> 1;
- Field midVal = a[mid];
- int cmp = midVal.getName()
- .compareTo(key);
- if (cmp < 0)
- low = mid + 1;
- else if (cmp > 0)
- high = mid - 1;
- else
- return mid; // key found
- }
- return -(low + 1); // key not found.
- }
-
- Field getField(Field[] fields, String name) {
- int index = bsearch(fields, 0, fields.length, name);
- if (index < 0)
- return null;
- else
- return fields[index];
- }
-
- /**
- * Shallow copy
- */
-
- @SuppressWarnings({
- "unchecked", "rawtypes"
- })
- @Override
- public <T> T shallowCopy(T source) {
- try {
- if (!isComplex(source))
- return source;
-
- Class<T> c = (Class<T>) source.getClass();
-
- if (c.isArray()) {
- int l = Array.getLength(source);
- T dest = (T) Array.newInstance(c.getComponentType(), l);
- System.arraycopy(source, 0, dest, 0, l);
- return dest;
- }
-
- T dest = c.newInstance();
-
- if (source instanceof Map) {
- ((Map) dest).putAll((Map) source);
- return dest;
- }
-
- if (source instanceof Collection) {
- ((Collection) dest).addAll((Collection) source);
- return dest;
- }
-
- for (Field field : getFields(c)) {
- field.set(dest, field.get(source));
- }
- return dest;
- } catch (Exception e) {
- throw Exceptions.duck(e);
- }
- }
-
- /**
- * Deep copy
- */
-
- @Override
- public <T> T deepCopy(T source) {
- return deepCopy(source, root);
- }
-
- @SuppressWarnings({
- "unchecked", "rawtypes"
- })
- <T> T deepCopy(T source, Link link) {
- try {
- if (!isComplex(source))
- return source;
-
- link.verifyCycle(source);
-
- Class<T> c = (Class<T>) source.getClass();
-
- if (c.isArray()) {
- int l = Array.getLength(source);
- T dest = (T) Array.newInstance(c.getComponentType(), l);
-
- for (int i = 0; i < l; i++) {
- Object s = Array.get(source, i);
- Array.set(dest, i, deepCopy(s, new Link(link, i, source)));
- }
- return dest;
- }
-
- T dest = c.newInstance();
-
- if (source instanceof Map) {
- Map<Object, Object> d = (Map<Object, Object>) dest;
- Map<Object, Object> s = (Map<Object, Object>) source;
- for (Entry<?, ?> entry : s.entrySet()) {
- Link next = new Link(link, entry.getKey(), source);
- d.put(deepCopy(entry.getKey(), next), deepCopy(entry.getValue(), next));
- }
- return dest;
- }
-
- if (source instanceof Collection) {
- Collection s = (Collection) source;
- Collection d = (Collection) dest;
- int i = 0;
- for (Object o : s) {
- Link next = new Link(link, i++, source);
- d.add(deepCopy(o, next));
- }
- return dest;
- }
-
- for (Field field : getFields(c)) {
- Link next = new Link(link, field.getName(), source);
- field.set(dest, deepCopy(field.get(source), next));
- }
- return dest;
- } catch (Exception e) {
- throw Exceptions.duck(e);
- }
-
- }
-
- @Override
- public String[] fromPathToSegments(String path) {
- return fromPathToSegments(path, 0, 0);
- }
-
- String[] fromPathToSegments(String path, int start, int n) {
- if (start >= path.length()) {
- return new String[n];
- }
-
- StringBuilder sb = new StringBuilder();
- int i = start;
- outer: for (; i < path.length(); i++) {
- char c = path.charAt(i);
- switch (c) {
-
- case '.' :
- break outer;
-
- case '\\' :
- c = path.charAt(++i);
- assert c == '.' || c == '\\';
-
- default :
- sb.append(c);
- break;
- }
- }
- String[] result = fromPathToSegments(path, i + 1, n + 1);
- result[n] = sb.toString();
- return result;
- }
-
- @Override
- public String fromSegmentsToPath(String[] segments) {
- StringBuilder sb = new StringBuilder();
- String del = "";
- for (String segment : segments) {
- sb.append(del);
- for (int i = 0; i < segment.length(); i++) {
- char c = segment.charAt(i);
- switch (c) {
- case '\\' :
- case '.' :
- sb.append('\\');
-
- // FALL THROUGH
-
- default :
- sb.append(c);
- break;
- }
- }
- del = ".";
- }
- return sb.toString();
- }
-
- @Override
- public boolean deepEquals(Object a, Object b) {
- try {
- return diff(a, b).isEmpty();
- } catch (Exception e) {
- throw Exceptions.duck(e);
- }
- }
-
- @Override
- public String toString(Object dto) {
- if (dto == null)
- return null + "";
-
- Field[] fields = getFields(dto);
- if (fields.length == 0)
- return dto.toString();
-
- try {
- try (Formatter format = new Formatter()) {
- for (Field f : fields) {
- format.format("%s: %s%n", f.getName(), f.get(dto));
- }
- return format.toString();
- }
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public boolean equals(Object a, Object b) {
- try {
- return diff(a, b).isEmpty();
- } catch (Exception e) {
- return false;
- }
- }
-
- @Override
- public int hashCode(Object dto) {
- Field[] fields = getFields(dto);
- if (fields.length == 0)
- return dto.hashCode();
-
- int prime = 31;
- int result = 1;
- try {
-
- for (Field f : fields) {
- Object a = f.get(this);
- result = prime * result + (a == null ? 0 : hashCode(dto));
- }
-
- return result;
- } catch (Exception e) {
- return result;
- }
- }
-
- @Override
- public Optional<Object> get(Object dto, String path) {
- return get(dto, fromPathToSegments(path));
- }
-
- @Override
- public Optional<Object> get(Object dto, String... path) {
- return get(dto, path, 0, path.length);
- }
-
- private Optional<Object> get(Object dto, String[] path, int i, int max) {
- try {
- if (i > path.length)
- throw new IllegalArgumentException("Incorrect index in path " + Arrays.toString(path) + "[" + i + "]");
-
- if (i == path.length || i == max)
- return Optional.of(dto);
-
- if (dto == null)
- return Optional.empty();
-
- String name = path[i];
-
- if (dto.getClass()
- .isArray()) {
- int index = Integer.parseInt(name);
- if (index >= Array.getLength(dto))
- throw new IllegalArgumentException(
- "path access contains an array but the corresponding index is not an integer: "
- + Arrays.toString(path) + "[" + i + "]");
-
- return get(Array.get(dto, index), path, i + 1, max);
- }
-
- if (dto instanceof Collection) {
- Collection<?> coll = (Collection<?>) dto;
- int index = Integer.parseInt(name);
- if (index >= coll.size())
- throw new IllegalArgumentException("path access contains a collection but the corresponding index is not an integer: "
- + Arrays.toString(path) + "[" + i + "]");
-
- if (coll instanceof List) {
- return get(((List<?>) coll).get(index), path, i + 1, max);
- }
- for (Object o : coll) {
- if (index-- == 0)
- return get(o, path, i + 1, max);
- }
- assert false;
- return null; // unreachable
- }
-
- if (dto instanceof Map) {
- Object value = ((Map<?, ?>) dto).get(name);
- return get(value, path, i + 1, max);
- }
-
- Field fields[] = getFields(dto);
- if (fields.length > 0) {
- for (Field field : fields) {
- if (field.getName()
- .equals(name)) {
- return get(field.get(dto), path, i + 1, max);
- }
- }
- }
-
- throw new IllegalArgumentException("Unknown type to traverse " + dto.getClass() + " for " + name);
- } catch (Exception e) {
- throw Exceptions.duck(e);
- }
- }
-
- @Override
- public List<Difference> diff(Object older, final Object newer) {
- List<Difference> diffs = new ArrayList<>();
- diff(diffs, root, older, newer);
- return diffs;
- }
-
- private boolean diff(List<Difference> diffs, Link link, Object older, Object newer) {
- try {
- if (older == newer)
- return false;
-
- if (older == null) {
- diffs.add(new Diff(Reason.ADDED, link));
- return true;
- }
-
- if (newer == null) {
- diffs.add(new Diff(Reason.REMOVED, link));
- return true;
- }
-
- Class<?> oc = older.getClass();
- Class<?> nc = newer.getClass();
- if (oc != nc) {
- diffs.add(new Diff(Reason.DIFFERENT_TYPES, link));
- return true;
- }
-
- if (older.equals(newer))
- return true;
-
- if (older instanceof Collection<?>) {
- Collection<?> co = (Collection<?>) older;
- Collection<?> cn = (Collection<?>) newer;
-
- if (co.size() != cn.size()) {
- diffs.add(new Diff(Reason.SIZE, link));
- return true;
- }
-
- if (co.equals(cn))
- return false;
-
- //
- // They're different, if it is a list we can find out which
- //
-
- if (older instanceof List<?>) {
- List<?> clo = (List<?>) older;
- List<?> cln = (List<?>) newer;
-
- for (int i = 0; i < co.size(); i++) {
- Object lo = clo.get(i);
- Object ln = cln.get(i);
- diff(diffs, new Link(link, i, older), lo, ln);
- }
- return true;
- }
-
- //
- // If not a list, we're lost ...
- //
-
- diffs.add(new Diff(Reason.UNEQUAL, link));
- return true;
- }
-
- if (oc.isArray()) {
- Object[] ao = new Object[] {
- older
- };
- Object[] an = new Object[] {
- newer
- };
- if (Arrays.deepEquals(ao, an)) {
- return false;
- }
-
- int lo = Array.getLength(older);
- int ln = Array.getLength(newer);
- if (lo != ln) {
- diffs.add(new Diff(Reason.SIZE, link));
- return true;
- }
-
- for (int i = 0; i < lo; i++) {
- diff(diffs, new Link(link, i, older), Array.get(older, i), Array.get(newer, i));
- }
- return true;
- }
-
- if (older instanceof Map<?, ?>) {
- Map<?, ?> co = (Map<?, ?>) older;
- Map<?, ?> cn = (Map<?, ?>) newer;
-
- if (co.size() != cn.size()) {
- diffs.add(new Diff(Reason.SIZE, link));
- return true;
- }
-
- if (co.equals(cn))
- return false;
-
- if (!co.keySet()
- .equals(cn.keySet())) {
- diffs.add(new Diff(Reason.KEYS, link));
- return true;
- }
-
- for (Map.Entry<?, ?> e : co.entrySet()) {
- Object key = e.getKey();
- if (!(key instanceof String)) {
- diffs.add(new Diff(Reason.NO_STRING_MAP, link));
- return true;
- }
-
- String k = escape((String) key);
-
- Object no = co.get(key);
- Object nn = cn.get(key);
-
- diff(diffs, new Link(link, k, older), no, nn);
- }
- return true;
- }
-
- Field[] fields = getFields(older);
- if (fields.length > 0) {
- for (Field field : fields) {
- Object o = field.get(older);
- Object n = field.get(newer);
- diff(diffs, new Link(link, field.getName(), older), o, n);
- }
- return true;
- }
-
- diffs.add(new Diff(Reason.UNEQUAL, link));
- return true;
- } catch (Exception e) {
- logger.warn("failed to diff %s to %s : %s", older, newer, e.getMessage(), e);
- throw Exceptions.duck(e);
- }
- }
-
- static Pattern ESCAPE_P = Pattern.compile("(\\.|\\\\)");
- static Pattern UNESCAPE_P = Pattern.compile("\\\\(\\.|\\\\)");
-
- @Override
- public String escape(String unescaped) {
- return ESCAPE_P.matcher(unescaped)
- .replaceAll("\\\\$1");
- }
-
- @Override
- public String unescape(String unescaped) {
- return UNESCAPE_P.matcher(unescaped)
- .replaceAll("$1");
- }
-
- @Override
- public boolean isComplex(Object a) {
- return a != null && (a instanceof Map || a instanceof Collection || a instanceof DTO || a.getClass()
- .isArray() || getFields(a).length > 0);
- }
-
- @Override
- public boolean isDTO(Object o) {
- return getFields(o).length != 0;
- }
-
-}
diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java
index e1ce42ffc..c1a3d87d5 100644
--- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java
+++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectLauncher.java
@@ -43,7 +43,6 @@ import aQute.bnd.osgi.Processor;
import aQute.bnd.osgi.Verifier;
import aQute.bnd.service.Strategy;
import aQute.lib.io.IO;
-import aQute.lib.startlevel.StartLevelRuntimeHandler;
import aQute.lib.strings.Strings;
import aQute.lib.watcher.FileWatcher;
import aQute.lib.watcher.FileWatcher.Builder;
--
2.46.0