]> git.argeo.org Git - lgpl/argeo-commons.git/blob - a2/ProvisioningManager.java
Prepare next development cycle
[lgpl/argeo-commons.git] / a2 / ProvisioningManager.java
1 package org.argeo.osgi.boot.a2;
2
3 import java.io.File;
4 import java.io.InputStream;
5 import java.net.URI;
6 import java.nio.file.Path;
7 import java.nio.file.Paths;
8 import java.util.ArrayList;
9 import java.util.Collection;
10 import java.util.Collections;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
17 import org.argeo.osgi.boot.OsgiBootException;
18 import org.argeo.osgi.boot.OsgiBootUtils;
19 import org.eclipse.osgi.launch.EquinoxFactory;
20 import org.osgi.framework.Bundle;
21 import org.osgi.framework.BundleContext;
22 import org.osgi.framework.BundleException;
23 import org.osgi.framework.Constants;
24 import org.osgi.framework.Version;
25 import org.osgi.framework.launch.Framework;
26 import org.osgi.framework.launch.FrameworkFactory;
27 import org.osgi.framework.wiring.FrameworkWiring;
28
29 public class ProvisioningManager {
30 BundleContext bc;
31 OsgiContext osgiContext;
32 List<ProvisioningSource> sources = Collections.synchronizedList(new ArrayList<>());
33
34 public ProvisioningManager(BundleContext bc) {
35 this.bc = bc;
36 osgiContext = new OsgiContext(bc);
37 osgiContext.load();
38 }
39
40 void addSource(ProvisioningSource context) {
41 sources.add(context);
42 }
43
44 void installWholeSource(ProvisioningSource context) {
45 Set<Bundle> updatedBundles = new HashSet<>();
46 for (A2Contribution contribution : context.contributions.values()) {
47 for (A2Component component : contribution.components.values()) {
48 A2Module module = component.last().last();
49 Bundle bundle = installOrUpdate(module);
50 if (bundle != null)
51 updatedBundles.add(bundle);
52 }
53 }
54 FrameworkWiring frameworkWiring = bc.getBundle(0).adapt(FrameworkWiring.class);
55 frameworkWiring.refreshBundles(updatedBundles);
56 }
57
58 public void registerSource(String uri) {
59 try {
60 URI u = new URI(uri);
61 if ("a2".equals(u.getScheme())) {
62 if (u.getHost() == null || "".equals(u.getHost())) {
63 String baseStr = u.getPath();
64 if (File.separatorChar == '\\') {// MS Windows
65 baseStr = baseStr.substring(1).replace('/', File.separatorChar);
66 }
67 Path base = Paths.get(baseStr);
68 FsA2Source source = new FsA2Source(base);
69 source.load();
70 addSource(source);
71 }
72 }
73 } catch (Exception e) {
74 throw new OsgiBootException("Cannot add source " + uri, e);
75 }
76 }
77
78 public boolean registerDefaultSource() {
79 String frameworkLocation = bc.getProperty("osgi.framework");
80 try {
81 URI frameworkLocationUri = new URI(frameworkLocation);
82 if ("file".equals(frameworkLocationUri.getScheme())) {
83 Path frameworkPath = Paths.get(frameworkLocationUri);
84 if (frameworkPath.getParent().getFileName().toString().equals(A2Contribution.BOOT)) {
85 Path base = frameworkPath.getParent().getParent();
86 String baseStr = base.toString();
87 if (File.separatorChar == '\\')// MS Windows
88 baseStr = '/' + baseStr.replace(File.separatorChar, '/');
89 URI baseUri = new URI("a2", null, null, 0, baseStr, null, null);
90 registerSource(baseUri.toString());
91 OsgiBootUtils.info("Registered " + baseUri + " as default source");
92 return true;
93 }
94 }
95 } catch (Exception e) {
96 OsgiBootUtils.error("Cannot register default source based on framework location " + frameworkLocation, e);
97 }
98 return false;
99 }
100
101 public void install(String spec) {
102 if (spec == null) {
103 for (ProvisioningSource source : sources) {
104 installWholeSource(source);
105 }
106 }
107 }
108
109 /** @return the new/updated bundle, or null if nothign was done. */
110 Bundle installOrUpdate(A2Module module) {
111 try {
112 ProvisioningSource moduleSource = module.getBranch().getComponent().getContribution().getSource();
113 Version moduleVersion = module.getVersion();
114 A2Branch osgiBranch = osgiContext.findBranch(module.getBranch().getComponent().getId(), moduleVersion);
115 if (osgiBranch == null) {
116 Bundle bundle = bc.installBundle(module.getBranch().getCoordinates(),
117 moduleSource.newInputStream(module.getLocator()));
118 if (OsgiBootUtils.isDebug())
119 OsgiBootUtils.debug("Installed bundle " + bundle.getLocation() + " with version " + moduleVersion);
120 return bundle;
121 } else {
122 A2Module lastOsgiModule = osgiBranch.last();
123 int compare = moduleVersion.compareTo(lastOsgiModule.getVersion());
124 if (compare > 0) {// update
125 Bundle bundle = (Bundle) lastOsgiModule.getLocator();
126 bundle.update(moduleSource.newInputStream(module.getLocator()));
127 OsgiBootUtils.info("Updated bundle " + bundle.getLocation() + " to version " + moduleVersion);
128 return bundle;
129 }
130 }
131 } catch (Exception e) {
132 OsgiBootUtils.error("Could not install module " + module + ": " + e.getMessage(), null);
133 }
134 return null;
135 }
136
137 public Collection<Bundle> update() {
138 boolean fragmentsUpdated = false;
139 Set<Bundle> updatedBundles = new HashSet<>();
140 bundles: for (Bundle bundle : bc.getBundles()) {
141 for (ProvisioningSource source : sources) {
142 String componentId = bundle.getSymbolicName();
143 Version version = bundle.getVersion();
144 A2Branch branch = source.findBranch(componentId, version);
145 if (branch == null)
146 continue bundles;
147 A2Module module = branch.last();
148 Version moduleVersion = module.getVersion();
149 int compare = moduleVersion.compareTo(version);
150 if (compare > 0) {// update
151 try (InputStream in = source.newInputStream(module.getLocator())) {
152 bundle.update(in);
153 String fragmentHost = bundle.getHeaders().get(Constants.FRAGMENT_HOST);
154 if (fragmentHost != null)
155 fragmentsUpdated = true;
156 OsgiBootUtils.info("Updated bundle " + bundle.getLocation() + " to version " + moduleVersion);
157 updatedBundles.add(bundle);
158 } catch (Exception e) {
159 OsgiBootUtils.error("Cannot update with module " + module, e);
160 }
161 }
162 }
163 }
164 FrameworkWiring frameworkWiring = bc.getBundle(0).adapt(FrameworkWiring.class);
165 if (fragmentsUpdated)// refresh all
166 frameworkWiring.refreshBundles(null);
167 else
168 frameworkWiring.refreshBundles(updatedBundles);
169 return updatedBundles;
170 }
171
172 private static Framework launch() {
173 // start OSGi
174 FrameworkFactory frameworkFactory = new EquinoxFactory();
175 Map<String, String> configuration = new HashMap<>();
176 configuration.put("osgi.console", "2323");
177 Framework framework = frameworkFactory.newFramework(configuration);
178 try {
179 framework.start();
180 } catch (BundleException e) {
181 throw new OsgiBootException("Cannot start OSGi framework", e);
182 }
183 return framework;
184 }
185
186 public static void main(String[] args) {
187 Framework framework = launch();
188 try {
189 ProvisioningManager pm = new ProvisioningManager(framework.getBundleContext());
190 FsA2Source context = new FsA2Source(Paths.get(
191 "/home/mbaudier/dev/git/apache2/argeo-commons/dist/argeo-node/target/argeo-node-2.1.74-SNAPSHOT/argeo-node/share/osgi"));
192 context.load();
193 if (framework.getBundleContext().getBundles().length == 1) {// initial
194 pm.install(null);
195 } else {
196 pm.update();
197 }
198 } catch (Exception e) {
199 e.printStackTrace();
200 } finally {
201 try {
202 // framework.stop();
203 } catch (Exception e) {
204 e.printStackTrace();
205 }
206 }
207 }
208
209 }