import java.util.HashMap; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.io.BufferedReader; import java.io.PrintWriter; import java.io.FileWriter; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.IOException; import java.net.URL; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; public class Group extends Thread { private static final HashMap KNOWN_GROUPS; private final HashMap class_files; private final String name; private final String abbreviation; private final String[] url; private final Group.Type[] type; static { KNOWN_GROUPS = new HashMap(); } private Group ( final String name, final String abbreviation, final String[] types_and_urls ) { final int sources; int j; sources = (types_and_urls.length / 2); this.name = name; this.abbreviation = abbreviation; url = new String[sources]; type = new Group.Type[sources]; for (int i = 0; i < sources; ++i) { j = (i * 2); type[i] = Type.get(types_and_urls[j]); url[i] = types_and_urls[j + 1]; } class_files = new HashMap(); } private void register () throws Group.AlreadyRegisteredException { if (KNOWN_GROUPS.containsKey(abbreviation)) { throw (new Group.AlreadyRegisteredException()); } KNOWN_GROUPS.put(abbreviation, this); } public String get_abbreviation () { return abbreviation; } public void add_event (final Event event) { final PrintWriter pw; pw = class_files.get ( Classes.abbreviation_from_name ( event.get_name(), false ) ); pw.println(event.toString()); pw.flush(); } public void add_ICS_fragment ( final String fragment, final String class_name, final boolean lazy ) { final PrintWriter pw; pw = class_files.get ( Classes.abbreviation_from_name(class_name, lazy) ); // Escapes all ',' or ';' not directly preceded by '\'. // That's quite an inefficient way to do it btw. pw.print ( fragment.replaceAll ( "(?= 4 && ((data.length % 2) == 0)) { new_group = new Group ( data[0], data[1], Arrays.copyOfRange(data, 2, data.length) ); try { new_group.register(); } catch (final Group.AlreadyRegisteredException e) { final StringBuilder sb; sb = new StringBuilder(); sb.append("Duplicate group entry for group \""); sb.append(new_group.name); sb.append("\"."); Error.ERROR.from_file ( Parameters.get_groups_filename(), sb.toString() ); continue; } } else { final StringBuilder sb; sb = new StringBuilder(); sb.append("Invalid group entry: \""); sb.append(input_line); sb.append("\"."); Error.ERROR.from_file ( Parameters.get_groups_filename(), sb.toString() ); continue; } } } catch (final Exception e) { Error.FATAL.from_file ( Parameters.get_groups_filename(), "Error while reading file:", e.getMessage() ); if (br != null) { try { br.close(); } catch (final Exception e2) { Error.WARNING.from_file ( Parameters.get_groups_filename(), "Error while closing file:", e2.getMessage() ); } } return; } try { br.close(); } catch (final Exception e) { Error.WARNING.from_file ( Parameters.get_groups_filename(), "Error while closing file:", e.getMessage() ); } } /** * Creates Group threads (one per group) to translate each XML file. * For performance reasons, we limit the number of threads running * concurrently at a give time (also, I'm on shared hosting and the task * doesn't actually need to be very fast so I avoid being too greedy). **/ public static void run_all () { final ExecutorService exec; final List> groups; groups = new ArrayList>(); exec = Executors.newFixedThreadPool(Parameters.get_max_threads()); for (final Group g: KNOWN_GROUPS.values()) { groups.add(Executors.callable(g)); } /** This won't return until all is done. **/ try { exec.invokeAll(groups); } catch (final InterruptedException ie) { Error.FATAL.from_thread("main", "Interrupted before the end."); } exec.shutdown(); } private static class AlreadyRegisteredException extends Exception {} }