ClassLoaderPolicy with Regular Expression Support
This topic has not yet been written. The content below is from the topic description.
The following two examples of ClassLoaderPolicy. The first one retrieves resources based on regular expressions, while the second one handles encrypted resources. Example 9.2. ClassLoaderPolicy with Regular Expression Support public class RegexpClassLoaderPolicy extends ClassLoaderPolicy { private VirtualFile[] roots; private String[] packageNames; public RegexpClassLoaderPolicy(VirtualFile[] roots) { this.roots = roots; } @Override public String[] getPackageNames() { if (packageNames == null) { Set exportedPackages = PackageVisitor.determineAllPackages(roots, null, ExportAll.NON_EMPTY, null, null, null); packageNames = exportedPackages.toArray(new String[exportedPackages.size()]); } return packageNames; } protected Pattern createPattern(String regexp) { boolean outside = true; StringBuilder builder = new StringBuilder(); for (int i = 0; i < regexp.length(); i++) { char ch = regexp.charAt(i); if ((ch == '[' || ch == ']' || ch == '.') && escaped(regexp, i) == false) { switch (ch) { case '[' : outside = false; break; case ']' : outside = true; break; case '.' : if (outside) builder.append("\"); break; } } builder.append(ch); } return Pattern.compile(builder.toString()); } protected boolean escaped(String regexp, int i) { return i > 0 && regexp.charAt(i - 1) == '\'; } public URL getResource(String path) { Pattern pattern = createPattern(path); for (VirtualFile root : roots) { URL url = findURL(root, root, pattern); if (url != null) return url; } return null; } private URL findURL(VirtualFile root, VirtualFile file, Pattern pattern) { try { String path = AbstractStructureDeployer.getRelativePath(root, file); Matcher matcher = pattern.matcher(path); if (matcher.matches()) return file.toURL(); List children = file.getChildren(); for (VirtualFile child : children) { URL url = findURL(root, child, pattern); if (url != null) return url; } return null; } catch (Exception e) { throw new RuntimeException(e); } } public void getResources(String name, Set urls) throws IOException { Pattern pattern = createPattern(name); for (VirtualFile root : roots) { RegexpVisitor visitor = new RegexpVisitor(root, pattern); root.visit(visitor); urls.addAll(visitor.getUrls()); } } private static class RegexpVisitor implements VirtualFileVisitor { private VirtualFile root; private Pattern pattern; private Set urls = new HashSet(); private RegexpVisitor(VirtualFile root, Pattern pattern) { this.root = root; this.pattern = pattern; } public VisitorAttributes getAttributes() { return VisitorAttributes.RECURSE_LEAVES_ONLY; } public void visit(VirtualFile file) { try { String path = AbstractStructureDeployer.getRelativePath(root, file); Matcher matcher = pattern.matcher(path); if (matcher.matches()) urls.add(file.toURL()); } catch (Exception e) { throw new RuntimeException(e); } } public Set getUrls() { return urls; } } } RegexpClassLoaderPolicy uses a simplistic mechanism to find matching resources. Real-world implementations would be more comprehensive and elegant. public class RegexpService extends PrintService { public void start() throws Exception { System.out.println(); ClassLoader cl = getClass().getClassLoader(); Enumeration urls = cl.getResources("config/[^.]+\.[^.]{1,4}"); while (urls.hasMoreElements()) { URL url = urls.nextElement(); print(url.openStream(), url.toExternalForm()); } } } The regexp service uses the regular expression pattern config/[^.]+\.[^.]{1,4} to list resources under the config// directory. The suffix length is limited, such that file names such as excluded.properties will be ignored.