]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/BundleModularDistribution.java
79bc3e6a87929a68f9feef2ebc8672ab5a453463
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.osgi / src / main / java / org / argeo / slc / osgi / build / BundleModularDistribution.java
1 package org.argeo.slc.osgi.build;
2
3 import java.net.URL;
4 import java.util.ArrayList;
5 import java.util.Enumeration;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9 import java.util.SortedMap;
10 import java.util.StringTokenizer;
11 import java.util.TreeMap;
12 import java.util.jar.JarInputStream;
13 import java.util.jar.Manifest;
14
15 import org.apache.commons.io.IOUtils;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.slc.SlcException;
19 import org.argeo.slc.UnsupportedException;
20 import org.argeo.slc.build.BasicNameVersion;
21 import org.argeo.slc.build.Distribution;
22 import org.argeo.slc.build.ModularDistribution;
23 import org.argeo.slc.build.NameVersion;
24 import org.argeo.slc.core.build.VersionedResourceDistribution;
25 import org.osgi.framework.BundleContext;
26 import org.osgi.framework.Constants;
27 import org.springframework.beans.factory.InitializingBean;
28 import org.springframework.context.ResourceLoaderAware;
29 import org.springframework.core.io.ResourceLoader;
30 import org.springframework.osgi.context.BundleContextAware;
31
32 public class BundleModularDistribution implements ModularDistribution,
33 BundleContextAware, InitializingBean, ResourceLoaderAware {
34 private final static Log log = LogFactory
35 .getLog(BundleModularDistribution.class);
36
37 private BundleContext bundleContext;
38 private ResourceLoader resourceLoader;
39
40 private String libDirectory = "/lib";
41 private EclipseUpdateSite eclipseUpdateSite;
42
43 /** Initialized by the object itself. */
44 private SortedMap<NameVersion, VersionedResourceDistribution> distributions = new TreeMap<NameVersion, VersionedResourceDistribution>();
45
46 public Distribution getModuleDistribution(String moduleName,
47 String moduleVersion) {
48 return distributions
49 .get(new BasicNameVersion(moduleName, moduleVersion));
50 // URL url = findModule(moduleName, moduleVersion);
51 // return new ResourceDistribution(new UrlResource(url));
52 }
53
54 @SuppressWarnings(value = { "unchecked" })
55 protected URL findModule(String moduleName, String version) {
56 Enumeration<URL> urls = (Enumeration<URL>) bundleContext.getBundle()
57 .findEntries(libDirectory, moduleName + "*", false);
58
59 if (!urls.hasMoreElements())
60 throw new SlcException("Cannot find module " + moduleName);
61
62 URL url = urls.nextElement();
63
64 // TODO: check version as well
65 if (urls.hasMoreElements())
66 throw new SlcException("More than one module with name "
67 + moduleName);
68 return url;
69 }
70
71 public String getDistributionId() {
72 return bundleContext.getBundle().getSymbolicName()
73 + "-"
74 + bundleContext.getBundle().getHeaders().get(
75 Constants.BUNDLE_VERSION);
76 }
77
78 public Set<NameVersion> listModulesNameVersions() {
79 return distributions.keySet();
80 }
81
82 public void setBundleContext(BundleContext bundleContext) {
83 this.bundleContext = bundleContext;
84 }
85
86 @SuppressWarnings(value = { "unchecked" })
87 public void afterPropertiesSet() throws Exception {
88 Enumeration<URL> urls = (Enumeration<URL>) bundleContext.getBundle()
89 .findEntries(libDirectory, "*.jar", false);
90 while (urls.hasMoreElements()) {
91 URL url = urls.nextElement();
92 JarInputStream in = null;
93 try {
94 in = new JarInputStream(url.openStream());
95 Manifest mf = in.getManifest();
96 String name = mf.getMainAttributes().getValue(
97 Constants.BUNDLE_SYMBOLICNAME);
98 // Skip additional specs such as
99 // ; singleton:=true
100 if (name.indexOf(';') > -1) {
101 name = new StringTokenizer(name, " ;").nextToken();
102 }
103
104 String version = mf.getMainAttributes().getValue(
105 Constants.BUNDLE_VERSION);
106 BasicNameVersion nameVersion = new BasicNameVersion(name,
107 version);
108 distributions.put(nameVersion,
109 new VersionedResourceDistribution(name, version,
110 resourceLoader.getResource(url.toString())));
111 } finally {
112 IOUtils.closeQuietly(in);
113 }
114 }
115 if (log.isDebugEnabled())
116 log.debug("Distribution " + getName() + ":" + getVersion()
117 + " loaded (" + distributions.size() + " modules)");
118
119 }
120
121 protected String findVersion(String name) {
122 Set<String> versions = new HashSet<String>();
123 for (NameVersion key : distributions.keySet()) {
124 if (key.getName().equals(name))
125 versions.add(key.getVersion());
126 }
127
128 if (versions.size() == 0)
129 throw new SlcException("Cannot find version for name " + name);
130 else if (versions.size() > 1)
131 throw new SlcException("Found more than one version for name "
132 + name + ": " + versions);
133 else
134 return versions.iterator().next();
135
136 }
137
138 public void setLibDirectory(String libDirectory) {
139 this.libDirectory = libDirectory;
140 }
141
142 public Object getDescriptor(String descriptorType) {
143 if (descriptorType.equals("eclipse"))
144 return writeEclipseUpdateSite();
145 else
146 throw new UnsupportedException("descriptorType", descriptorType);
147 }
148
149 protected Set<NameVersion> writePlainUrlList() {
150 return distributions.keySet();
151 }
152
153 protected String writeEclipseUpdateSite() {
154 if (eclipseUpdateSite == null)
155 throw new SlcException("No eclipse update site declared.");
156
157 StringBuffer buf = new StringBuffer("");
158 buf.append("<site>");
159
160 List<EclipseUpdateSiteCategory> usedCategories = new ArrayList<EclipseUpdateSiteCategory>();
161 for (EclipseUpdateSiteFeature feature : eclipseUpdateSite.getFeatures()) {
162
163 String featureId = feature.getName();
164 String featureVersion = findVersion(featureId);
165 buf.append("<feature");
166 buf.append(" url=\"features/").append(featureId).append('_')
167 .append(featureVersion).append(".jar\"");
168 buf.append(" id=\"").append(featureId).append("\"");
169 buf.append(" version=\"").append(featureVersion).append("\"");
170 buf.append(">\n");
171
172 for (EclipseUpdateSiteCategory category : feature.getCategories()) {
173 usedCategories.add(category);
174 buf.append(" <category name=\"").append(category.getName())
175 .append("\"/>\n");
176 }
177 buf.append("</feature>\n\n");
178 }
179
180 for (EclipseUpdateSiteCategory category : usedCategories) {
181 buf.append("<category-def");
182 buf.append(" name=\"").append(category.getName()).append("\"");
183 buf.append(" label=\"").append(category.getLabel()).append("\"");
184 buf.append(">\n");
185 buf.append(" <description>").append(category.getDescription())
186 .append("</description>\n");
187 buf.append("</category-def>\n\n");
188 }
189
190 buf.append("</site>");
191 return buf.toString();
192 }
193
194 public void setResourceLoader(ResourceLoader resourceLoader) {
195 this.resourceLoader = resourceLoader;
196 }
197
198 public String getName() {
199 return bundleContext.getBundle().getSymbolicName();
200 }
201
202 public String getVersion() {
203 return bundleContext.getBundle().getHeaders().get(
204 Constants.BUNDLE_VERSION).toString();
205 }
206
207 @Override
208 public String toString() {
209 return new BasicNameVersion(this).toString();
210 }
211
212 public void setEclipseUpdateSite(EclipseUpdateSite eclipseUpdateSite) {
213 this.eclipseUpdateSite = eclipseUpdateSite;
214 }
215
216 }