What is the alternative to PackageAdmin.getFragments - osgi

With OSGi 4.3, I understand PackageAdmin has been deprecated. How do you then find the fragments for a specific bundle - i.e. what is the alternative to PackageAdmin.getFragments(Bundle bundle)?

Use the BundleWiring API to find the provided wires in the osgi.wiring.host namespace:
BundleWiring myWiring = myBundle.adapt(BundleWiring.class);
List<BundleWire> wires = myWiring.getProvidedWires(HostNamespace.HOST_NAMESPACE);
for (BundleWire wire : wires) {
Bundle fragment = wire.getRequirerWiring().getBundle();
}

Related

Use one version of java library or another => make code compatible for both

I'm working on a Spring Boot project built with Gradle and the main language is Kotlin.
In this project, there is one imported library (developed in Java) which, depending on the version I use, has 5 or 6 parameters in the constructor of a specific class I use.
For now, I switch between the versions manually by changing the version number in the build.gradle.kts file so my question would be : regardless of the version I use, how could my code work for all the versions ?
So, basically,
library-version1.jar => Class(6 parameters)
library-version2.jar => Class(5 parameters)
project with library-version1.jar or library-version2.jar imported => universal code to create instance of Class
P.S : may I add that I have to use those 2 versions of the library.
I found the solution for my initial question :
val yourVariable = YourClass::class.java
val constructor = yourVariable.constructors[0] //The class I use has only one constructor
val implementationVersion = yourVariable.`package`.implementationVersion
if (implementationVersion < "a specific version number") {
constructor.newInstance(6 parameters) as YourClass
} else {
constructor.newInstance(5 parameters) as YourClass
}
But now I have a follow-up question that you can find in the comments (I can still post it here though) :
In my build.gradle.kts file, I have this line in my dependencies :
dependencies {
implementation("myLibrary:1.0")
...
}
Obviously, I don't want to switch between myLibrary v1 and v2 manually. Just by changing the build.gradle.kts file, would it be possible to have :
build.gradle.kts -> appV1 (if myLibrary v1 used)
-> appV2 (if myLibrary v2 used)
?

Django Rest Framework: Creating a serializer with a ListField causes circular dependency error

I am new to Django and Rest Framework. I'm following the documentation on serializers and am trying to create a ListField (https://www.django-rest-framework.org/api-guide/fields/#listfield)
and when I do I get a nasty circular import error
django.core.exceptions.ImproperlyConfigured: The included URLconf 'api.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import.
My serializers file appears as:
class CapacitySerializer(serializers.Serializer):
planeIds = serializers.ListField(
planeId = serializers.IntegerField(min_value=0, max_value=10)
)
passangerNums = serializers.ListField(
passangerNum = serializers.IntegerField(min_value=0)
)
litersPerMinute = serializers.FloatField(required=False)
minutesOfFlight = serializers.FloatField(required=False)
The code would work if I simply left the code as:
class CapacitySerializer(serializers.Serializer):
planeId = serializers.IntegerField(min_value=0, max_value=10)
passangerNum = serializers.IntegerField(min_value=0)
litersPerMinute = serializers.FloatField(required=False)
minutesOfFlight = serializers.FloatField(required=False)
Any idea why this error is being thrown?
Additionally If I expect my data to be lists of planeIds and passengerNums is this not a good way to go about it?
versions:
Django==3.0.4
djangorestframework==3.11.0
The documentation linked required the use of the child parameter. Child is required and not a placeholder name

Is there a simply way to list of consumer components for an Interface?

