package net.ME1312.SubServers.Host.Library; import net.ME1312.Galaxi.Library.Util; import java.io.*; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.regex.Pattern; /** * File Replacement Scanner */ public class ReplacementScanner { private final Map replacements = new LinkedHashMap<>(); public ReplacementScanner(Map replacements) { TreeMap> order = new TreeMap>(Comparator.reverseOrder()); for (String key : replacements.keySet()) { int length = key.length(); if (!order.keySet().contains(length)) order.put(length, new LinkedList<>()); order.get(length).add(key); } for (Integer length : order.keySet()) { for (String key : order.get(length)) { this.replacements.put(key, replacements.get(key)); } } } /** * Get the replacements * * @return Replacement Map */ public Map getReplacements() { return new HashMap<>(replacements); } /** * Make replacements in a File or Directory * * @param dir File or Directory * @param whitelist File Whitelist */ public void replace(File dir, String... whitelist) throws IOException { List files; try { files = Util.reflect(Util.class.getDeclaredMethod("zipsearch", File.class, File.class), null, dir, dir); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new IllegalStateException("Cannot access zipsearch()", e); } LinkedHashMap rules = new LinkedHashMap(); for (String entry : whitelist) { boolean mode = !entry.startsWith("!"); if (!mode) entry = entry.substring(1); if (entry.startsWith(".")) entry = entry.substring(1); StringBuilder rule = new StringBuilder(); if (entry.startsWith("**")) { entry = entry.substring(2); rule.append("^.*"); } else if (entry.startsWith("/")) { rule.append("^"); } boolean greedyEnding = false; if (entry.endsWith("**")) { entry = entry.substring(0, entry.length() - 2); greedyEnding = true; } else if (entry.endsWith("/")) { greedyEnding = true; } StringBuilder literal = new StringBuilder(); for (PrimitiveIterator.OfInt i = entry.codePoints().iterator(); i.hasNext(); ) { int c = i.next(); if ((c == '*' || c == '?' || c == '[') && literal.length() > 0) { rule.append(Pattern.quote(literal.toString())); literal = new StringBuilder(); } switch (c) { case '\\': if (i.hasNext()) c = i.next(); literal.appendCodePoint(c); case '[': for (boolean escaped = false; i.hasNext() && (c != ']' || escaped); c = i.next()) { if (c == '\\') escaped = !escaped; else escaped = false; literal.appendCodePoint(c); } if (c == ']' && literal.length() > 1) { literal.appendCodePoint(c); rule.append(literal.toString()); } literal = new StringBuilder(); break; case '*': rule.append("[^/]+"); break; case '?': rule.append("[^/]"); break; default: literal.appendCodePoint(c); break; } } if (literal.length() > 0) rule.append(Pattern.quote(literal.toString())); if (greedyEnding) rule.append(".*"); rule.append("$"); rules.put(Pattern.compile(rule.toString()), mode); } for (String file : files) { boolean act = false; for (Map.Entry rule : rules.entrySet()) { if (rule.getKey().matcher('/' + file.replace(File.separatorChar, '/')).find()) act = rule.getValue(); } if (act) replaceFile(new File(dir, file)); } } private void replaceFile(File file) throws IOException { FileInputStream stream = new FileInputStream(file); String string = Util.readAll(new InputStreamReader(stream)); stream.close(); for (Map.Entry replacement : replacements.entrySet()) string = string.replace("SubServers::" + replacement.getKey(), replacement.getValue()); FileWriter writer = new FileWriter(file, false); writer.write(string); writer.close(); } /** * Make replacements in an Object * * @param value Map, Collection, Array, or String * @return Object with replaced variables */ public Object replace(Object value) { if (value instanceof Map) { List list = new ArrayList(); list.addAll(((Map) value).keySet()); for (String key : list) ((Map) value).put(key, replace(((Map) value).get(key))); return value; } else if (value instanceof Collection) { List list = new ArrayList(); for (Object val : (Collection) value) list.add(replace(val)); return list; } else if (value.getClass().isArray()) { List list = new ArrayList(); for (int i = 0; i < ((Object[]) value).length; i++) list.add(replace(((Object[]) value)[i])); return list; } else if (value instanceof String) { return replaceObj((String) value); } else { return value; } } private String replaceObj(String string) { for (Map.Entry replacement : replacements.entrySet()) string = string.replace('$' + replacement.getKey() + '$', replacement.getValue()); return string; } }