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