Last active
March 11, 2021 08:38
-
-
Save stoerr/a54c58b4b05770c6a7ee39654ea84305 to your computer and use it in GitHub Desktop.
Servlet to download a resource subtree from AEM as a content-package
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is a servlet that enables to download a package of a JCR subtree without | |
* having to create a package in the package manager. The package is | |
* created on the fly, and not saved to disk / the repository, so this is | |
* better suited to large content trees, but valuable also for quickly downloading | |
* a page. | |
* | |
* CAUTION: not suitable for production, only for internal testing systems! | |
* | |
* Usage with curl e.g. | |
* curl -s -S -o tmp.zip -u admin:admin http://localhost:6502/apps/net/stoerr/hpsx/getpackage.html/{path to download} | |
* | |
* Example Creates a package of this tool: | |
* http://localhost:6502/apps/net/stoerr/hpsx/getpackage.html/apps/net/stoerr/hpsx | |
* | |
* Fragment of a bash script to download a path from another AEM system and install it locally on AEM: | |
* path=$1 | |
* TMPFIL=`mktemp -u`.zip | |
* trap "{ rm -f $TMPFIL; }" EXIT | |
* PKG=$(basename $TMPFIL) | |
* curl -S -o $TMPFIL -u ${OTHER_USER}:${OTHER_PWD} http://${OTHERIP}:4502/apps/netcentric/hpsx/getpackage.html${path}?packageName=$PKG | |
* curl -u admin:admin -F file=@"$TMPFIL" -F name="tmp $path" -F force=true -F install=true http://localhost:6502/crx/packmgr/service.jsp | |
* curl -u admin:admin -F cmd=delete http://localhost:6502/crx/packmgr/service/.json/etc/packages/my_packages/${PKG%%.zip}-1.zip | |
*/ | |
package apps.net.stoerr.hpsx.getpackage; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.jackrabbit.vault.fs.api.PathFilterSet; | |
import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter; | |
import org.apache.jackrabbit.vault.packaging.*; | |
import org.apache.sling.api.SlingHttpServletRequest; | |
import org.apache.sling.api.SlingHttpServletResponse; | |
import org.apache.sling.api.request.RequestPathInfo; | |
import org.apache.sling.api.resource.Resource; | |
import org.apache.sling.api.resource.ResourceResolver; | |
import org.apache.sling.api.servlets.SlingSafeMethodsServlet; | |
import org.osgi.framework.BundleContext; | |
import org.osgi.framework.FrameworkUtil; | |
import org.osgi.framework.ServiceReference; | |
import javax.jcr.RepositoryException; | |
import javax.jcr.Session; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletOutputStream; | |
import java.io.IOException; | |
public class getpackage extends SlingSafeMethodsServlet { | |
String PARAM_PACKAGENAME = "packageName"; | |
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) | |
throws ServletException, IOException { | |
RequestPathInfo pathInfo = request.getRequestPathInfo(); | |
String resourcePath = pathInfo.getSuffix(); | |
ResourceResolver resolver = request.getResourceResolver(); | |
Resource resource = resolver.getResource(resourcePath); | |
if (resource == null) { | |
throw new IllegalArgumentException("Not found: " + resourcePath); | |
} | |
if (!resource.getPath().matches("/.*/.*/.*")) { | |
throw new IllegalArgumentException("Path too short - package would probably be too large"); | |
} | |
if (!"admin".equals(request.getResourceResolver().getUserID())) { | |
throw new IllegalArgumentException("For security reasons only allowed for admin"); | |
} | |
resourcePath = resource.getPath(); | |
String packageName = "tmp-" + resourcePath.replaceAll("[^a-zA-Z0-9_-]+", "_"); | |
if (StringUtils.isNotBlank(request.getParameter(PARAM_PACKAGENAME))) { | |
packageName = request.getParameter(PARAM_PACKAGENAME); | |
} | |
response.setContentType("application/zip"); | |
response.addHeader("Content-Disposition", "attachment; filename=" + | |
packageName + ".zip"); | |
BundleContext bundleContext = FrameworkUtil.getBundle(Packaging.class).getBundleContext(); | |
ServiceReference packagingRef = bundleContext.getServiceReference(Packaging.class.getName()); | |
Packaging packaging = (Packaging) bundleContext.getService(packagingRef); | |
try { | |
writePackage(resource, packageName, request, packaging, response.getOutputStream()); | |
} catch (RepositoryException | PackageException e) { | |
throw new ServletException(e); | |
} finally { | |
bundleContext.ungetService(packagingRef); | |
resolver.revert(); | |
} | |
} | |
private void writePackage(Resource resource, String packageName, SlingHttpServletRequest request, Packaging packaging, ServletOutputStream outputStream) throws IOException, RepositoryException, PackageException { | |
JcrPackageManager pkgmgr = packaging.getPackageManager(request.getResourceResolver().adaptTo(Session.class)); | |
JcrPackage jcrPackage = pkgmgr.create("my_packages", packageName, "1"); | |
try { | |
JcrPackageDefinition pkgdef = jcrPackage.getDefinition(); | |
DefaultWorkspaceFilter workspaceFilter = new DefaultWorkspaceFilter(); | |
workspaceFilter.add(new PathFilterSet(resource.getPath())); | |
pkgdef.setFilter(workspaceFilter, false); | |
pkgmgr.assemble(pkgdef, null, outputStream); | |
} finally { | |
try { | |
pkgmgr.remove(jcrPackage); | |
} catch (Exception e) { | |
// ignore | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment