From b98bef7b2e743103c93e719ac5c18bf41858ec3a Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 28 Jun 2009 23:58:05 +0000 Subject: [PATCH] Provisioning git-svn-id: https://svn.argeo.org/slc/trunk@2616 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- demo/pom.xml | 4 +- dep/org.argeo.slc.dep.agent/pom.xml | 4 + modules/server/.classpath | 6 + modules/server/.project | 23 ++ .../.settings/org.eclipse.jdt.core.prefs | 5 + .../.settings/org.maven.ide.eclipse.prefs | 9 + .../org.argeo.slc.webapp.war/WEB-INF/osgi.xml | 3 + .../WEB-INF/provisioning-servlet.xml | 94 ++++++++ .../org.argeo.slc.webapp.war/WEB-INF/web.xml | 15 ++ modules/server/pom.xml | 11 +- pom.xml | 2 +- .../slc/core/build/ResourceDistribution.java | 15 +- .../build/VersionedResourceDistribution.java | 38 +++ .../org/argeo/slc/osgiboot/Activator.java | 1 + .../java/org/argeo/slc/osgiboot/OsgiBoot.java | 176 +++++++++++++- .../AbstractAvailableModules.java | 36 +++ .../AbstractProvisioningInterceptor.java | 8 + .../provisioning/AvailableDistributions.java | 62 +++++ .../provisioning/AvailableModulesHtml.java | 31 +++ .../AvailableModulesOsgiBoot.java | 30 +++ .../provisioning/AvailableModulesPlain.java | 22 ++ .../web/mvc/provisioning/BundleHandler.java | 46 ++++ .../provisioning/BundleJarInterceptor.java | 42 ++++ .../EclipseUpdateSiteHandler.java | 71 +----- .../EclipseUpdateSiteInterceptor.java | 51 +++++ .../web/mvc/provisioning/FileProvider.java | 63 ----- .../ModularDistributionInterceptor.java | 67 ++++++ .../web/mvc/provisioning/PluginHandler.java | 61 ----- .../java/org/argeo/slc/StreamReadable.java | 7 + .../org/argeo/slc/build/BasicNameVersion.java | 63 +++++ .../argeo/slc/build/ModularDistribution.java | 12 + .../java/org/argeo/slc/build/NameVersion.java | 7 + .../org/argeo/slc/deploy/DeployedSystem.java | 2 +- .../java/org/argeo/slc/deploy/Module.java | 7 +- .../java/org/argeo/slc/osgi/OsgiBundle.java | 8 +- .../java/org/argeo/slc/osgi/OsgiRuntime.java | 7 +- .../osgi/build/BundleModularDistribution.java | 216 ++++++++++++++++++ .../slc/osgi/build}/EclipseUpdateSite.java | 2 +- .../build}/EclipseUpdateSiteCategory.java | 2 +- .../osgi/build}/EclipseUpdateSiteFeature.java | 2 +- .../argeo/slc/unit/db/DbUnitDeployment.java | 2 +- 41 files changed, 1116 insertions(+), 217 deletions(-) create mode 100644 modules/server/.classpath create mode 100644 modules/server/.project create mode 100644 modules/server/.settings/org.eclipse.jdt.core.prefs create mode 100644 modules/server/.settings/org.maven.ide.eclipse.prefs create mode 100644 modules/server/org.argeo.slc.webapp.war/WEB-INF/provisioning-servlet.xml create mode 100644 runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractAvailableModules.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractProvisioningInterceptor.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableDistributions.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesHtml.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesOsgiBoot.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesPlain.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleHandler.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleJarInterceptor.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteInterceptor.java delete mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/FileProvider.java create mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/ModularDistributionInterceptor.java delete mode 100644 runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/PluginHandler.java create mode 100644 runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/StreamReadable.java create mode 100644 runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/BasicNameVersion.java create mode 100644 runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/ModularDistribution.java create mode 100644 runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/NameVersion.java create mode 100644 runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/BundleModularDistribution.java rename runtime/{org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning => org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build}/EclipseUpdateSite.java (89%) rename runtime/{org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning => org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build}/EclipseUpdateSiteCategory.java (91%) rename runtime/{org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning => org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build}/EclipseUpdateSiteFeature.java (92%) diff --git a/demo/pom.xml b/demo/pom.xml index 0fcdaaf85..71be268c1 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -103,7 +103,9 @@ org.argeo.slc.ria - ${basedir}/../modules/server;in=*;ex=pom.xml;ex=target + ${user.home}/dev/src/sparta/dist/runtime/target;in=*.jar, + ${basedir}/site;in=*;ex=pom.xml;ex=target, + ${basedir}/../modules/server;in=*;ex=pom.xml;ex=target;ex=.* diff --git a/dep/org.argeo.slc.dep.agent/pom.xml b/dep/org.argeo.slc.dep.agent/pom.xml index 65f6df5a9..31c229f48 100644 --- a/dep/org.argeo.slc.dep.agent/pom.xml +++ b/dep/org.argeo.slc.dep.agent/pom.xml @@ -32,5 +32,9 @@ org.argeo.slc.runtime org.argeo.slc.support.castor + + org.argeo.slc.runtime + org.argeo.slc.support.ant + \ No newline at end of file diff --git a/modules/server/.classpath b/modules/server/.classpath new file mode 100644 index 000000000..d0bec0f76 --- /dev/null +++ b/modules/server/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/modules/server/.project b/modules/server/.project new file mode 100644 index 000000000..c8893ab94 --- /dev/null +++ b/modules/server/.project @@ -0,0 +1,23 @@ + + + org.argeo.slc.modules.server + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.maven.ide.eclipse.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.maven.ide.eclipse.maven2Nature + + diff --git a/modules/server/.settings/org.eclipse.jdt.core.prefs b/modules/server/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..9bd01867d --- /dev/null +++ b/modules/server/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Sat Jun 27 18:22:37 CEST 2009 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/modules/server/.settings/org.maven.ide.eclipse.prefs b/modules/server/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 000000000..c4d229498 --- /dev/null +++ b/modules/server/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Sat Jun 27 18:22:31 CEST 2009 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 diff --git a/modules/server/org.argeo.slc.webapp.war/WEB-INF/osgi.xml b/modules/server/org.argeo.slc.webapp.war/WEB-INF/osgi.xml index a75bac77a..c79f6a6ea 100644 --- a/modules/server/org.argeo.slc.webapp.war/WEB-INF/osgi.xml +++ b/modules/server/org.argeo.slc.webapp.war/WEB-INF/osgi.xml @@ -43,5 +43,8 @@ + + \ No newline at end of file diff --git a/modules/server/org.argeo.slc.webapp.war/WEB-INF/provisioning-servlet.xml b/modules/server/org.argeo.slc.webapp.war/WEB-INF/provisioning-servlet.xml new file mode 100644 index 000000000..a0f4c6490 --- /dev/null +++ b/modules/server/org.argeo.slc.webapp.war/WEB-INF/provisioning-servlet.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + /*/*/modules.html=availableModulesHtml + /*/*/modules=availableModulesPlain + /*/*/osgiBoot=availableModulesOsgiBoot + /*/*/site.xml=updateSiteHandler + + + + + + + + + + + + + + /*/*/plugins/*=getBundleHandler + /*/*/features/*=getBundleHandler + + + + + + + + + + + + + + /*/*/*.jar=getBundleHandler + + + + + + + + + + + + /distributions=availableDistributions + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/server/org.argeo.slc.webapp.war/WEB-INF/web.xml b/modules/server/org.argeo.slc.webapp.war/WEB-INF/web.xml index 0e1ad8909..3e9d60b93 100644 --- a/modules/server/org.argeo.slc.webapp.war/WEB-INF/web.xml +++ b/modules/server/org.argeo.slc.webapp.war/WEB-INF/web.xml @@ -55,6 +55,21 @@ *.pdf + + + provisioning + org.springframework.web.servlet.DispatcherServlet + + contextClass + org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext + + 1 + + + provisioning + /dist/* + + contextConfigLocation diff --git a/modules/server/pom.xml b/modules/server/pom.xml index 534ae5376..90795a618 100644 --- a/modules/server/pom.xml +++ b/modules/server/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 org.argeo.slc @@ -23,4 +24,12 @@ + + + org.argeo.slc.dep + org.argeo.slc.dep.server + ${project.version} + test + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6a6346d2c..754fdfd6c 100644 --- a/pom.xml +++ b/pom.xml @@ -574,7 +574,7 @@ limitations under the License. org.argeo.dep.osgi org.argeo.dep.osgi.commons.cli - 1.1 + 1.1.0.argeo1 org.argeo.dep.osgi diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java index c24d6ec6c..633be7a7f 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/ResourceDistribution.java @@ -1,9 +1,14 @@ package org.argeo.slc.core.build; +import java.io.IOException; +import java.io.InputStream; + +import org.argeo.slc.SlcException; +import org.argeo.slc.StreamReadable; import org.argeo.slc.build.Distribution; import org.springframework.core.io.Resource; -public class ResourceDistribution implements Distribution { +public class ResourceDistribution implements Distribution, StreamReadable { private Resource location; public ResourceDistribution() { @@ -25,4 +30,12 @@ public class ResourceDistribution implements Distribution { this.location = location; } + public InputStream getInputStream() { + try { + return location.getInputStream(); + } catch (IOException e) { + throw new SlcException("Cannot get input stream", e); + } + } + } diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java new file mode 100644 index 000000000..a813438ba --- /dev/null +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/build/VersionedResourceDistribution.java @@ -0,0 +1,38 @@ +package org.argeo.slc.core.build; + +import org.argeo.slc.build.NameVersion; +import org.springframework.core.io.Resource; + +public class VersionedResourceDistribution extends ResourceDistribution + implements NameVersion { + private String name; + private String version; + + public VersionedResourceDistribution() { + super(); + } + + public VersionedResourceDistribution(String name, String version, + Resource resource) { + super(resource); + this.name = name; + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + +} diff --git a/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/Activator.java b/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/Activator.java index d3dc59ff6..0945ca719 100644 --- a/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/Activator.java +++ b/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/Activator.java @@ -11,6 +11,7 @@ public class Activator implements BundleActivator { OsgiBoot osgiBoot = new OsgiBoot(bundleContext); osgiBoot.installUrls(osgiBoot.getBundlesUrls()); osgiBoot.installUrls(osgiBoot.getLocationsUrls()); + osgiBoot.installUrls(osgiBoot.getModulesUrls()); osgiBoot.startBundles(); OsgiBoot.info("SLC OSGi bootstrap completed"); } catch (Exception e) { diff --git a/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java b/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java index 2c6d1434a..dd2b1b691 100644 --- a/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java +++ b/runtime/org.argeo.slc.osgiboot/src/main/java/org/argeo/slc/osgiboot/OsgiBoot.java @@ -1,9 +1,14 @@ package org.argeo.slc.osgiboot; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -14,12 +19,14 @@ import org.argeo.slc.osgiboot.internal.springutil.SystemPropertyUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; public class OsgiBoot { public final static String PROP_SLC_OSGI_START = "slc.osgi.start"; public final static String PROP_SLC_OSGI_BUNDLES = "slc.osgi.bundles"; public final static String PROP_SLC_OSGI_LOCATIONS = "slc.osgi.locations"; public final static String PROP_SLC_OSGI_BASE_URL = "slc.osgi.baseUrl"; + public final static String PROP_SLC_OSGI_MODULES_URL = "slc.osgi.modulesUrl"; public final static String PROP_SLC_OSGIBOOT_DEBUG = "slc.osgiboot.debug"; public final static String DEFAULT_BASE_URL = "reference:file:"; @@ -30,6 +37,7 @@ public class OsgiBoot { .booleanValue(); private boolean excludeSvn = true; + private String modulesUrlSeparator = ";"; private final BundleContext bundleContext; @@ -62,6 +70,45 @@ public class OsgiBoot { } + public void installOrUpdateUrls(Map urls) { + Map installedBundles = getBundles(); + + for (Iterator modules = urls.keySet().iterator(); modules.hasNext();) { + String moduleName = (String) modules.next(); + String urlStr = (String) urls.get(moduleName); + if (installedBundles.containsKey(moduleName)) { + Bundle bundle = (Bundle) installedBundles.get(moduleName); + InputStream in; + try { + URL url = new URL(urlStr); + in = url.openStream(); + bundle.update(in); + info("Updated bundle " + moduleName + " from " + urlStr); + } catch (Exception e) { + throw new RuntimeException("Cannot update " + moduleName + + " from " + urlStr); + } + if (in != null) + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } else { + try { + Bundle bundle = bundleContext.installBundle(urlStr); + if (debug) + debug("Installed bundle " + bundle.getSymbolicName() + + " from " + urlStr); + } catch (BundleException e) { + warn("Could not install bundle from " + urlStr + ": " + + e.getMessage()); + } + } + } + + } + public void startBundles() throws Exception { String bundlesToStart = getProperty(PROP_SLC_OSGI_START); startBundles(bundlesToStart); @@ -84,21 +131,24 @@ public class OsgiBoot { if (bundlesToStart.size() == 0) return; - Map bundles = getBundles(); - for (int i = 0; i < bundlesToStart.size(); i++) { - String name = bundlesToStart.get(i).toString(); - Bundle bundle = (Bundle) bundles.get(name); - if (bundle != null) + List notStartedBundles = new ArrayList(bundlesToStart); + Bundle[] bundles = bundleContext.getBundles(); + for (int i = 0; i < bundles.length; i++) { + Bundle bundle = bundles[i]; + String symbolicName = bundle.getSymbolicName(); + if (bundlesToStart.contains(symbolicName)) try { bundle.start(); + notStartedBundles.remove(symbolicName); } catch (Exception e) { - warn("Bundle " + name + " cannot be started: " + warn("Bundle " + symbolicName + " cannot be started: " + e.getMessage()); } - else - warn("Bundle " + name + " not installed."); - } + + for (int i = 0; i < notStartedBundles.size(); i++) + warn("Bundle " + notStartedBundles.get(i) + + " not started because it was not found."); } /** Key is location */ @@ -128,6 +178,114 @@ public class OsgiBoot { return getLocationsUrls(baseUrl, bundleLocations); } + public List getModulesUrls() { + List urls = new ArrayList(); + String modulesUrlStr = getProperty(PROP_SLC_OSGI_MODULES_URL); + if (modulesUrlStr == null) + return urls; + + Map installedBundles = getBundles(); + + BufferedReader reader = null; + try { + URL modulesUrl = new URL(modulesUrlStr); + reader = new BufferedReader(new InputStreamReader(modulesUrl + .openStream())); + String line = null; + while ((line = reader.readLine()) != null) { + StringTokenizer st = new StringTokenizer(line, + modulesUrlSeparator); + String moduleName = st.nextToken(); + String moduleVersion = st.nextToken(); + String url = st.nextToken(); + + if (installedBundles.containsKey(moduleName)) { + Bundle bundle = (Bundle) installedBundles.get(moduleName); + String bundleVersion = bundle.getHeaders().get( + Constants.BUNDLE_VERSION).toString(); + int comp = compareVersions(bundleVersion, moduleVersion); + if (comp > 0) { + warn("Installed version " + bundleVersion + + " of bundle " + moduleName + + " is newer than provided version " + + moduleVersion); + } else if (comp < 0) { + urls.add(url); + info("Updated bundle " + moduleName + " with version " + + moduleVersion + " (old version was " + + bundleVersion + ")"); + } else { + // do nothing + } + } else { + urls.add(url); + } + } + } catch (Exception e1) { + throw new RuntimeException("Cannot read url " + modulesUrlStr, e1); + } finally { + if (reader != null) + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return urls; + } + + /** + * @return ==0: versions are identical, <0: tested version is newer, >0: + * currentVersion is newer. + */ + protected int compareVersions(String currentVersion, String testedVersion) { + List cToks = new ArrayList(); + StringTokenizer cSt = new StringTokenizer(currentVersion, "."); + while (cSt.hasMoreTokens()) + cToks.add(cSt.nextToken()); + List tToks = new ArrayList(); + StringTokenizer tSt = new StringTokenizer(currentVersion, "."); + while (tSt.hasMoreTokens()) + tToks.add(tSt.nextToken()); + + int comp = 0; + comp: for (int i = 0; i < cToks.size(); i++) { + if (tToks.size() <= i) { + // equals until then, tested shorter + comp = 1; + break comp; + } + + String c = (String) cToks.get(i); + String t = (String) tToks.get(i); + + try { + int cInt = Integer.parseInt(c); + int tInt = Integer.parseInt(t); + if (cInt == tInt) + continue comp; + else { + comp = (cInt - tInt); + break comp; + } + } catch (NumberFormatException e) { + if (c.equals(t)) + continue comp; + else { + comp = c.compareTo(t); + break comp; + } + } + } + + if (comp == 0 && tToks.size() > cToks.size()) { + // equals until then, current shorter + comp = -1; + } + + return comp; + } + public List getLocationsUrls(String baseUrl, String bundleLocations) { List urls = new ArrayList(); diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractAvailableModules.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractAvailableModules.java new file mode 100644 index 000000000..e9acf08f2 --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractAvailableModules.java @@ -0,0 +1,36 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.slc.build.ModularDistribution; +import org.springframework.web.HttpRequestHandler; + +/** List of modules for a distribution. */ +public abstract class AbstractAvailableModules implements HttpRequestHandler { + protected abstract void print(Writer out, String baseUrl, + ModularDistribution md) throws IOException; + + public final void handleRequest(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType(getContentType()); + + ModularDistribution md = (ModularDistribution) request + .getAttribute("modularDistribution"); + + String baseUrl = "http://" + request.getServerName() + ":" + + request.getServerPort() + request.getContextPath() + "/" + + md.getName() + "/" + md.getVersion() + "/"; + + print(response.getWriter(), baseUrl, md); + } + + public String getContentType() { + return "text/plain"; + } + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractProvisioningInterceptor.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractProvisioningInterceptor.java new file mode 100644 index 000000000..613de2c3f --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AbstractProvisioningInterceptor.java @@ -0,0 +1,8 @@ +package org.argeo.slc.web.mvc.provisioning; + +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public abstract class AbstractProvisioningInterceptor extends + HandlerInterceptorAdapter { + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableDistributions.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableDistributions.java new file mode 100644 index 000000000..b4a2cc92b --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableDistributions.java @@ -0,0 +1,62 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.io.IOException; +import java.io.Writer; +import java.util.Iterator; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.slc.build.ModularDistribution; +import org.springframework.web.HttpRequestHandler; + +/** List of distributions. */ +public class AvailableDistributions implements HttpRequestHandler { + private Set modularDistributions; + + public void handleRequest(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/html"); + + String baseUrl = "http://" + request.getServerName() + ":" + + request.getServerPort() + request.getContextPath() + + request.getServletPath() + "/"; + + Writer out = response.getWriter(); + + out.write("

