You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2013/10/22 16:31:41 UTC
svn commit: r1534645 - in /sling/trunk/tooling/support/install: pom.xml
src/main/java/org/apache/sling/tooling/support/install/impl/InstallServlet.java
Author: rombert
Date: Tue Oct 22 14:31:41 2013
New Revision: 1534645
URL: http://svn.apache.org/r1534645
Log:
SLING-3019 - Provide a mechanism to install a bundle based on a
directory
Allow updating a bundle from an uploaded jar file.
Modified:
sling/trunk/tooling/support/install/pom.xml
sling/trunk/tooling/support/install/src/main/java/org/apache/sling/tooling/support/install/impl/InstallServlet.java
Modified: sling/trunk/tooling/support/install/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/support/install/pom.xml?rev=1534645&r1=1534644&r2=1534645&view=diff
==============================================================================
--- sling/trunk/tooling/support/install/pom.xml (original)
+++ sling/trunk/tooling/support/install/pom.xml Tue Oct 22 14:31:41 2013
@@ -99,5 +99,11 @@
<version>2.4</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <version>1.2.2</version>
+ <scope>provided</scope>
+ </dependency>
</dependencies>
</project>
Modified: sling/trunk/tooling/support/install/src/main/java/org/apache/sling/tooling/support/install/impl/InstallServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/tooling/support/install/src/main/java/org/apache/sling/tooling/support/install/impl/InstallServlet.java?rev=1534645&r1=1534644&r2=1534645&view=diff
==============================================================================
--- sling/trunk/tooling/support/install/src/main/java/org/apache/sling/tooling/support/install/impl/InstallServlet.java (original)
+++ sling/trunk/tooling/support/install/src/main/java/org/apache/sling/tooling/support/install/impl/InstallServlet.java Tue Oct 22 14:31:41 2013
@@ -22,7 +22,9 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import java.util.jar.JarFile;
+import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.Deflater;
@@ -38,13 +40,20 @@ import javax.servlet.http.HttpServletRes
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.service.packageadmin.PackageAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.io.IOUtils;
/**
* Prototype for installing/updating a bundle from a directory
@@ -60,8 +69,13 @@ public class InstallServlet extends Http
private static final String DIR = "dir";
+ private static final int UPLOAD_IN_MEMORY_SIZE_THRESHOLD = 512 * 1024 * 1024;
+
private BundleContext bundleContext;
+ @Reference
+ private PackageAdmin packageAdmin;
+
@Activate
protected void activate(final BundleContext bundleContext) {
this.bundleContext = bundleContext;
@@ -71,16 +85,98 @@ public class InstallServlet extends Http
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
final String dirPath = req.getParameter(DIR);
- if ( dirPath == null ) {
- logger.error("No dir parameter specified : {}", req.getParameterMap());
+
+ boolean isMultipart = ServletFileUpload.isMultipartContent(req);
+
+ if (dirPath == null && !isMultipart) {
+ logger.error("No dir parameter specified : {} and no multipart content found", req.getParameterMap());
resp.setStatus(500);
InstallationResult result = new InstallationResult(false, "No dir parameter specified: "
- + req.getParameterMap());
+ + req.getParameterMap() + " and no multipart content found");
result.render(resp.getWriter());
return;
}
- final File dir = new File(dirPath);
- installBasedOnDirectory(resp, dir);
+
+ if (isMultipart) {
+ installBasedOnUploadedJar(req, resp);
+ } else {
+ installBasedOnDirectory(resp, new File(dirPath));
+ }
+ }
+
+ private void installBasedOnUploadedJar(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+
+ InstallationResult result = null;
+
+ try {
+ DiskFileItemFactory factory = new DiskFileItemFactory();
+ // try to hold even largish bundles in memory to potentially improve performance
+ factory.setSizeThreshold(UPLOAD_IN_MEMORY_SIZE_THRESHOLD);
+
+ ServletFileUpload upload = new ServletFileUpload();
+ upload.setFileItemFactory(factory);
+
+ @SuppressWarnings("unchecked")
+ List<FileItem> items = upload.parseRequest(req);
+ if (items.size() != 1) {
+ logAndWriteError("Found " + items.size() + " items to process, but only updating 1 bundle is supported", resp);
+ return;
+ }
+
+ FileItem item = items.get(0);
+
+ JarInputStream jar = null;
+ InputStream rawInput = null;
+ try {
+ jar = new JarInputStream(item.getInputStream());
+ Manifest manifest = jar.getManifest();
+ if (manifest == null) {
+ logAndWriteError("Uploaded jar file does not contain a manifest", resp);
+ return;
+ }
+
+ final String symbolicName = manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+ if (symbolicName == null) {
+ logAndWriteError("Manifest does not have a " + Constants.BUNDLE_SYMBOLICNAME, resp);
+ return;
+ }
+
+ // the JarInputStream is used only for validation, we need a fresh input stream for updating
+ rawInput = item.getInputStream();
+
+ Bundle found = getBundle(symbolicName);
+ try {
+ installOrUpdateBundle(found, rawInput, null);
+
+ result = new InstallationResult(true, null);
+ resp.setStatus(200);
+ result.render(resp.getWriter());
+ return;
+ } catch (BundleException e) {
+ logAndWriteError("Unable to install/update bundle " + symbolicName, e, resp);
+ return;
+ }
+ } finally {
+ IOUtils.closeQuietly(jar);
+ IOUtils.closeQuietly(rawInput);
+ }
+
+ } catch (FileUploadException e) {
+ logAndWriteError("Failed parsing uploaded bundle", e, resp);
+ return;
+ }
+ }
+
+ private void logAndWriteError(String message, HttpServletResponse resp) throws IOException {
+ logger.info(message);
+ resp.setStatus(500);
+ new InstallationResult(false, message).render(resp.getWriter());
+ }
+
+ private void logAndWriteError(String message, Exception e, HttpServletResponse resp) throws IOException {
+ logger.info(message, e);
+ resp.setStatus(500);
+ new InstallationResult(false, message + " : " + e.getMessage()).render(resp.getWriter());
}
private void installBasedOnDirectory(HttpServletResponse resp, final File dir) throws FileNotFoundException,
@@ -100,13 +196,7 @@ public class InstallServlet extends Http
final String symbolicName = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
if ( symbolicName != null ) {
// search bundle
- Bundle found = null;
- for(final Bundle b : this.bundleContext.getBundles() ) {
- if ( symbolicName.equals(b.getSymbolicName()) ) {
- found = b;
- break;
- }
- }
+ Bundle found = getBundle(symbolicName);
final File tempFile = File.createTempFile(dir.getName(), "bundle");
try {
@@ -114,14 +204,9 @@ public class InstallServlet extends Http
final InputStream in = new FileInputStream(tempFile);
try {
- if ( found != null ) {
- // update
- found.update(in);
- } else {
- // install
- final Bundle b = bundleContext.installBundle(dir.getAbsolutePath(), in);
- b.start();
- }
+ String location = dir.getAbsolutePath();
+
+ installOrUpdateBundle(found, in, location);
result = new InstallationResult(true, null);
resp.setStatus(200);
result.render(resp.getWriter());
@@ -157,6 +242,30 @@ public class InstallServlet extends Http
}
}
+ private void installOrUpdateBundle(Bundle bundle, final InputStream in, String location) throws BundleException {
+ if (bundle != null) {
+ // update
+ bundle.update(in);
+
+ packageAdmin.refreshPackages(new Bundle[] { bundle });
+ } else {
+ // install
+ final Bundle b = bundleContext.installBundle(location, in);
+ b.start();
+ }
+ }
+
+ private Bundle getBundle(final String symbolicName) {
+ Bundle found = null;
+ for (final Bundle b : this.bundleContext.getBundles()) {
+ if (symbolicName.equals(b.getSymbolicName())) {
+ found = b;
+ break;
+ }
+ }
+ return found;
+ }
+
private static void createJar(final File sourceDir, final File jarFile, final Manifest mf)
throws IOException {
final JarOutputStream zos = new JarOutputStream(new FileOutputStream(jarFile));