1 package org
.argeo
.init
.a2
;
4 import java
.io
.UnsupportedEncodingException
;
6 import java
.net
.URLDecoder
;
7 import java
.nio
.charset
.StandardCharsets
;
8 import java
.nio
.file
.Files
;
9 import java
.nio
.file
.Path
;
10 import java
.nio
.file
.Paths
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Arrays
;
13 import java
.util
.Collection
;
14 import java
.util
.Collections
;
15 import java
.util
.HashMap
;
16 import java
.util
.HashSet
;
17 import java
.util
.LinkedHashMap
;
18 import java
.util
.LinkedList
;
19 import java
.util
.List
;
23 import org
.argeo
.init
.osgi
.OsgiBootUtils
;
24 import org
.osgi
.framework
.Bundle
;
25 import org
.osgi
.framework
.BundleContext
;
26 import org
.osgi
.framework
.Constants
;
27 import org
.osgi
.framework
.Version
;
28 import org
.osgi
.framework
.launch
.Framework
;
29 import org
.osgi
.framework
.wiring
.FrameworkWiring
;
31 /** Loads provisioning sources into an OSGi context. */
32 public class ProvisioningManager
{
34 OsgiContext osgiContext
;
35 List
<ProvisioningSource
> sources
= Collections
.synchronizedList(new ArrayList
<>());
37 public ProvisioningManager(BundleContext bc
) {
39 osgiContext
= new OsgiContext(bc
);
43 protected void addSource(ProvisioningSource source
) {
47 void installWholeSource(ProvisioningSource source
) {
48 Set
<Bundle
> updatedBundles
= new HashSet
<>();
49 for (A2Contribution contribution
: source
.listContributions(null)) {
50 for (A2Component component
: contribution
.components
.values()) {
51 A2Module module
= component
.last().last();
52 Bundle bundle
= installOrUpdate(module
);
54 updatedBundles
.add(bundle
);
57 FrameworkWiring frameworkWiring
= bc
.getBundle(0).adapt(FrameworkWiring
.class);
58 frameworkWiring
.refreshBundles(updatedBundles
);
61 public void registerSource(String uri
) {
66 Map
<String
, List
<String
>> properties
= queryToMap(u
);
67 Map
<String
, String
> xOr
= new HashMap
<>();
68 for (String key
: properties
.keySet()) {
69 List
<String
> lst
= properties
.get(key
);
71 throw new IllegalArgumentException("Invalid XOR definitions in " + uri
);
72 xOr
.put(key
, lst
.get(0));
75 if (A2Source
.SCHEME_A2
.equals(u
.getScheme())) {
76 if (u
.getHost() == null || "".equals(u
.getHost())) {
77 String baseStr
= u
.getPath();
78 if (File
.separatorChar
== '\\') {// MS Windows
79 baseStr
= baseStr
.substring(1).replace('/', File
.separatorChar
);
81 Path base
= Paths
.get(baseStr
);
82 if (Files
.exists(base
)) {
83 FsA2Source source
= new FsA2Source(base
, xOr
);
86 OsgiBootUtils
.info("Registered " + uri
+ " as source");
90 } catch (Exception e
) {
91 throw new A2Exception("Cannot add source " + uri
, e
);
95 public boolean registerDefaultSource() {
96 String frameworkLocation
= bc
.getProperty("osgi.framework");
98 URI frameworkLocationUri
= new URI(frameworkLocation
);
99 if ("file".equals(frameworkLocationUri
.getScheme())) {
100 Path frameworkPath
= Paths
.get(frameworkLocationUri
);
101 if (frameworkPath
.getParent().getFileName().toString().equals(A2Contribution
.BOOT
)) {
102 Path base
= frameworkPath
.getParent().getParent();
103 String baseStr
= base
.toString();
104 if (File
.separatorChar
== '\\')// MS Windows
105 baseStr
= '/' + baseStr
.replace(File
.separatorChar
, '/');
106 URI baseUri
= new URI(A2Source
.SCHEME_A2
, null, null, 0, baseStr
, null, null);
107 registerSource(baseUri
.toString());
108 OsgiBootUtils
.debug("Default source from framework location " + frameworkLocation
);
112 } catch (Exception e
) {
113 OsgiBootUtils
.error("Cannot register default source based on framework location " + frameworkLocation
, e
);
118 public void install(String spec
) {
120 for (ProvisioningSource source
: sources
) {
121 installWholeSource(source
);
126 /** @return the new/updated bundle, or null if nothing was done. */
127 protected Bundle
installOrUpdate(A2Module module
) {
129 ProvisioningSource moduleSource
= module
.getBranch().getComponent().getContribution().getSource();
130 Version moduleVersion
= module
.getVersion();
131 A2Branch osgiBranch
= osgiContext
.findBranch(module
.getBranch().getComponent().getId(), moduleVersion
);
132 if (osgiBranch
== null) {
133 // Bundle bundle = bc.installBundle(module.getBranch().getCoordinates(),
134 // moduleSource.newInputStream(module.getLocator()));
135 Bundle bundle
= moduleSource
.install(bc
, module
);
136 if (OsgiBootUtils
.isDebug())
137 OsgiBootUtils
.debug("Installed bundle " + bundle
.getLocation() + " with version " + moduleVersion
);
140 A2Module lastOsgiModule
= osgiBranch
.last();
141 int compare
= moduleVersion
.compareTo(lastOsgiModule
.getVersion());
142 if (compare
> 0) {// update
143 Bundle bundle
= (Bundle
) lastOsgiModule
.getLocator();
144 // bundle.update(moduleSource.newInputStream(module.getLocator()));
145 moduleSource
.update(bundle
, module
);
146 OsgiBootUtils
.info("Updated bundle " + bundle
.getLocation() + " to version " + moduleVersion
);
150 } catch (Exception e
) {
151 OsgiBootUtils
.error("Could not install module " + module
+ ": " + e
.getMessage(), e
);
156 public Collection
<Bundle
> update() {
157 boolean fragmentsUpdated
= false;
158 Set
<Bundle
> updatedBundles
= new HashSet
<>();
159 bundles
: for (Bundle bundle
: bc
.getBundles()) {
160 for (ProvisioningSource source
: sources
) {
161 String componentId
= bundle
.getSymbolicName();
162 Version version
= bundle
.getVersion();
163 A2Branch branch
= source
.findBranch(componentId
, version
);
166 A2Module module
= branch
.last();
167 Version moduleVersion
= module
.getVersion();
168 int compare
= moduleVersion
.compareTo(version
);
169 if (compare
> 0) {// update
171 source
.update(bundle
, module
);
172 // bundle.update(in);
173 String fragmentHost
= bundle
.getHeaders().get(Constants
.FRAGMENT_HOST
);
174 if (fragmentHost
!= null)
175 fragmentsUpdated
= true;
176 OsgiBootUtils
.info("Updated bundle " + bundle
.getLocation() + " to version " + moduleVersion
);
177 updatedBundles
.add(bundle
);
178 } catch (Exception e
) {
179 OsgiBootUtils
.error("Cannot update with module " + module
, e
);
184 FrameworkWiring frameworkWiring
= bc
.getBundle(0).adapt(FrameworkWiring
.class);
185 if (fragmentsUpdated
)// refresh all
186 frameworkWiring
.refreshBundles(null);
188 frameworkWiring
.refreshBundles(updatedBundles
);
189 return updatedBundles
;
192 private static Map
<String
, List
<String
>> queryToMap(URI uri
) {
193 return queryToMap(uri
.getQuery());
196 private static Map
<String
, List
<String
>> queryToMap(String queryPart
) {
198 final Map
<String
, List
<String
>> query_pairs
= new LinkedHashMap
<String
, List
<String
>>();
199 if (queryPart
== null)
201 final String
[] pairs
= queryPart
.split("&");
202 for (String pair
: pairs
) {
203 final int idx
= pair
.indexOf("=");
204 final String key
= idx
> 0 ? URLDecoder
.decode(pair
.substring(0, idx
), StandardCharsets
.UTF_8
.name())
206 if (!query_pairs
.containsKey(key
)) {
207 query_pairs
.put(key
, new LinkedList
<String
>());
209 final String value
= idx
> 0 && pair
.length() > idx
+ 1
210 ? URLDecoder
.decode(pair
.substring(idx
+ 1), StandardCharsets
.UTF_8
.name())
212 query_pairs
.get(key
).add(value
);
215 } catch (UnsupportedEncodingException e
) {
216 throw new IllegalArgumentException("Cannot convert " + queryPart
+ " to map", e
);
220 public static void main(String
[] args
) {
221 if (args
.length
== 0)
222 throw new IllegalArgumentException("Usage: <path to A2 base>");
223 Map
<String
, String
> configuration
= new HashMap
<>();
224 configuration
.put("osgi.console", "2323");
225 configuration
.put("org.osgi.framework.bootdelegation",
226 "com.sun.jndi.ldap,com.sun.jndi.ldap.sasl,com.sun.security.jgss,com.sun.jndi.dns,com.sun.nio.file,com.sun.nio.sctp,sun.nio.cs");
227 Framework framework
= OsgiBootUtils
.launch(configuration
);
229 ProvisioningManager pm
= new ProvisioningManager(framework
.getBundleContext());
230 Map
<String
, String
> xOr
= new HashMap
<>();
231 xOr
.put("osgi", "equinox");
232 xOr
.put("swt", "rap");
233 FsA2Source context
= new FsA2Source(Paths
.get(args
[0]), xOr
);
235 pm
.addSource(context
);
236 if (framework
.getBundleContext().getBundles().length
== 1) {// initial
244 Bundle
[] bundles
= framework
.getBundleContext().getBundles();
245 Arrays
.sort(bundles
, (b1
, b2
) -> b1
.getSymbolicName().compareTo(b2
.getSymbolicName()));
246 for (Bundle b
: bundles
)
247 if (b
.getState() == Bundle
.RESOLVED
|| b
.getState() == Bundle
.STARTING
|| b
.getState() == Bundle
.ACTIVE
)
248 System
.out
.println(b
.getSymbolicName() + " " + b
.getVersion());
250 System
.err
.println(b
.getSymbolicName() + " " + b
.getVersion() + " (" + b
.getState() + ")");
251 } catch (Exception e
) {
256 } catch (Exception e
) {