Distributions

"); + for (Iterator it = modularDistributions.iterator(); it + .hasNext();) { + ModularDistribution md = it.next(); + out.write("

" + md + "

"); + out.write("Modules: "); + String moduleBase = baseUrl + md.getName() + "/" + md.getVersion() + + "/"; + + String modulesListHtml = moduleBase + "modules.html"; + out.write(" html"); + + String modulesListPlain = moduleBase + "modules"; + out.write(" plain"); + + String modulesListOsgiBoot = moduleBase + "osgiBoot"; + out.write(" osgiBoot"); + + out.write("
"); + + out.write("Eclipse update site: "); + String updateSiteUrl = baseUrl + md.getName() + "/" + + md.getVersion() + "/site.xml"; + out.write("" + updateSiteUrl + + ""); + } + } + + public void setModularDistributions( + Set modularDistributions) { + this.modularDistributions = modularDistributions; + } + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesHtml.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesHtml.java new file mode 100644 index 000000000..338de8353 --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesHtml.java @@ -0,0 +1,31 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.io.IOException; +import java.io.Writer; + +import org.argeo.slc.build.ModularDistribution; +import org.argeo.slc.build.NameVersion; + +/** List of modules for a distribution. */ +public class AvailableModulesHtml extends AbstractAvailableModules { + @Override + protected void print(Writer out, String baseUrl, ModularDistribution md) + throws IOException { + out.write("

