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