X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms.ee%2Fsrc%2Forg%2Fargeo%2Fcms%2Fservlet%2Finternal%2FPkgServlet.java;fp=org.argeo.cms.ee%2Fsrc%2Forg%2Fargeo%2Fcms%2Fservlet%2Finternal%2FPkgServlet.java;h=c762b67ecc36a610b3e24508861cdcf4655c064b;hb=00753f77ac3f41f7dbfe281eeab886ef4bdc0ce5;hp=0000000000000000000000000000000000000000;hpb=fa0040a5e9655896bb32c4db7392cf1f08f8be63;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms.ee/src/org/argeo/cms/servlet/internal/PkgServlet.java b/org.argeo.cms.ee/src/org/argeo/cms/servlet/internal/PkgServlet.java new file mode 100644 index 000000000..c762b67ec --- /dev/null +++ b/org.argeo.cms.ee/src/org/argeo/cms/servlet/internal/PkgServlet.java @@ -0,0 +1,133 @@ +package org.argeo.cms.servlet.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collection; +import java.util.SortedMap; +import java.util.TreeMap; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.IOUtils; +import org.argeo.cms.osgi.PublishNamespace; +import org.argeo.osgi.util.FilterRequirement; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.Version; +import org.osgi.framework.VersionRange; +import org.osgi.framework.namespace.PackageNamespace; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.framework.wiring.FrameworkWiring; +import org.osgi.resource.Requirement; + +public class PkgServlet extends HttpServlet { + private static final long serialVersionUID = 7660824185145214324L; + + private BundleContext bundleContext = FrameworkUtil.getBundle(PkgServlet.class).getBundleContext(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String pathInfo = req.getPathInfo(); + + String pkg, versionStr, file; + String[] parts = pathInfo.split("/"); + // first is always empty + if (parts.length == 4) { + pkg = parts[1]; + versionStr = parts[2]; + file = parts[3]; + } else if (parts.length == 3) { + pkg = parts[1]; + versionStr = null; + file = parts[2]; + } else { + throw new IllegalArgumentException("Unsupported path length " + pathInfo); + } + + FrameworkWiring frameworkWiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class); + String filter; + if (versionStr == null) { + filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")"; + } else { + if (versionStr.startsWith("[") || versionStr.startsWith("(")) {// range + VersionRange versionRange = new VersionRange(versionStr); + filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")" + + versionRange.toFilterString(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE) + ")"; + + } else { + Version version = new Version(versionStr); + filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")(" + + PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=" + version + "))"; + } + } + Requirement requirement = new FilterRequirement(PackageNamespace.PACKAGE_NAMESPACE, filter); + Collection packages = frameworkWiring.findProviders(requirement); + if (packages.isEmpty()) { + resp.sendError(404); + return; + } + + // TODO verify that it works with multiple versions + SortedMap sorted = new TreeMap<>(); + for (BundleCapability capability : packages) { + sorted.put(capability.getRevision().getVersion(), capability); + } + + Bundle bundle = sorted.get(sorted.firstKey()).getRevision().getBundle(); + String entryPath = '/' + pkg.replace('.', '/') + '/' + file; + URL internalURL = bundle.getResource(entryPath); + if (internalURL == null) { + resp.sendError(404); + return; + } + + // Resource found, we now check whether it can be published + boolean publish = false; + BundleWiring bundleWiring = bundle.adapt(BundleWiring.class); + capabilities: for (BundleCapability bundleCapability : bundleWiring + .getCapabilities(PublishNamespace.CMS_PUBLISH_NAMESPACE)) { + Object publishedPkg = bundleCapability.getAttributes().get(PublishNamespace.PKG); + if (publishedPkg != null) { + if (publishedPkg.equals("*") || publishedPkg.equals(pkg)) { + Object publishedFile = bundleCapability.getAttributes().get(PublishNamespace.FILE); + if (publishedFile == null) { + publish = true; + break capabilities; + } else { + String[] publishedFiles = publishedFile.toString().split(","); + for (String pattern : publishedFiles) { + if (pattern.startsWith("*.")) { + String ext = pattern.substring(1); + if (file.endsWith(ext)) { + publish = true; + break capabilities; + } + } else { + if (publishedFile.equals(file)) { + publish = true; + break capabilities; + } + } + } + } + } + } + } + + if (!publish) { + resp.sendError(404); + return; + } + + try (InputStream in = internalURL.openStream()) { + IOUtils.copy(in, resp.getOutputStream()); + } + } + +}