package com.nominanuda.springsoy; import static com.nominanuda.zen.io.Uris.URIS; import static com.nominanuda.zen.oio.OioUtils.IO; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import java.util.function.Function; import java.util.jar.JarEntry; import java.util.jar.JarFile; import com.google.template.soy.SoyFileSet.Builder; import com.nominanuda.zen.common.Tuple2; public class JarSoySource extends SoySource { private final List<String> templatesLocations = new ArrayList<>(); public JarSoySource(String... baseTemplatesLocations) { setTemplatesLocations(baseTemplatesLocations); } public JarSoySource() { } @Override protected void cumulate(Builder builder, List<String> jsTplNames) throws IOException { List<Tuple2<String, String>> templateFileUrls = new LinkedList<Tuple2<String,String>>(); for (String templatesLocation : templatesLocations) { List<Tuple2<String, String>> entries = getEntries(templatesLocation, new Function<String, Boolean>() { public Boolean apply(String param) { return param.endsWith(".soy"); } }); if (null != entries) { templateFileUrls.addAll(entries); } } for (Tuple2<String, String> templateFile : templateFileUrls) { builder.add(templateFile.get1(), templateFile.get0()); jsTplNames.add(templateFile.get0()); //jsTplNames.add(IO.getLastPathSegment(templateFile.get0())); } } private List<Tuple2<String, String>> getEntries(String jarOrFileSrcDir, Function<String,Boolean> namePredicate) throws IOException { ClassLoader cl = Thread.currentThread().getContextClassLoader(); URL r = cl.getResource(jarOrFileSrcDir); if (null != r) { String dirUrl = r.getFile(); if (dirUrl.contains("!")) { return getJarEntries(dirUrl, namePredicate); } else { dirUrl = new File(dirUrl).getAbsolutePath(); // to compute the right length on win systems int prefixLength = dirUrl.length() - jarOrFileSrcDir.length(); return getDirEntries(prefixLength, dirUrl, namePredicate); } } else { log.warn("no url for this src: " + jarOrFileSrcDir); return null; } } private List<Tuple2<String, String>> getDirEntries(int prefixLength, String srcDir, final Function<String,Boolean> namePredicate) throws IOException { File dir = new File(srcDir); String[] files = dir.list(new FilenameFilter() { public boolean accept(File dir, String name) { return namePredicate.apply(name); } }); String[] dirs= dir.list(new FilenameFilter() { public boolean accept(File dir, String name) { return new File(dir, name).isDirectory(); } }); LinkedList<Tuple2<String, String>> l = new LinkedList<Tuple2<String,String>>(); for (String f : files) { String filename = URIS.pathJoin(dir.getAbsolutePath(), f).replace("\\", "/"); // for win systems l.add(new Tuple2<String, String>(filename.substring(prefixLength), IO.readAndCloseUtf8(new FileInputStream(new File(filename))))); } for (String d : dirs) { l.addAll(getDirEntries(prefixLength, URIS.pathJoin(srcDir, d), namePredicate)); } return l; } private List<Tuple2<String, String>> getJarEntries(String jarSrcDir, Function<String,Boolean> namePredicate) throws IOException { List<Tuple2<String, String>> result = new LinkedList<Tuple2<String, String>>(); String[] arr = jarSrcDir.substring("file:".length()).split("!"); String jarPath = arr[0]; String dirPathInJar = arr[1].substring(1) + "/"; //int dirPathInJarLen = dirPathInJar.length(); File f = new File(jarPath); JarFile jf = new JarFile(f); Enumeration<JarEntry> entries = jf.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String entryName = entry.getName(); if (entryName.startsWith(dirPathInJar) && !dirPathInJar.equals(entryName)) { //String subResource = entryName.substring(dirPathInJarLen); if(namePredicate.apply(entryName)) { result.add(new Tuple2<String, String>(entryName, IO.readAndCloseUtf8(jf.getInputStream(entry)))); } } } jf.close(); return result; } /* setters */ public void setTemplatesLocations(String... templatesLocation) { this.templatesLocations.addAll(Arrays.asList(templatesLocation)); } }