Fellow coders,
I'm currently trying to find a simple and concise way to get a listing of of Services/Components that use a given Interface. I'm using the gogo-shell of a running Liferay 7.1.x server and can't seem to find an easy and direct way to to just that.
We want to override references to the used service via OSGI-configuration, but first need to find all components using it.
As there are static reluctant references to the service component, simply providing an alternative with a higher ranking is not a viable solution.
Here are the gogo related bundles I'm using:
35|Active | 6|Apache Felix Gogo Command (1.0.2)|1.0.2
36|Active | 6|Apache Felix Gogo Runtime (1.1.0.LIFERAY-PATCHED-2)|1.1.0.LIFERAY-PATCHED-2
72|Active | 6|Apache Felix Gogo Shell (1.1.0)|1.1.0
542|Active | 10|Liferay Foundation - Liferay Gogo Shell - Impl (1.0.13)|1.0.13
543|Active | 10|Liferay Gogo Shell Web (2.0.25)|2.0.25
So far I've been able to list all providers of an interface via se (interface=com.liferay.saml.runtime.servlet.profile.WebSsoProfile):
{com.liferay.saml.runtime.profile.WebSsoProfile, com.liferay.saml.runtime.servlet.profile.WebSsoProfile}={service.id=6293, service.bundleid=79, service.scope=bundle, component.name=com.liferay.saml.opensaml.integration.internal.servlet.profile.WebSsoProfileImpl, component.id=3963}
"Registered by bundle:" de.haufe.leong.com.liferay.saml.opensaml.integration [79]
"Bundles using service"
com.liferay.saml.web_2.0.11 [82]
com.liferay.saml.impl_2.0.12 [78]
See all bundle requirements via: inspect cap service:
com.liferay.saml.impl_2.0.12 [78] requires:
...
service; com.liferay.saml.runtime.profile.WebSsoProfile, com.liferay.saml.runtime.servlet.profile.WebSsoProfile provided by:
de.haufe.leong.com.liferay.saml.opensaml.integration [79]
...
But listing the actual services from within these bundles that use the given interface (or the service component) has eluded me so far.
The only solution I see so far is listing all provided services of these bundles via scr:list bid and then check each service with scr:info componentId to see if it uses the WebSsoProfile service.
Do you guys know a faster way to find the services using the WebSsoProfile-service?
[EDIT]: We solved the problem without having to provide config overrides for all consumers of the WebSsoProfile service but rather ensure that our implementation is used by deactivating the default service on Server startup. You can see the approach described here.
Anyways for debugging purposes this kind of lookup would be very useful.
So if anyone knows a way to retrieve the list of all consumers of an interface then please post your solution!
The standard solution is using the inspect command. It has a special namespace for services. Since a service registration is a capability, you can use inspect capability service:
g! inspect c service
org.apache.felix.framework [0] provides:
----------------------------------------
service; org.osgi.service.resolver.Resolver with properties:
service.bundleid = 0
service.id = 1
service.scope = singleton
service; org.osgi.service.packageadmin.PackageAdmin with properties:
service.bundleid = 0
service.id = 2
service.scope = singleton
service; org.osgi.service.startlevel.StartLevel with properties:
service.bundleid = 0
service.id = 3
service.scope = singleton
....
However, I find this command seriously useless. The command is inflexible and has a horrible output.
However, Gogo is way more powerful than people know. For one, you can use all the methods on the bundle context.
g! servicereferences org.osgi.service.startlevel.StartLevel null
000003 0 StartLevel
If you want to see the properties of each service:
g! each (servicereferences org.osgi.service.startlevel.StartLevel null) { $it properties }
[service.id=3, objectClass=[Ljava.lang.String;#4acd14d7, service.scope=singleton, service.bundleid=0]
You can make this into a built-in function:
g! srv = { servicereferences $1 null }
servicereferences $1 null
g! srv org.osgi.service.startlevel.StartLevel
000003 0 StartLevel
Unfortunately, the OSGi added an overloaded method in the Bundle Context for getServiceReferences() that throws an NPE when called with null. Gogo is awful with overloaded methods :-(
However, it is trivial to add your own command with a declarative service component. You could use the following:
#GogoCommand(scope="service", function="srv")
#Component(service=ServiceCommand.class)
public class ServiceCommand {
#Activate
BundleContext context;
#Descriptor("List all services")
public ServiceReference<?>[] srv() throws InvalidSyntaxException {
return context.getAllServiceReferences(null, null);
}
#Descriptor("List all services that match the name")
public ServiceReference<?>[] srv(
String... names)
throws InvalidSyntaxException {
ServiceReference<?>[] allServiceReferences =
context.getAllServiceReferences(null,null);
if ( allServiceReferences==null)
return new ServiceReference[0];
return Stream.of(allServiceReferences)
.filter(r -> {
String[] objectClass = (String[]) r.getProperty(Constants.OBJECTCLASS);
for (String oc : objectClass) {
for (String name : names)
if (oc.contains(name))
return true;
}
return names.length == 0;
}).sorted().toArray(ServiceReference[]::new);
}
}
This adds the srv command to Gogo:
g! srv Help Basic
000004 1 Basic
000005 1 Inspect
Update If you want to find which bundles are using a specific service, you could use:
g! each (srv X) { $it usingbundles }
Make sure you got the following dependencies on your classpath:
-buildpath: \
org.osgi.service.component.annotations,\
org.apache.felix.gogo.runtime, \
org.osgi.framework

Overwrite Databricks Dependency

In our project we're using com.typesafe:config in version 1.3.4. According to the latest release notes, this dependency is already provided by Databricks on the cluster, but in a very old version (1.2.1).
How can I overwrite the provided dependency with our own version?
We use maven, in our dependencies I have
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
<version>1.3.4</version>
</dependency>
Our created jar file should therefore contain the newer version.
I created a Job by uploading the jar file. The Job fails because it can't find a method that was added after version 1.2.1, so it looks like the library we provided gets overwritten by the older version on the cluster.
In the end we have fixed this by shading the relevant classes, by adding the following to our build.sbt
assemblyShadeRules in assembly := Seq(
ShadeRule.rename("com.typesafe.config.**" -> "shadedSparkConfigForSpark.#1").inAll
)
We solved it in the end by utilizing Sparks ChildFirstURLClassLoader. The project is open source so you can check it out yourself here and the usage of the method here.
But for reference, here is the method in its entirety. You need to provide a Seq of jars that you want to override with your own, in our case it's the typesafe config.
def getChildFirstClassLoader(jars: Seq[String]): ChildFirstURLClassLoader = {
val initialLoader = getClass.getClassLoader.asInstanceOf[URLClassLoader]
#tailrec
def collectUrls(clazz: ClassLoader, acc: Map[String, URL]): Map[String, URL] = {
val urlsAcc: Map[String, URL] = acc++
// add urls on this level to accumulator
clazz.asInstanceOf[URLClassLoader].getURLs
.map( url => (url.getFile.split(Environment.defaultPathSeparator).last, url))
.filter{ case (name, url) => jars.contains(name)}
.toMap
// check if any jars without URL are left
val jarMissing = jars.exists(jar => urlsAcc.get(jar).isEmpty)
// return accumulated if there is no parent left or no jars are missing anymore
if (clazz.getParent == null || !jarMissing) urlsAcc else collectUrls(clazz.getParent, urlsAcc)
}
// search classpath hierarchy until all jars are found or we have reached the top
val urlsMap = collectUrls(initialLoader, Map())
// check if everything found
val jarsNotFound = jars.filter( jar => urlsMap.get(jar).isEmpty)
if (jarsNotFound.nonEmpty) {
logger.info(s"""available jars are ${initialLoader.getURLs.mkString(", ")} (not including parent classpaths)""")
throw ConfigurationException(s"""jars ${jarsNotFound.mkString(", ")} not found in parent class loaders classpath. Cannot initialize ChildFirstURLClassLoader.""")
}
// create child-first classloader
new ChildFirstURLClassLoader(urlsMap.values.toArray, initialLoader)
}
As you can see, it also has some logic to abort if the jar files you specified do not exist in the classpath.
Databricks supports the initialization script (cluster scope or global scope) so that you can install/remove any dependency. The details are at https://docs.databricks.com/clusters/init-scripts.html.
In your initialization script, you can remove the default jar file locates at databricks driver/executor classpath /databricks/jars/ and add the expected one there.

Fali to use getAppliedStereotype to get id and name of requirement

In Eclipse, Using Papyrus neon and Acceleo 3.7 for SysML 1.4 diagram, the getAppliedStereotype()returns null.
The modules are
[module generate('http://www.eclipse.org/uml2/5.0.0/UML',
'http://www.eclipse.org/papyrus/sysml/1.4/SysML',
'http://www.eclipse.org/papyrus/sysml/1.4/SysML/Blocks',
'http://www.eclipse.org/papyrus/sysml/1.4/SysML/Activities',
'http://www.eclipse.org/papyrus/sysml/1.4/SysML/Requirements',
'http://www.eclipse.org/papyrus/sysml/1.4/SysML/ModelElements')]
I have added the following code in the generate.java but still cannot work
Map<URI, URI> uriMap = resourceSet.getURIConverter().getURIMap();
// UML2 profiles
URI uri = URI.createURI("platform:/plugin/org.eclipse.uml2.uml.resources");
uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri.appendSegment("libraries").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri.appendSegment("metamodels").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri.appendSegment("profiles").appendSegment(""));
// SysML profiles
uri = URI.createURI("platform:/plugin/org.eclipse.papyrus.sysml14");
uriMap.put(URI.createURI(SysMLResource.LIBRARIES_PATHMAP), uri.appendSegment("librairies").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML14_PROFILES/"), uri.appendSegment("model").appendSegment(""));
The code like c.getAppliedStereotypes() returns null. I want to get the information of a requirement like the following code which returns nothing because of the getAppliedStereotype operation:
[for (re : uml::Class | uml::Class.allInstances()->select(cl : uml::Class | cl.getAppliedStereotype('SysML::Requirements::Requirement') <> null))]
--[re.name/]
Modellpfad : [re.qualifiedName/]
Id : [re.getValue(re.getAppliedStereotype('SysML::Requirements::Requirement'), 'id')/]
Text : [re.getValue(re.getAppliedStereotype('SysML::Requirements::Requirement'), 'text')/]
[/for]
Well, if none of your model elements have an applied stereotype, you will find no classes or objects. Thus, when you try to print the applied stereotype of all elements with an applied stereotype without first ensuring that the list is itself not null, you will fail.

Resources