View Javadoc

1   package org.paneris.bibliomania;
2   
3   import java.io.OutputStreamWriter;
4   import java.io.Writer;
5   import java.util.Enumeration;
6   
7   import org.melati.LogicalDatabase;
8   import org.melati.Melati;
9   import org.melati.poem.AccessToken;
10  import org.melati.poem.PoemTask;
11  import org.melati.poem.PoemThread;
12  import org.melati.poem.Table;
13  import org.melati.poem.UnexpectedExceptionPoemException;
14  import org.melati.poem.util.ArrayUtils;
15  import org.melati.poem.util.ConsEnumeration;
16  import org.melati.poem.util.FlattenedEnumeration;
17  import org.melati.poem.util.MappedEnumeration;
18  import org.melati.util.MelatiRuntimeException;
19  import org.webmacro.servlet.WebContext;
20  
21  public class BatchImporter extends BibliomaniaServlet {
22    private static final long serialVersionUID = 6162775496346853625L;
23  
24    public static final int KEYDOTTXT = 8, PAGINATE = 4, INDEX = 2, ENCACHE = 1;
25  
26    public static class Result {
27      public Exception trouble;
28      public Unit unit;
29    }
30  /*
31    private static final class Stopwatch {
32      public long datum;
33  
34      public Stopwatch() {
35        datum = System.currentTimeMillis();
36      }
37  
38      public long click() {
39        long now = System.currentTimeMillis();
40        try {
41          return now - datum;
42        } finally {
43          datum = now;
44        }
45      }
46    }
47  */
48    public static Enumeration<Result> importResults(
49      final Unit unit,
50      final boolean recurse,
51      final int actions,
52      final boolean doChapters,
53      final boolean flushDuring) {
54  
55      Result result = new Result();
56      result.unit = unit;
57  
58      try {
59        if ((actions & KEYDOTTXT) != 0)
60          unit.readKeyDotTxt();
61  
62        if ((actions & PAGINATE) != 0) {
63          unit.paginate();
64          unit.getBibliomaniaDatabase().pagination().flush();
65        }
66  
67        if ((actions & ENCACHE) != 0)
68          unit.encache();
69  
70        if ((actions & INDEX) != 0) {
71          try {
72            unit.index();
73          } finally {
74            // FIXME there are two of these but we shouldn't have to know that
75            // here
76  
77            if (flushDuring) {
78              unit.getBibliomaniaDatabase().fti().flush();
79              unit.getBibliomaniaDatabase().infoFTI().flush();
80            }
81          }
82        }
83  
84        PoemThread.commit();
85      } catch (Exception e) {
86        e.printStackTrace();
87        result.trouble = e;
88        PoemThread.rollback();
89      }
90  
91      return new ConsEnumeration<Result>(
92        result,
93        recurse
94          && !(unit instanceof Book && !doChapters)
95            ? new FlattenedEnumeration<Result>(
96                new MappedEnumeration<Enumeration<Result>,Unit>(
97              unit.getMembersSlowly()) {
98        public Enumeration<Result> mapped(Unit member) {
99          return importResults(
100           member,
101           recurse,
102           actions,
103           doChapters,
104           flushDuring);
105       }
106     }) : null);
107   }
108 
109   protected String bibliomaniaHandle(Melati melati, WebContext context)
110     throws Exception {
111     melati.setBufferingOff();
112     melati.setFlushingOn();
113     melati.setPassbackExceptionHandling();
114 
115     context.put(
116       "results",
117       importResults(
118         (Unit)melati.getObject(),
119         "true".equals(context.getForm("recurse")),
120         Integer.parseInt(context.getForm("actions")),
121         !"true".equals(context.getForm("skipChaps")),
122         true));
123 
124     return bibliomaniaTemplate("admin/BatchImport");
125   }
126 
127   private static void doImport(
128     BibliomaniaDatabase db,
129     String[] args,
130     final Writer commentary)
131     throws Exception {
132     final boolean recurse, skipChaps;
133 
134     if (args[1].equals("recurse")) {
135       recurse = true;
136       skipChaps = false;
137     } else if (args[1].equals("skipChaps")) {
138       recurse = true;
139       skipChaps = true;
140     } else if (args[1].equals("norecurse")) {
141       recurse = false;
142       skipChaps = false;
143     } else
144       throw new IllegalArgumentException("second arg must be norecurse, recurse or skipChaps");
145 
146     final boolean flushDuring;
147 
148     if (args.length > 4) {
149       if (args[4].equals("flushDuring"))
150         flushDuring = true;
151       else if (args[4].equals("flushAfter"))
152         flushDuring = false;
153       else
154         throw new IllegalArgumentException("fifth arg must be flushDuring or flushAfter");
155     } else
156       flushDuring = true;
157 
158     final int actions = Integer.parseInt(args[0]);
159 
160     @SuppressWarnings("unchecked")
161     Table<Unit> table = (Table<Unit>)db.getTable(args[2]);
162 
163     Enumeration<Result> results;
164 
165     if (args[3].equals("_"))
166       results =
167         new FlattenedEnumeration<Result>(
168             new MappedEnumeration<Enumeration<Result>, Unit>(table.selection()) {
169       public Enumeration<Result> mapped(Unit member) {
170         return importResults(
171           member,
172           recurse,
173           actions,
174           !skipChaps,
175           flushDuring);
176       }
177     });
178     else
179       results =
180         importResults(
181           (Unit)table.getObject(Integer.parseInt(args[3])),
182           recurse,
183           actions,
184           !skipChaps,
185           flushDuring);
186 
187     while (results.hasMoreElements()) {
188       Result result = (Result)results.nextElement();
189       commentary.write(
190         "=== ... finished "
191           + result.unit.getTable().getName()
192           + "/"
193           + result.unit.getTroid()
194           + " `"
195           + result.unit.getPath());
196       if (result.unit instanceof Chapter)
197         commentary.write(((Chapter)result.unit).getFilename());
198       commentary.write("'\n\n");
199 
200       if (result.trouble != null)
201         commentary.write("!!! " + result.trouble + "\n");
202       commentary.flush();
203     }
204 
205     if (!flushDuring) {
206       long now = System.currentTimeMillis();
207 
208       // FIXME there are two of these but we shouldn't have to know that here
209       db.fti().flush();
210       db.infoFTI().flush();
211 
212       commentary.write(
213         "... final flush millis " + (System.currentTimeMillis() - now) + "\n");
214       commentary.flush();
215 
216     }
217   }
218 
219   public static void main(final String[] args) {
220     final BibliomaniaDatabase db = new BibliomaniaDatabase(false);
221     db.connect("bibliomania",
222       "org.paneris.bibliomania.poem.dbms.Postgresql",
223       "jdbc:postgresql:bibliomania",
224       "postgres",
225       "*",
226       8);
227 
228     db.inSession(AccessToken.root, // FIXME
229     new PoemTask() {
230       public void run() {
231         try {
232           doImport(db, args, new OutputStreamWriter(System.err));
233         } catch (Exception e) {
234           throw new UnexpectedExceptionPoemException(e);
235         }
236       }
237     });
238   }
239 
240   public static class Interpreter implements CommandServer.Interpreter {
241 
242     public static class AuthenticationException
243       extends MelatiRuntimeException {
244       public String getMessage() {
245         return "Authentication failed";
246       }
247     }
248 
249     /**
250      * expecting a command line something like 
251      * org.paneris.bibliomania.BatchImporter$Interpreter bibliomania _administrator_ password 1 recurse book 117
252      * @see org.paneris.bibliomania.CommandServer.Interpreter#interpret(java.lang.String[], java.io.Writer, java.io.Writer)
253      */
254     public void interpret(
255       final String[] args,
256       final Writer output,
257       final Writer errors)
258       throws Exception {
259 
260       final BibliomaniaDatabase db =
261         (BibliomaniaDatabase)LogicalDatabase.getDatabase(args[0]);
262 
263       db.inSession(AccessToken.root, new PoemTask() {
264         public void run() {
265           try {
266             User user =
267               (User)PoemThread
268                 .database()
269                 .getUserTable()
270                 .getLoginColumn()
271                 .firstWhereEq(
272                 args[1]);
273             if (user == null || !user.getPassword_unsafe().equals(args[2]))
274               throw new AuthenticationException();
275 
276             PoemThread.setAccessToken(user);
277 
278             doImport(
279               db,
280               (String[])ArrayUtils.section(args, 3, args.length),
281               errors);
282           } catch (Exception e) {
283             try {
284               errors.write(e + "\n");
285             } catch (Exception ee) {
286             }
287           }
288         }
289       });
290     }
291   }
292 }