Distribution " + md + "

"); + + for (NameVersion nameVersion : md.listModulesNameVersions()) { + String fileName = nameVersion.getName() + "-" + + nameVersion.getVersion() + ".jar"; + String moduleUrl = baseUrl + fileName; + out + .write("" + fileName + + "
"); + } + } + + @Override + public String getContentType() { + return "text/html"; + } + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesOsgiBoot.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesOsgiBoot.java new file mode 100644 index 000000000..a31dae9cc --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesOsgiBoot.java @@ -0,0 +1,30 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.io.IOException; +import java.io.Writer; + +import org.argeo.slc.build.ModularDistribution; +import org.argeo.slc.build.NameVersion; + +/** List of modules for a distribution. */ +public class AvailableModulesOsgiBoot extends AbstractAvailableModules { + private String separator = ";"; + + @Override + protected void print(Writer out, String baseUrl, ModularDistribution md) + throws IOException { + for (NameVersion nameVersion : md.listModulesNameVersions()) { + String fileName = nameVersion.getName() + "-" + + nameVersion.getVersion() + ".jar"; + String moduleUrl = baseUrl + fileName; + out.write(nameVersion.getName() + separator + + nameVersion.getVersion() + separator + moduleUrl); + out.write("\n"); + } + } + + public void setSeparator(String separator) { + this.separator = separator; + } + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesPlain.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesPlain.java new file mode 100644 index 000000000..fb7c7c909 --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/AvailableModulesPlain.java @@ -0,0 +1,22 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.io.IOException; +import java.io.Writer; + +import org.argeo.slc.build.ModularDistribution; +import org.argeo.slc.build.NameVersion; + +/** List of modules for a distribution. */ +public class AvailableModulesPlain extends AbstractAvailableModules { + @Override + protected void print(Writer out, String baseUrl, ModularDistribution md) + throws IOException { + for (NameVersion nameVersion : md.listModulesNameVersions()) { + String fileName = nameVersion.getName() + "-" + + nameVersion.getVersion() + ".jar"; + String moduleUrl = baseUrl + fileName; + out.write(moduleUrl); + out.write("\n"); + } + } +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleHandler.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleHandler.java new file mode 100644 index 000000000..9936d88c4 --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleHandler.java @@ -0,0 +1,46 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.StreamReadable; +import org.argeo.slc.UnsupportedException; +import org.argeo.slc.build.Distribution; +import org.argeo.slc.build.ModularDistribution; +import org.springframework.web.HttpRequestHandler; + +public class BundleHandler implements HttpRequestHandler { + private final static Log log = LogFactory.getLog(BundleHandler.class); + + public void handleRequest(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + String path = request.getPathInfo(); + + if (log.isDebugEnabled()) + log.debug("Bundle jar Requested: " + path); + response.setContentType("application/java-archive"); + + String moduleName = request.getParameter("moduleName"); + if (moduleName == null) + moduleName = request.getAttribute("moduleName").toString(); + String moduleVersion = request.getParameter("moduleVersion"); + if (moduleVersion == null) + moduleVersion = request.getAttribute("moduleVersion").toString(); + + ModularDistribution modularDistribution = (ModularDistribution) request + .getAttribute("modularDistribution"); + Distribution distribution = modularDistribution.getModuleDistribution( + moduleName, moduleVersion); + if (distribution instanceof StreamReadable) + IOUtils.copy(((StreamReadable) distribution).getInputStream(), + response.getOutputStream()); + else + throw new UnsupportedException("distribution", distribution); + } +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleJarInterceptor.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleJarInterceptor.java new file mode 100644 index 000000000..a439f8199 --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/BundleJarInterceptor.java @@ -0,0 +1,42 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.util.StringTokenizer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.slc.SlcException; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class BundleJarInterceptor extends HandlerInterceptorAdapter { + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object handler) throws Exception { + String path = request.getPathInfo(); + StringTokenizer stS = new StringTokenizer(path, "/"); + String fileName = null; + while (stS.hasMoreTokens()) { + String token = stS.nextToken(); + if (!stS.hasMoreTokens()) { + fileName = token; + } + } + + int ind_ = fileName.indexOf('-'); + String moduleName; + if (ind_ > -1) + moduleName = fileName.substring(0, ind_); + else + throw new SlcException("Cannot determine version for " + fileName); + + String versionAndExtension = fileName.substring(ind_ + 1); + int indExt = versionAndExtension.lastIndexOf('.'); + String moduleVersion = versionAndExtension.substring(0, indExt); + + request.setAttribute("moduleName", moduleName); + request.setAttribute("moduleVersion", moduleVersion); + + return true; + } +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteHandler.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteHandler.java index 7718ca38a..d4c7260a9 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteHandler.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteHandler.java @@ -1,83 +1,22 @@ package org.argeo.slc.web.mvc.provisioning; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; -import java.util.jar.JarInputStream; -import java.util.jar.Manifest; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.core.io.Resource; +import org.argeo.slc.build.ModularDistribution; import org.springframework.web.HttpRequestHandler; /** An Eclipse update site, serving site.xml features/* and plugins/*. */ public class EclipseUpdateSiteHandler implements HttpRequestHandler { - private FileProvider provider; - private String baseVersion = "0.9.4-SNAPSHOT"; - - private EclipseUpdateSite updateSite; - public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - String path = request.getPathInfo(); - StringTokenizer stS = new StringTokenizer(path, "/"); - String distribution = stS.nextToken(); - - StringBuffer buf = new StringBuffer(""); - buf.append(""); - - List usedCategories = new ArrayList(); - for (EclipseUpdateSiteFeature feature : updateSite.getFeatures()) { - Resource bundle = provider.getBundle(distribution, feature - .getName(), baseVersion); - JarInputStream in = new JarInputStream(bundle.getInputStream()); - Manifest mf = in.getManifest(); - String version = mf.getMainAttributes().getValue("Bundle-Version"); - String featureId = feature.getName(); - buf.append("\n"); - - for (EclipseUpdateSiteCategory category : feature.getCategories()) { - usedCategories.add(category); - buf.append(" \n"); - } - buf.append("\n\n"); - } - - for (EclipseUpdateSiteCategory category : usedCategories) { - buf.append("\n"); - buf.append(" ").append(category.getDescription()) - .append("\n"); - buf.append("\n\n"); - } - - buf.append(""); - response.getWriter().print(buf.toString()); + ModularDistribution modularDistribution = (ModularDistribution) request + .getAttribute("modularDistribution"); + response.getWriter().write( + modularDistribution.getDescriptor("eclipse").toString()); } - - public void setProvider(FileProvider provider) { - this.provider = provider; - } - - public void setBaseVersion(String baseVersion) { - this.baseVersion = baseVersion; - } - - public void setUpdateSite(EclipseUpdateSite updateSite) { - this.updateSite = updateSite; - } - } diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteInterceptor.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteInterceptor.java new file mode 100644 index 000000000..5dab52b77 --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteInterceptor.java @@ -0,0 +1,51 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.util.StringTokenizer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.slc.SlcException; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class EclipseUpdateSiteInterceptor extends HandlerInterceptorAdapter { + public final static String RELEASE = "RELEASE"; + public final static String LATEST = "LATEST"; + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object handler) throws Exception { + String path = request.getPathInfo(); + StringTokenizer stS = new StringTokenizer(path, "/"); + String type = null; + pathTokenizer: while (stS.hasMoreTokens()) { + String token = stS.nextToken(); + if (token.equals("plugins") || token.equals("features")) { + type = token; + break pathTokenizer; + } + } + + if (type == null || !stS.hasMoreTokens()) + throw new SlcException("Cannot determine file name from path " + + path); + + String fileName = stS.nextToken(); + + int ind_ = fileName.indexOf('_'); + String moduleName; + if (ind_ > -1) + moduleName = fileName.substring(0, ind_); + else + throw new SlcException("Cannot determine version for " + fileName); + + String versionAndExtension = fileName.substring(ind_ + 1); + int indExt = versionAndExtension.lastIndexOf('.'); + String moduleVersion = versionAndExtension.substring(0, indExt); + + request.setAttribute("moduleName", moduleName); + request.setAttribute("moduleVersion", moduleVersion); + + return true; + } +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/FileProvider.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/FileProvider.java deleted file mode 100644 index 6751e09f8..000000000 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/FileProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.argeo.slc.web.mvc.provisioning; - -import java.io.InputStream; -import java.io.OutputStream; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.core.io.Resource; - -public class FileProvider { - private final static Log log = LogFactory.getLog(FileProvider.class); - - private Resource base; - - public void read(String distribution, String name, String version, - OutputStream out) { - Resource bundle = getBundle(distribution, name, version); - InputStream in = null; - try { - in = bundle.getInputStream(); - IOUtils.copy(in, out); - } catch (Exception e) { - throw new SlcException("Cannot read bundle for " + name + " (" - + version + ")",e); - } finally { - IOUtils.closeQuietly(in); - } - } - - public Resource getBundle(String distribution, String name, String version) { - try { - String shortVersion = version; - int indR = version.indexOf("-r"); - if (indR > -1) { - shortVersion = version.substring(0, indR); - } - - int indS = shortVersion.indexOf(".SNAPSHOT"); - if (indS > -1) { - StringBuffer buf = new StringBuffer(shortVersion); - buf.setCharAt(indS, '-'); - shortVersion = buf.toString(); - } - - if (log.isDebugEnabled()) - log.debug("Short version for " + name + ": " + shortVersion); - - Resource res = base.createRelative("lib/" + name + "-" - + shortVersion + ".jar"); - return res; - } catch (Exception e) { - throw new SlcException("Cannot get bundle for " + name + " (" - + version + ")",e); - } - } - - public void setBase(Resource base) { - this.base = base; - } - -} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/ModularDistributionInterceptor.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/ModularDistributionInterceptor.java new file mode 100644 index 000000000..309b9960c --- /dev/null +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/ModularDistributionInterceptor.java @@ -0,0 +1,67 @@ +package org.argeo.slc.web.mvc.provisioning; + +import java.util.Iterator; +import java.util.Set; +import java.util.SortedMap; +import java.util.StringTokenizer; +import java.util.TreeMap; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.argeo.slc.SlcException; +import org.argeo.slc.build.BasicNameVersion; +import org.argeo.slc.build.ModularDistribution; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class ModularDistributionInterceptor extends HandlerInterceptorAdapter { + private Set modularDistributions; + + public final static String RELEASE = "RELEASE"; + public final static String LATEST = "LATEST"; + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, Object handler) throws Exception { + String path = request.getPathInfo(); + StringTokenizer stS = new StringTokenizer(path, "/"); + String distributionName = stS.nextToken(); + String distributionVersion = stS.nextToken(); + + SortedMap choices = new TreeMap(); + distribs: for (Iterator it = modularDistributions + .iterator(); it.hasNext();) { + ModularDistribution md = it.next(); + if (md.getName().equals(distributionName)) { + if (distributionVersion.equals(RELEASE) + && md.getVersion().contains("SNAPSHOT")) + continue distribs; + + else if (distributionVersion.equals(LATEST)) + choices.put(md.getVersion(), md); + else if (distributionVersion.equals(md.getVersion())) { + choices.put(md.getVersion(), md); + break distribs; + } + } + } + + if (choices.size() == 0) + throw new SlcException("Cannot find distribution for " + + new BasicNameVersion(distributionName, + distributionVersion)); + + ModularDistribution modularDistribution = choices.get(choices + .firstKey()); + + request.setAttribute("modularDistribution", modularDistribution); + + return true; + } + + public void setModularDistributions( + Set modularDistributions) { + this.modularDistributions = modularDistributions; + } + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/PluginHandler.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/PluginHandler.java deleted file mode 100644 index 7f44d0d20..000000000 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/PluginHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.argeo.slc.web.mvc.provisioning; - -import java.io.IOException; -import java.util.StringTokenizer; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.slc.SlcException; -import org.springframework.web.HttpRequestHandler; - -public class PluginHandler implements HttpRequestHandler { - private final static Log log = LogFactory.getLog(PluginHandler.class); - - private FileProvider provider; - - public void handleRequest(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - // log.debug(request.getContextPath()); - // log.debug(request.getServletPath()); - // log.debug(request.getPathInfo()); - // log.debug(request.getPathTranslated()); - // log.debug(request.getLocalName()); - // log.debug(request.getLocalAddr()); - // log.debug(request.getQueryString()); - // log.debug(request.getRequestURL()); - // log.debug(request.getRequestURI()); - - String path = request.getPathInfo(); - - if (log.isDebugEnabled()) - log.debug("Request " + path); - - StringTokenizer stS = new StringTokenizer(path, "/"); - String distribution = stS.nextToken(); - stS.nextToken();// plugins - String fileName = stS.nextToken(); - - int ind_ = fileName.indexOf('_'); - String moduleName; - if (ind_ > -1) - moduleName = fileName.substring(0, ind_); - else - throw new SlcException("Cannot determine version for " + fileName); - - String versionAndExtension = fileName.substring(ind_ + 1); - int indExt = versionAndExtension.lastIndexOf('.'); - String moduleVersion = versionAndExtension.substring(0, indExt); - - provider.read(distribution, moduleName, moduleVersion, response - .getOutputStream()); - } - - public void setProvider(FileProvider provider) { - this.provider = provider; - } - -} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/StreamReadable.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/StreamReadable.java new file mode 100644 index 000000000..f1bef22fd --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/StreamReadable.java @@ -0,0 +1,7 @@ +package org.argeo.slc; + +import java.io.InputStream; + +public interface StreamReadable { + public InputStream getInputStream(); +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/BasicNameVersion.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/BasicNameVersion.java new file mode 100644 index 000000000..c83ef3c21 --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/BasicNameVersion.java @@ -0,0 +1,63 @@ +package org.argeo.slc.build; + +public class BasicNameVersion implements NameVersion, Comparable { + private String name; + private String version; + + public BasicNameVersion() { + } + + public BasicNameVersion(String name, String version) { + this.name = name; + this.version = version; + } + + public BasicNameVersion(NameVersion nameVersion) { + this.name = nameVersion.getName(); + this.version = nameVersion.getVersion(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof NameVersion) { + NameVersion nameVersion = (NameVersion) obj; + return name.equals(nameVersion.getName()) + && version.equals(nameVersion.getVersion()); + } else + return false; + } + + @Override + public int hashCode() { + return name.hashCode() + version.hashCode(); + } + + @Override + public String toString() { + return name + ":" + version; + } + + public int compareTo(NameVersion o) { + if (o.getName().equals(name)) + return version.compareTo(o.getVersion()); + else + return name.compareTo(o.getName()); + } + +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/ModularDistribution.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/ModularDistribution.java new file mode 100644 index 000000000..cc9aacdc0 --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/ModularDistribution.java @@ -0,0 +1,12 @@ +package org.argeo.slc.build; + +import java.util.Set; + +public interface ModularDistribution extends Distribution, NameVersion { + public Distribution getModuleDistribution(String moduleName, + String moduleVersion); + + public Set listModulesNameVersions(); + + public Object getDescriptor(String descriptorType); +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/NameVersion.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/NameVersion.java new file mode 100644 index 000000000..ae65255a1 --- /dev/null +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/build/NameVersion.java @@ -0,0 +1,7 @@ +package org.argeo.slc.build; + +public interface NameVersion { + public String getName(); + + public String getVersion(); +} diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java index cd2e95eb9..be28154fe 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/DeployedSystem.java @@ -3,7 +3,7 @@ package org.argeo.slc.deploy; import org.argeo.slc.build.Distribution; /** An instance of a software system. */ -public interface DeployedSystem extends TargetData { +public interface DeployedSystem extends TargetData { /** Unique ID for this system instance. */ public String getDeployedSystemId(); diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java index 57e387924..0020ad6a3 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/deploy/Module.java @@ -1,9 +1,6 @@ package org.argeo.slc.deploy; -import org.argeo.slc.build.Distribution; +import org.argeo.slc.build.NameVersion; -public interface Module extends DeployedSystem { - public String getName(); - - public String getVersion(); +public interface Module extends DeployedSystem, NameVersion { } diff --git a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiBundle.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiBundle.java index ff90b95b7..745ba76a6 100644 --- a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiBundle.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiBundle.java @@ -1,7 +1,6 @@ package org.argeo.slc.osgi; import org.argeo.slc.build.Distribution; -import org.argeo.slc.core.build.ResourceDistribution; import org.argeo.slc.deploy.DeploymentData; import org.argeo.slc.deploy.Module; import org.argeo.slc.deploy.TargetData; @@ -9,7 +8,7 @@ import org.argeo.slc.process.RealizedFlow; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; -public class OsgiBundle implements Module { +public class OsgiBundle implements Module { private String name; private String version; private Distribution distribution; @@ -20,6 +19,11 @@ public class OsgiBundle implements Module { } + public OsgiBundle(String name, String version) { + this.name = name; + this.version = version; + } + public OsgiBundle(Bundle bundle) { name = bundle.getSymbolicName(); version = bundle.getHeaders().get(Constants.BUNDLE_VERSION).toString(); diff --git a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java index f82ceffba..e433d7e29 100644 --- a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/OsgiRuntime.java @@ -6,7 +6,7 @@ import java.util.UUID; import org.argeo.slc.UnsupportedException; import org.argeo.slc.build.Distribution; -import org.argeo.slc.core.build.ResourceDistribution; +import org.argeo.slc.core.build.VersionedResourceDistribution; import org.argeo.slc.deploy.DeploymentData; import org.argeo.slc.deploy.ModularDeployedSystem; import org.argeo.slc.deploy.TargetData; @@ -32,7 +32,10 @@ public class OsgiRuntime implements ModularDeployedSystem, String location = bundle.getLocation(); if (location != null) { Resource resource = resourceLoader.getResource(location); - osgiBundle.setDistribution(new ResourceDistribution(resource)); + osgiBundle + .setDistribution(new VersionedResourceDistribution( + osgiBundle.getName(), osgiBundle.getVersion(), + resource)); } } return modules; diff --git a/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/BundleModularDistribution.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/BundleModularDistribution.java new file mode 100644 index 000000000..79bc3e6a8 --- /dev/null +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/BundleModularDistribution.java @@ -0,0 +1,216 @@ +package org.argeo.slc.osgi.build; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedMap; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.UnsupportedException; +import org.argeo.slc.build.BasicNameVersion; +import org.argeo.slc.build.Distribution; +import org.argeo.slc.build.ModularDistribution; +import org.argeo.slc.build.NameVersion; +import org.argeo.slc.core.build.VersionedResourceDistribution; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.ResourceLoader; +import org.springframework.osgi.context.BundleContextAware; + +public class BundleModularDistribution implements ModularDistribution, + BundleContextAware, InitializingBean, ResourceLoaderAware { + private final static Log log = LogFactory + .getLog(BundleModularDistribution.class); + + private BundleContext bundleContext; + private ResourceLoader resourceLoader; + + private String libDirectory = "/lib"; + private EclipseUpdateSite eclipseUpdateSite; + + /** Initialized by the object itself. */ + private SortedMap distributions = new TreeMap(); + + public Distribution getModuleDistribution(String moduleName, + String moduleVersion) { + return distributions + .get(new BasicNameVersion(moduleName, moduleVersion)); + // URL url = findModule(moduleName, moduleVersion); + // return new ResourceDistribution(new UrlResource(url)); + } + + @SuppressWarnings(value = { "unchecked" }) + protected URL findModule(String moduleName, String version) { + Enumeration urls = (Enumeration) bundleContext.getBundle() + .findEntries(libDirectory, moduleName + "*", false); + + if (!urls.hasMoreElements()) + throw new SlcException("Cannot find module " + moduleName); + + URL url = urls.nextElement(); + + // TODO: check version as well + if (urls.hasMoreElements()) + throw new SlcException("More than one module with name " + + moduleName); + return url; + } + + public String getDistributionId() { + return bundleContext.getBundle().getSymbolicName() + + "-" + + bundleContext.getBundle().getHeaders().get( + Constants.BUNDLE_VERSION); + } + + public Set listModulesNameVersions() { + return distributions.keySet(); + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + @SuppressWarnings(value = { "unchecked" }) + public void afterPropertiesSet() throws Exception { + Enumeration urls = (Enumeration) bundleContext.getBundle() + .findEntries(libDirectory, "*.jar", false); + while (urls.hasMoreElements()) { + URL url = urls.nextElement(); + JarInputStream in = null; + try { + in = new JarInputStream(url.openStream()); + Manifest mf = in.getManifest(); + String name = mf.getMainAttributes().getValue( + Constants.BUNDLE_SYMBOLICNAME); + // Skip additional specs such as + // ; singleton:=true + if (name.indexOf(';') > -1) { + name = new StringTokenizer(name, " ;").nextToken(); + } + + String version = mf.getMainAttributes().getValue( + Constants.BUNDLE_VERSION); + BasicNameVersion nameVersion = new BasicNameVersion(name, + version); + distributions.put(nameVersion, + new VersionedResourceDistribution(name, version, + resourceLoader.getResource(url.toString()))); + } finally { + IOUtils.closeQuietly(in); + } + } + if (log.isDebugEnabled()) + log.debug("Distribution " + getName() + ":" + getVersion() + + " loaded (" + distributions.size() + " modules)"); + + } + + protected String findVersion(String name) { + Set versions = new HashSet(); + for (NameVersion key : distributions.keySet()) { + if (key.getName().equals(name)) + versions.add(key.getVersion()); + } + + if (versions.size() == 0) + throw new SlcException("Cannot find version for name " + name); + else if (versions.size() > 1) + throw new SlcException("Found more than one version for name " + + name + ": " + versions); + else + return versions.iterator().next(); + + } + + public void setLibDirectory(String libDirectory) { + this.libDirectory = libDirectory; + } + + public Object getDescriptor(String descriptorType) { + if (descriptorType.equals("eclipse")) + return writeEclipseUpdateSite(); + else + throw new UnsupportedException("descriptorType", descriptorType); + } + + protected Set writePlainUrlList() { + return distributions.keySet(); + } + + protected String writeEclipseUpdateSite() { + if (eclipseUpdateSite == null) + throw new SlcException("No eclipse update site declared."); + + StringBuffer buf = new StringBuffer(""); + buf.append(""); + + List usedCategories = new ArrayList(); + for (EclipseUpdateSiteFeature feature : eclipseUpdateSite.getFeatures()) { + + String featureId = feature.getName(); + String featureVersion = findVersion(featureId); + buf.append("\n"); + + for (EclipseUpdateSiteCategory category : feature.getCategories()) { + usedCategories.add(category); + buf.append(" \n"); + } + buf.append("\n\n"); + } + + for (EclipseUpdateSiteCategory category : usedCategories) { + buf.append("\n"); + buf.append(" ").append(category.getDescription()) + .append("\n"); + buf.append("\n\n"); + } + + buf.append(""); + return buf.toString(); + } + + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + + public String getName() { + return bundleContext.getBundle().getSymbolicName(); + } + + public String getVersion() { + return bundleContext.getBundle().getHeaders().get( + Constants.BUNDLE_VERSION).toString(); + } + + @Override + public String toString() { + return new BasicNameVersion(this).toString(); + } + + public void setEclipseUpdateSite(EclipseUpdateSite eclipseUpdateSite) { + this.eclipseUpdateSite = eclipseUpdateSite; + } + +} diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSite.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSite.java similarity index 89% rename from runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSite.java rename to runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSite.java index 36a09491b..b8debf575 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSite.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSite.java @@ -1,4 +1,4 @@ -package org.argeo.slc.web.mvc.provisioning; +package org.argeo.slc.osgi.build; import java.util.ArrayList; import java.util.List; diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteCategory.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSiteCategory.java similarity index 91% rename from runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteCategory.java rename to runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSiteCategory.java index 04e8e2bda..510a55552 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteCategory.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSiteCategory.java @@ -1,4 +1,4 @@ -package org.argeo.slc.web.mvc.provisioning; +package org.argeo.slc.osgi.build; public class EclipseUpdateSiteCategory { private String name; diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteFeature.java b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSiteFeature.java similarity index 92% rename from runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteFeature.java rename to runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSiteFeature.java index dc24f28f6..42ded0b31 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/provisioning/EclipseUpdateSiteFeature.java +++ b/runtime/org.argeo.slc.support.osgi/src/main/java/org/argeo/slc/osgi/build/EclipseUpdateSiteFeature.java @@ -1,4 +1,4 @@ -package org.argeo.slc.web.mvc.provisioning; +package org.argeo.slc.osgi.build; import java.util.ArrayList; import java.util.List; diff --git a/runtime/org.argeo.slc.unit/src/main/java/org/argeo/slc/unit/db/DbUnitDeployment.java b/runtime/org.argeo.slc.unit/src/main/java/org/argeo/slc/unit/db/DbUnitDeployment.java index 998a36e5a..7c10f8e95 100644 --- a/runtime/org.argeo.slc.unit/src/main/java/org/argeo/slc/unit/db/DbUnitDeployment.java +++ b/runtime/org.argeo.slc.unit/src/main/java/org/argeo/slc/unit/db/DbUnitDeployment.java @@ -56,7 +56,7 @@ public class DbUnitDeployment implements Deployment { } } - public DeployedSystem getDeployedSystem() { + public DeployedSystem getDeployedSystem() { throw new UnsupportedOperationException(); } -- 2.39.2