]> git.argeo.org Git - lgpl/argeo-commons.git/blob - PkgServlet.java
c762b67ecc36a610b3e24508861cdcf4655c064b
[lgpl/argeo-commons.git] / PkgServlet.java
1 package org.argeo.cms.servlet.internal;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URL;
6 import java.util.Collection;
7 import java.util.SortedMap;
8 import java.util.TreeMap;
9
10 import javax.servlet.ServletException;
11 import javax.servlet.http.HttpServlet;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14
15 import org.apache.commons.io.IOUtils;
16 import org.argeo.cms.osgi.PublishNamespace;
17 import org.argeo.osgi.util.FilterRequirement;
18 import org.osgi.framework.Bundle;
19 import org.osgi.framework.BundleContext;
20 import org.osgi.framework.FrameworkUtil;
21 import org.osgi.framework.Version;
22 import org.osgi.framework.VersionRange;
23 import org.osgi.framework.namespace.PackageNamespace;
24 import org.osgi.framework.wiring.BundleCapability;
25 import org.osgi.framework.wiring.BundleWiring;
26 import org.osgi.framework.wiring.FrameworkWiring;
27 import org.osgi.resource.Requirement;
28
29 public class PkgServlet extends HttpServlet {
30 private static final long serialVersionUID = 7660824185145214324L;
31
32 private BundleContext bundleContext = FrameworkUtil.getBundle(PkgServlet.class).getBundleContext();
33
34 @Override
35 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
36 String pathInfo = req.getPathInfo();
37
38 String pkg, versionStr, file;
39 String[] parts = pathInfo.split("/");
40 // first is always empty
41 if (parts.length == 4) {
42 pkg = parts[1];
43 versionStr = parts[2];
44 file = parts[3];
45 } else if (parts.length == 3) {
46 pkg = parts[1];
47 versionStr = null;
48 file = parts[2];
49 } else {
50 throw new IllegalArgumentException("Unsupported path length " + pathInfo);
51 }
52
53 FrameworkWiring frameworkWiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
54 String filter;
55 if (versionStr == null) {
56 filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")";
57 } else {
58 if (versionStr.startsWith("[") || versionStr.startsWith("(")) {// range
59 VersionRange versionRange = new VersionRange(versionStr);
60 filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")"
61 + versionRange.toFilterString(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE) + ")";
62
63 } else {
64 Version version = new Version(versionStr);
65 filter = "(&(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + pkg + ")("
66 + PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE + "=" + version + "))";
67 }
68 }
69 Requirement requirement = new FilterRequirement(PackageNamespace.PACKAGE_NAMESPACE, filter);
70 Collection<BundleCapability> packages = frameworkWiring.findProviders(requirement);
71 if (packages.isEmpty()) {
72 resp.sendError(404);
73 return;
74 }
75
76 // TODO verify that it works with multiple versions
77 SortedMap<Version, BundleCapability> sorted = new TreeMap<>();
78 for (BundleCapability capability : packages) {
79 sorted.put(capability.getRevision().getVersion(), capability);
80 }
81
82 Bundle bundle = sorted.get(sorted.firstKey()).getRevision().getBundle();
83 String entryPath = '/' + pkg.replace('.', '/') + '/' + file;
84 URL internalURL = bundle.getResource(entryPath);
85 if (internalURL == null) {
86 resp.sendError(404);
87 return;
88 }
89
90 // Resource found, we now check whether it can be published
91 boolean publish = false;
92 BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
93 capabilities: for (BundleCapability bundleCapability : bundleWiring
94 .getCapabilities(PublishNamespace.CMS_PUBLISH_NAMESPACE)) {
95 Object publishedPkg = bundleCapability.getAttributes().get(PublishNamespace.PKG);
96 if (publishedPkg != null) {
97 if (publishedPkg.equals("*") || publishedPkg.equals(pkg)) {
98 Object publishedFile = bundleCapability.getAttributes().get(PublishNamespace.FILE);
99 if (publishedFile == null) {
100 publish = true;
101 break capabilities;
102 } else {
103 String[] publishedFiles = publishedFile.toString().split(",");
104 for (String pattern : publishedFiles) {
105 if (pattern.startsWith("*.")) {
106 String ext = pattern.substring(1);
107 if (file.endsWith(ext)) {
108 publish = true;
109 break capabilities;
110 }
111 } else {
112 if (publishedFile.equals(file)) {
113 publish = true;
114 break capabilities;
115 }
116 }
117 }
118 }
119 }
120 }
121 }
122
123 if (!publish) {
124 resp.sendError(404);
125 return;
126 }
127
128 try (InputStream in = internalURL.openStream()) {
129 IOUtils.copy(in, resp.getOutputStream());
130 }
131 }
132
133 }