Project

General

Profile

1 51 jones
/**
2 203 jones
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6 361 berkley
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7 348 jones
 *    Release: @release@
8 154 jones
 *
9 203 jones
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 51 jones
 */
13
14
package edu.ucsb.nceas.metacat;
15
16 46 jones
import java.io.PrintWriter;
17
import java.io.IOException;
18 50 jones
import java.io.Reader;
19
import java.io.StringReader;
20 59 jones
import java.io.BufferedReader;
21 185 jones
import java.io.File;
22
import java.io.FileInputStream;
23 458 berkley
import java.io.FileOutputStream;
24
import java.io.InputStreamReader;
25 453 berkley
import java.io.DataInputStream;
26 46 jones
import java.util.Enumeration;
27
import java.util.Hashtable;
28 341 berkley
import java.util.ResourceBundle;
29 82 jones
import java.util.PropertyResourceBundle;
30 50 jones
import java.net.URL;
31
import java.net.MalformedURLException;
32 85 jones
import java.sql.PreparedStatement;
33
import java.sql.ResultSet;
34 50 jones
import java.sql.Connection;
35 55 jones
import java.sql.SQLException;
36 361 berkley
import java.lang.reflect.*;
37 453 berkley
import java.net.*;
38 458 berkley
import java.util.zip.*;
39 46 jones
40
import javax.servlet.ServletConfig;
41
import javax.servlet.ServletContext;
42
import javax.servlet.ServletException;
43 48 jones
import javax.servlet.ServletInputStream;
44 46 jones
import javax.servlet.http.HttpServlet;
45
import javax.servlet.http.HttpServletRequest;
46
import javax.servlet.http.HttpServletResponse;
47 210 bojilova
import javax.servlet.http.HttpSession;
48 47 jones
import javax.servlet.http.HttpUtils;
49 458 berkley
import javax.servlet.ServletOutputStream;
50 46 jones
51 50 jones
import oracle.xml.parser.v2.XSLStylesheet;
52
import oracle.xml.parser.v2.XSLException;
53
import oracle.xml.parser.v2.XMLDocumentFragment;
54
import oracle.xml.parser.v2.XSLProcessor;
55
56 204 jones
import org.xml.sax.SAXException;
57
58 46 jones
/**
59
 * A metadata catalog server implemented as a Java Servlet
60 154 jones
 *
61
 * <p>Valid parameters are:<br>
62
 * action=query -- query the values of all elements and attributes
63
 *                     and return a result set of nodes<br>
64 205 jones
 * action=squery -- structured query (see pathquery.dtd)<br>
65
 * action=insert -- insert an XML document into the database store<br>
66
 * action=update -- update an XML document that is in the database store<br>
67
 * action=delete --  delete an XML document from the database store<br>
68
 * action=validate -- vallidate the xml contained in valtext<br>
69
 * action=getdocument -- display an XML document in XML or HTML<br>
70
 * doctype -- document type list returned by the query (publicID)<br>
71 154 jones
 * qformat=xml -- display resultset from query in XML<br>
72
 * qformat=html -- display resultset from query in HTML<br>
73
 * docid=34 -- display the document with the document ID number 34<br>
74 205 jones
 * doctext -- XML text of the document to load into the database<br>
75 183 jones
 * query -- actual query text (to go with 'action=query' or 'action=squery')<br>
76 205 jones
 * valtext -- XML text to be validated<br>
77
 * action=getdatadoc -- retreive a stored datadocument<br>
78 302 bojilova
 * action=getdoctypes -- retreive all doctypes (publicID)<br>
79
 * action=getdataguide -- retreive a Data Guide<br>
80 205 jones
 * datadoc -- data document name (id)<br>
81
 * <p>
82
 * The particular combination of parameters that are valid for each
83
 * particular action value is quite specific.  This documentation
84
 * will be reorganized to reflect this information.
85 46 jones
 */
86
public class MetaCatServlet extends HttpServlet {
87
88 370 berkley
  private ServletConfig config = null;
89
  private ServletContext context = null;
90
  private Hashtable connectionPool = new Hashtable();
91
  private String resultStyleURL = null;
92
  private String xmlcatalogfile = null;
93
  private String saxparser = null;
94
  private String defaultdatapath = null;
95
  private String servletpath = null;
96 380 jones
  private PropertyResourceBundle options = null;
97
  private MetaCatUtil util = null;
98
99
  // path to directory where data files
100
  // that can be downloaded will be stored
101 370 berkley
  private String htmlpath = null;
102 380 jones
  // script to get data file and put it
103
  // in defaultdocpath dir
104 370 berkley
  private String executescript  = null;
105 46 jones
106 50 jones
  /**
107
   * Initialize the servlet by creating appropriate database connections
108
   */
109 46 jones
  public void init( ServletConfig config ) throws ServletException {
110
    try {
111
      super.init( config );
112
      this.config = config;
113 332 bojilova
      this.context = config.getServletContext();
114 184 jones
      System.out.println("MetaCatServlet Initialize");
115 82 jones
116 184 jones
      util = new MetaCatUtil();
117
118 83 jones
      // Get the configuration file information
119 184 jones
      resultStyleURL = util.getOption("resultStyleURL");
120
      xmlcatalogfile = util.getOption("xmlcatalogfile");
121
      saxparser = util.getOption("saxparser");
122
      defaultdatapath = util.getOption("defaultdatapath");
123
      executescript = util.getOption("executescript");
124 360 bojilova
      servletpath = util.getOption("servletpath");
125
      htmlpath = util.getOption("htmlpath");
126 82 jones
127 46 jones
      try {
128 309 bojilova
        // Open a pool of db connections
129
        connectionPool = util.getConnectionPool();
130
      } catch (Exception e) {
131
        System.err.println("Error creating pool of database connections");
132
        System.err.println(e.getMessage());
133
      }
134 46 jones
    } catch ( ServletException ex ) {
135
      throw ex;
136
    }
137
  }
138
139 320 bojilova
  /**
140
   * Close all db connections from the pool
141
   */
142
  public void destroy() {
143
144
    if (util != null) {
145
        util.closeConnections();
146
    }
147
  }
148
149 50 jones
  /** Handle "GET" method requests from HTTP clients */
150 46 jones
  public void doGet (HttpServletRequest request, HttpServletResponse response)
151
    throws ServletException, IOException {
152
153 48 jones
    // Process the data and send back the response
154 59 jones
    handleGetOrPost(request, response);
155 48 jones
  }
156
157 50 jones
  /** Handle "POST" method requests from HTTP clients */
158 48 jones
  public void doPost( HttpServletRequest request, HttpServletResponse response)
159
    throws ServletException, IOException {
160
161
    // Process the data and send back the response
162 59 jones
    handleGetOrPost(request, response);
163 48 jones
  }
164
165 49 jones
  /**
166 50 jones
   * Control servlet response depending on the action parameter specified
167 49 jones
   */
168 382 berkley
  private void handleGetOrPost(HttpServletRequest request,
169 59 jones
    HttpServletResponse response)
170 355 berkley
    throws ServletException, IOException
171
 {
172 48 jones
173 309 bojilova
    if ( util == null ) {
174
        util = new MetaCatUtil();
175
    }
176
    if ( connectionPool == null ) {
177
      try {
178
        // Open a pool of db connections
179
        connectionPool = util.getConnectionPool();
180
      } catch (Exception e) {
181
        System.err.println("Error creating pool of database connections");
182
        System.err.println(e.getMessage());
183
      }
184
    }
185 49 jones
    // Get a handle to the output stream back to the client
186 458 berkley
    //PrintWriter out = response.getWriter();
187 102 jones
    //response.setContentType("text/html");
188 49 jones
189 59 jones
    String name = null;
190
    String[] value = null;
191 103 jones
    String[] docid = new String[3];
192 59 jones
    Hashtable params = new Hashtable();
193
    Enumeration paramlist = request.getParameterNames();
194
    while (paramlist.hasMoreElements()) {
195
      name = (String)paramlist.nextElement();
196
      value = request.getParameterValues(name);
197 103 jones
198
      // Decode the docid and mouse click information
199
      if (name.endsWith(".y")) {
200
        docid[0] = name.substring(0,name.length()-2);
201
        //out.println("docid => " + docid[0]);
202
        params.put("docid", docid);
203
        name = "ypos";
204
      }
205
      if (name.endsWith(".x")) {
206
        name = "xpos";
207 373 berkley
      }
208 103 jones
209 102 jones
      //out.println(name + " => " + value[0]);
210 373 berkley
      params.put(name,value);
211
    }
212 355 berkley
213 505 jones
    String action = ((String[])params.get("action"))[0];
214
    util.debugMessage("Line 213: Action is: " + action);
215 355 berkley
    //if the user clicked on the input images, decode which image
216
    //was clicked then set the action.
217 505 jones
    //MBJELIMINATE String action = decodeMouseAction(params);
218
    //if(action.equals("error"))
219
    //{
220
     // util.debugMessage("Line 218: Action is: " + action);
221
      //action = ((String[])params.get("action"))[0];
222
    //}
223 355 berkley
224 380 jones
    // This block handles session management for the servlet
225
    // by looking up the current session information for all actions
226
    // other than "Login" and "Logout"
227 210 bojilova
    // handle login action
228 425 bojilova
    String username = null;
229
    String groupname = null;
230 297 bojilova
    if (action.equals("Login") || action.equals("Login Client")) {
231 458 berkley
      handleLoginAction(response.getWriter(), params, request, response);
232 210 bojilova
    // handle logout action
233 345 bojilova
    } else if (action.equals("Logout") || action.equals("Logout Client")) {
234 210 bojilova
      HttpSession sess = request.getSession(false);
235 251 bojilova
      if (sess != null) { sess.invalidate();  }
236 345 bojilova
      if (action.equals("Logout Client")) {
237 458 berkley
        PrintWriter out = response.getWriter();
238 345 bojilova
        out.println("<?xml version=\"1.0\"?>");
239
        out.println("<success>");
240
        out.println("User logout.");
241
        out.println("</success>");
242
        return;
243
      }
244 361 berkley
245 360 bojilova
      response.sendRedirect(htmlpath + "/index.html");
246 361 berkley
247 251 bojilova
    // aware of session expiration on every request
248 343 jones
    } else {
249 332 bojilova
      HttpSession sess = request.getSession(true);
250
      if (sess.isNew()) {
251 251 bojilova
        // session expired or has not been stored b/w user requests
252 328 bojilova
        // redirect to default page for query only access
253 441 bojilova
        //  response.sendRedirect(htmlpath + "/sexpire.html");
254
        username = "public";
255 425 bojilova
      } else {
256
        username = (String)sess.getAttribute("username");
257
        groupname = (String)sess.getAttribute("groupname");
258
      }
259 210 bojilova
    }
260 219 jones
261 380 jones
    // Now that we know the session is valid, we can delegate the request
262
    // to a particular action handler
263 361 berkley
    if(action.equals("query"))
264
    {
265 458 berkley
      handleQuery(response.getWriter(), params, response, username, groupname);
266 373 berkley
    }
267 371 berkley
    else if(action.equals("squery"))
268 361 berkley
    {
269 373 berkley
      if(params.containsKey("query"))
270
      {
271 458 berkley
        handleSQuery(response.getWriter(), params, response, username, groupname);
272 373 berkley
      }
273
      else
274
      {
275 458 berkley
        PrintWriter out = response.getWriter();
276 373 berkley
        out.println("Illegal action squery without \"query\" parameter");
277
      }
278
    }
279 361 berkley
    else if (action.equals("getdocument")) {
280 458 berkley
      PrintWriter out = response.getWriter();
281 87 jones
      try {
282
        handleGetDocumentAction(out, params, response);
283
      } catch (ClassNotFoundException e) {
284 103 jones
        out.println(e.getMessage());
285 87 jones
      } catch (SQLException se) {
286 103 jones
        out.println(se.getMessage());
287 87 jones
      }
288 453 berkley
    }
289
    else if (action.equals("getrelateddocument")) {
290 458 berkley
      PrintWriter out = response.getWriter();
291 453 berkley
      try {
292
        handleGetRelatedDocumentAction(out, params, response);
293
      } catch (ClassNotFoundException e) {
294
        out.println(e.getMessage());
295
      } catch (SQLException se) {
296
        out.println(se.getMessage());
297
      }
298
    }
299
    else if (action.equals("insert") || action.equals("update")) {
300 458 berkley
      PrintWriter out = response.getWriter();
301 425 bojilova
      if ( !username.equals("public") && (username != null) ) {
302
        handleInsertOrUpdateAction(out, params, response, username, groupname);
303
      } else {
304
        out.println("Permission denied for " + action);
305
      }
306 203 jones
    } else if (action.equals("delete")) {
307 458 berkley
      PrintWriter out = response.getWriter();
308 425 bojilova
      if ( !username.equals("public") && (username != null) ) {
309
        handleDeleteAction(out, params, response, username, groupname);
310
      } else {
311
        out.println("Permission denied for " + action);
312
      }
313 68 higgins
    } else if (action.equals("validate")) {
314 458 berkley
      PrintWriter out = response.getWriter();
315 437 berkley
      handleValidateAction(out, params, response);
316
    } else if (action.equals("getabstract")) {
317 458 berkley
      PrintWriter out = response.getWriter();
318 437 berkley
      try{
319
        handleViewAbstractAction(out, params, response);
320
      }
321
      catch(Exception e)
322
      {
323
        out.println("error viewing abstract: " + e.getMessage());
324
      }
325 91 higgins
    } else if (action.equals("getdatadoc")) {
326 458 berkley
      response.setContentType("application/zip");
327
      ServletOutputStream out = response.getOutputStream();
328 91 higgins
      handleGetDataDocumentAction(out, params, response);
329 302 bojilova
    } else if (action.equals("getdoctypes")) {
330 458 berkley
      PrintWriter out = response.getWriter();
331 302 bojilova
      handleGetDoctypesAction(out, params, response);
332
    } else if (action.equals("getdataguide")) {
333 458 berkley
      PrintWriter out = response.getWriter();
334 302 bojilova
      handleGetDataGuideAction(out, params, response);
335 297 bojilova
    } else if (action.equals("Login") || action.equals("Login Client")) {
336 50 jones
    } else {
337 458 berkley
      PrintWriter out = response.getWriter();
338 50 jones
      out.println("Error: action not registered.  Please report this error.");
339 46 jones
    }
340 465 berkley
    util.closeConnections();
341 49 jones
    // Close the stream to the client
342 458 berkley
    //out.close();
343 46 jones
  }
344 355 berkley
345
  /**
346
   * decodes the mouse click information coming from the client.
347
   * This function may be overwritten to provide specific functionality
348
   * for different applications.
349
   * @param params the parameters from the CGI
350
   * @return action the action to be performed or "error" if an error was
351
   * generated
352
   */
353 375 berkley
  protected String decodeMouseAction(Hashtable params)
354 355 berkley
  {
355
    // Determine what type of request the user made
356
    // if the action parameter is set, use it as a default
357
    // but if the ypos param is set, calculate the action needed
358
    String action=null;
359
    long ypos = 0;
360
    try {
361
      ypos = (new Long(((String[])params.get("ypos"))[0]).longValue());
362
      //out.println("<P>YPOS IS " + ypos);
363
      if (ypos <= 13) {
364
        action = "getdocument";
365
      } else if (ypos > 13 && ypos <= 27) {
366
        action = "validate";
367
      } else if (ypos > 27) {
368
        action = "transform";
369
      }
370
      return action;
371
    } catch (Exception npe) {
372 380 jones
      //
373
      // MBJ -- NOTE that this should be handled more gracefully with
374
      //        the new exception infrastructure -- this "error" return
375
      //        value is inappropriate
376 355 berkley
      //out.println("<P>Caught exception looking for Y value.");
377
      return "error";
378 382 berkley
    }
379 355 berkley
  }
380 49 jones
381 50 jones
  /**
382 210 bojilova
   * Handle the Login request. Create a new session object.
383 503 bojilova
   * Do user authentication through the session.
384 210 bojilova
   */
385
  private void handleLoginAction(PrintWriter out, Hashtable params,
386
               HttpServletRequest request, HttpServletResponse response) {
387 251 bojilova
388 503 bojilova
    AuthSession sess = null;
389 228 bojilova
    String un = ((String[])params.get("username"))[0];
390
    String pw = ((String[])params.get("password"))[0];
391 297 bojilova
    String action = ((String[])params.get("action"))[0];
392 332 bojilova
393 297 bojilova
    try {
394 503 bojilova
      sess = new AuthSession(request, un, pw);
395 297 bojilova
    } catch (Exception e) {
396
      out.println(e.getMessage());
397
    }
398 411 bojilova
399
    String output = null;
400 503 bojilova
    boolean isValid = sess.authenticate();
401
    if (action.equals("Login Client")) {
402
      out.println(sess.getMessage());
403
    } else {
404
      try {
405
        if (isValid) {
406
          if (un.equals("public")) {
407
            response.sendRedirect(
408
                   response.encodeRedirectUrl(htmlpath + "/index.html"));
409
          } else {
410
            response.sendRedirect(
411
                   response.encodeRedirectUrl(htmlpath + "/metacat.html"));
412
          }
413
        } else {
414
          response.sendRedirect(
415
                   response.encodeRedirectUrl(htmlpath + "/login.html"));
416
        }
417
      } catch ( java.io.IOException ioe) {
418
        String message = "handleLoginAction() - " +
419
                    "Error on redirect of HttpServletResponse: " +
420
                    ioe.getMessage();
421
        out.println(message);
422
      }
423
    }
424 370 berkley
  }
425
426 373 berkley
  /**
427 380 jones
   * Retreive the squery xml, execute it and display it
428
   *
429
   * @param out the output stream to the client
430
   * @param params the Hashtable of parameters that should be included
431
   * in the squery.
432
   * @param response the response object linked to the client
433
   * @param conn the database connection
434
   */
435
  protected void handleSQuery(PrintWriter out, Hashtable params,
436 441 bojilova
                 HttpServletResponse response, String user, String group)
437 373 berkley
  {
438 380 jones
    String xmlquery = ((String[])params.get("query"))[0];
439
    String qformat = ((String[])params.get("qformat"))[0];
440 465 berkley
    String resultdoc = null;
441
    String[] returndoc = null;
442
    if(params.contains("returndoc"))
443
    {
444
      returndoc = (String[])params.get("returndoc");
445
    }
446
447
    Hashtable doclist = runQuery(xmlquery, user, group, returndoc);
448
    //String resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
449 444 berkley
450 465 berkley
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
451
452 380 jones
    //format and transform the results
453
    if(qformat.equals("html")) {
454
      transformResultset(resultdoc, response, out);
455
    } else if(qformat.equals("xml")) {
456
      response.setContentType("text/xml");
457
      out.println(resultdoc);
458
    } else {
459
      out.println("invalid qformat: " + qformat);
460
    }
461 341 berkley
  }
462
463
   /**
464 380 jones
    * Create the xml query, execute it and display the results.
465
    *
466
    * @param out the output stream to the client
467
    * @param params the Hashtable of parameters that should be included
468 370 berkley
    * in the squery.
469 380 jones
    * @param response the response object linked to the client
470 370 berkley
    */
471 375 berkley
  protected void handleQuery(PrintWriter out, Hashtable params,
472 441 bojilova
                 HttpServletResponse response, String user, String group)
473 341 berkley
  {
474 370 berkley
    //create the query and run it
475 465 berkley
    String[] returndoc = null;
476
    if(params.containsKey("returndoc"))
477
    {
478
      returndoc = (String[])params.get("returndoc");
479
    }
480 373 berkley
    String xmlquery = DBQuery.createSQuery(params);
481 465 berkley
    Hashtable doclist = runQuery(xmlquery, user, group, returndoc);
482
    String qformat = ((String[])params.get("qformat"))[0];
483
    String resultdoc = null;
484
485
    resultdoc = createResultDocument(doclist, transformQuery(params));
486 425 bojilova
487 370 berkley
    //format and transform the results
488 380 jones
    if(qformat.equals("html")) {
489 370 berkley
      transformResultset(resultdoc, response, out);
490 380 jones
    } else if(qformat.equals("xml")) {
491 370 berkley
      response.setContentType("text/xml");
492
      out.println(resultdoc);
493 443 berkley
    } else {
494 370 berkley
      out.println("invalid qformat: " + qformat);
495
    }
496 341 berkley
  }
497
498
  /**
499 384 berkley
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
500
   * so it can properly be placed in the <query> tag of the resultset.
501
   * This method is overwritable so that other applications can customize
502
   * the structure of what is in the <query> tag.
503
   *
504
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
505
   */
506
  protected String transformQuery(Hashtable params)
507
  {
508
    //DBQuery.createSQuery is a re-calling of a previously called
509
    //function but it is necessary
510
    //so that overriding methods have access to the params hashtable
511
    String xmlquery = DBQuery.createSQuery(params);
512
    //the <?xml version="1.0"?> tag is the first 22 characters of the
513
    xmlquery = xmlquery.trim();
514
    int index = xmlquery.indexOf("?>");
515
    return xmlquery.substring(index + 2, xmlquery.length());
516
  }
517
518
  /**
519 443 berkley
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
520
   * string as a param instead of a hashtable.
521
   *
522
   * @param xmlquery a string representing a query.
523
   */
524
  protected String transformQuery(String xmlquery)
525
  {
526
    xmlquery = xmlquery.trim();
527
    int index = xmlquery.indexOf("?>");
528
    return xmlquery.substring(index + 2, xmlquery.length());
529
  }
530
531
  /**
532 380 jones
   * Run the query and return a hashtable of results.
533
   *
534
   * @param xmlquery the query to run
535
   */
536 465 berkley
  private Hashtable runQuery(String xmlquery, String user, String group,
537
                             String[] returndoc)
538 341 berkley
  {
539
    Hashtable doclist=null;
540
    Connection conn = null;
541
    try
542
    {
543 441 bojilova
      conn = util.getConnection();
544
      DBQuery queryobj = new DBQuery(conn, saxparser);
545 465 berkley
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,group,
546
                                       returndoc);
547 441 bojilova
      util.returnConnection(conn);
548
      return doclist;
549 341 berkley
    }
550
    catch (Exception e)
551
    {
552 441 bojilova
      util.returnConnection(conn);
553 341 berkley
      util.debugMessage("Error in runQuery: " + e.getMessage());
554
      doclist = null;
555
      return doclist;
556
    }
557
  }
558
559 380 jones
  /**
560 370 berkley
   * Transorms an xml resultset document to html and sends it to the browser
561 380 jones
   *
562 370 berkley
   * @param resultdoc the string representation of the document that needs
563
   * to be transformed.
564
   * @param response the HttpServletResponse object bound to the client.
565
   * @param out the output stream to the client
566 375 berkley
   */
567
  protected void transformResultset(String resultdoc,
568 380 jones
                                    HttpServletResponse response,
569
                                    PrintWriter out)
570 370 berkley
  {
571
    Connection conn = null;
572 380 jones
    try {
573 370 berkley
      conn = util.getConnection();
574
      DBTransform trans = new DBTransform(conn);
575
      response.setContentType("text/html");
576
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
577
                                 "-//W3C//HTML//EN", out);
578 382 berkley
      util.returnConnection(conn);
579
    }
580
    catch(Exception e)
581
    {
582 441 bojilova
      util.returnConnection(conn);
583 370 berkley
    }
584
  }
585
586 355 berkley
  /**
587
   * Transforms a hashtable of documents to an xml or html result.
588 465 berkley
   * If there is a returndoc, then it only displays documents of
589
   * whatever type returndoc represents.  If a result is found in a document
590
   * that is not of type returndoc then this attempts to find a relation
591
   * between this document and one that satifies the returndoc doctype.
592 380 jones
   *
593 355 berkley
   * @param doclist- the hashtable to transform
594
   * @param xmlquery- the query that returned the dolist result
595 465 berkley
   * @param resultdoc- the document type to backtrack to.
596 355 berkley
   */
597 375 berkley
  protected String createResultDocument(Hashtable doclist, String xmlquery)
598 341 berkley
  {
599
    // Create a buffer to hold the xml result
600
    StringBuffer resultset = new StringBuffer();
601
602 382 berkley
    // Print the resulting root nodes
603 341 berkley
    String docid = null;
604
    String document = null;
605
    resultset.append("<?xml version=\"1.0\"?>\n");
606
    resultset.append("<resultset>\n");
607 465 berkley
608 384 berkley
    resultset.append("  <query>" + xmlquery + "</query>");
609 478 berkley
610
    if(doclist != null)
611 341 berkley
    {
612 478 berkley
      Enumeration doclistkeys = doclist.keys();
613
      while (doclistkeys.hasMoreElements())
614
      {
615
        docid = (String)doclistkeys.nextElement();
616
        document = (String)doclist.get(docid);
617
        resultset.append("  <document>" + document + "</document>");
618
      }
619
    }
620
621 341 berkley
    resultset.append("</resultset>");
622 444 berkley
    //System.out.println(resultset.toString());
623 370 berkley
    return resultset.toString();
624 341 berkley
  }
625 437 berkley
626
  /**
627
   * Handle the request to view the abstract of a document.
628 444 berkley
   * The abstractpath CGI parameter gives the xml path to the abstract
629
   * node.
630 437 berkley
   */
631
  private void handleViewAbstractAction(PrintWriter out, Hashtable params,
632
               HttpServletResponse response) throws IOException, SQLException
633
  {
634
    String abstractpath = null;
635
    String docid = null;
636
    Connection conn = null;
637
    response.setContentType("text/html");
638
    try
639
    {
640
      docid = ((String[])params.get("docid"))[0];
641
      if(params.containsKey("abstractpath"))
642
      {
643 444 berkley
        //the CGI parameter abstractpath holds the path to the abstract
644
        //that should be displayed.
645 437 berkley
        abstractpath = ((String[])params.get("abstractpath"))[0];
646
      }
647
      else
648
      {
649
        out.println("error: no abstractpath parameter");
650
      }
651
      conn = util.getConnection();
652
653
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid, conn);
654
655 444 berkley
      out.println("<html><head><title>Abstract</title></head>");
656
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
657 437 berkley
      for(int i=0; i<abstracts.length; i++)
658
      {
659
        out.println("<p>" + (String)abstracts[i] + "</p>");
660
      }
661
      out.println("</body></html>");
662
    }
663
    catch (IOException ioe)
664
    {
665 444 berkley
       util.debugMessage("error in handlegetabstract: " + ioe.getMessage());
666 437 berkley
    }
667
    catch(SQLException sqle)
668
    {
669 444 berkley
      util.debugMessage("error in handlegetabstract: " + sqle.getMessage());
670 437 berkley
    }
671
    catch(Exception e)
672
    {
673 444 berkley
      util.debugMessage("error in handlegetabstract: " + e.getMessage());
674 437 berkley
    }
675
676
    util.returnConnection(conn);
677
  }
678 181 jones
679 50 jones
  /**
680 453 berkley
   * Handle the database getrelateddocument request and return a XML document,
681
   * possibly transformed from XML into HTML
682
   */
683
  private void handleGetRelatedDocumentAction(PrintWriter out, Hashtable params,
684
               HttpServletResponse response)
685
               throws ClassNotFoundException, IOException, SQLException
686
  {
687
    String docid = null;
688
    Connection conn = null;
689
690
    if(params.containsKey("url"))
691
    {//the identifier for the related document is contained in the URL param
692
      try
693
      {
694
        DocumentImpl xmldoc=null;
695
        metacatURL murl = new metacatURL(((String[])params.get("url"))[0]);
696
        if(murl.getURLType().equals("metacat"))
697
        {//get the document from the database if it is the right type of url
698 473 berkley
          Hashtable murlParams = murl.getHashParams();
699
          if(murlParams.containsKey("docid"))
700 453 berkley
          {//the docid should be first
701 473 berkley
            docid = (String)murlParams.get("docid"); //get the docid value
702 453 berkley
            conn = util.getConnection();
703
            xmldoc = new DocumentImpl(conn, docid);
704 485 berkley
            String qformat = ((String[])params.get("qformat"))[0];
705
            if (qformat.equals("xml"))
706
            {
707
              // set content type and other response header fields first
708
              response.setContentType("text/xml");
709
              xmldoc.toXml(out);
710
              //out.println(xmldoc);
711
            }
712
            else if (qformat.equals("html"))
713
            {
714
              response.setContentType("text/html");
715
              // Look up the document type
716
              String sourcetype = xmldoc.getDoctype();
717
              // Transform the document to the new doctype
718
              DBTransform dbt = new DBTransform(conn);
719
              dbt.transformXMLDocument(xmldoc.toString(), sourcetype,
720
                                 "-//W3C//HTML//EN", out);
721
            }
722
723 473 berkley
            util.returnConnection(conn);
724 453 berkley
          }
725
          else
726
          {
727
            //throw new Exception("handleGetDocument: bad URL");
728
            System.err.println("handleGetDocument: bad URL");
729
          }
730
        }
731
        else if(murl.getURLType().equals("http"))
732
        {//get the document from the internet
733 473 berkley
          Hashtable murlParams = murl.getHashParams();
734
          if(murlParams.containsKey("httpurl"))
735 453 berkley
          {//httpurl is the param name for an http url.
736 473 berkley
            URL urlconn = new URL((String)murlParams.get("httpurl"));
737
            //create a new url obj.
738 458 berkley
            //DataInputStream htmldoc = new DataInputStream(urlconn.openStream());
739
            BufferedReader htmldoc = new BufferedReader(
740
                                   new InputStreamReader(urlconn.openStream()));
741 453 berkley
            //bind a data stream.
742
            try
743
            { //display the document
744
              String line=null;
745
              while((line = htmldoc.readLine()) != null)
746
              {
747
                out.println(line);
748
              }
749
            }
750
            catch(Exception e)
751
            {
752
              util.debugMessage("error viewing html document");
753
            }
754
          }
755
        }
756
      }
757
      catch (McdbException e) {
758
        response.setContentType("text/xml");
759
        e.toXml(out);
760
      } catch   (Throwable t) {
761
        response.setContentType("text/html");
762
        out.println(t.getMessage());
763
      } finally {
764
        util.returnConnection(conn);
765
      }
766
    }
767
  }
768
769
  /**
770 50 jones
   * Handle the database getdocument request and return a XML document,
771
   * possibly transformed from XML into HTML
772
   */
773 382 berkley
  private void handleGetDocumentAction(PrintWriter out, Hashtable params,
774 87 jones
               HttpServletResponse response)
775
               throws ClassNotFoundException, IOException, SQLException {
776 102 jones
    String docidstr = null;
777 162 bojilova
    String docid = null;
778 102 jones
    String doc = null;
779 309 bojilova
    Connection conn = null;
780
781 102 jones
    try {
782 87 jones
      // Find the document id number
783 102 jones
      docidstr = ((String[])params.get("docid"))[0];
784 162 bojilova
      docid = docidstr;
785 309 bojilova
      conn = util.getConnection();
786 393 jones
      DocumentImpl xmldoc = new DocumentImpl(conn, docid);
787
      // Get the document indicated from the db
788
      //doc = docreader.readXMLDocument(docid);
789 85 jones
790 87 jones
      // Return the document in XML or HTML format
791 437 berkley
      String qformat=null;
792
      if(params.containsKey("qformat"))
793
      {
794
        qformat = ((String[])params.get("qformat"))[0];
795
      }
796
      else
797
      {
798
        qformat = "html";
799
      }
800
      if (qformat.equals("xml")) {
801 85 jones
        // set content type and other response header fields first
802
        response.setContentType("text/xml");
803 431 jones
        xmldoc.toXml(out);
804
        //out.println(xmldoc);
805 85 jones
      } else if (qformat.equals("html")) {
806 437 berkley
        response.setContentType("text/html");
807 87 jones
        // Look up the document type
808 393 jones
        String sourcetype = xmldoc.getDoctype();
809 87 jones
        // Transform the document to the new doctype
810 393 jones
        DBTransform dbt = new DBTransform(conn);
811
        dbt.transformXMLDocument(xmldoc.toString(), sourcetype,
812
                                 "-//W3C//HTML//EN", out);
813 85 jones
      }
814 343 jones
    } catch (McdbException e) {
815
      response.setContentType("text/xml");
816
      e.toXml(out);
817
    } catch (Throwable t) {
818 309 bojilova
      response.setContentType("text/html");
819 343 jones
      out.println(t.getMessage());
820 309 bojilova
    } finally {
821 320 bojilova
      util.returnConnection(conn);
822 309 bojilova
    }
823
824 49 jones
  }
825 55 jones
826
  /**
827
   * Handle the database putdocument request and write an XML document
828
   * to the database connection
829
   */
830 382 berkley
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
831 425 bojilova
               HttpServletResponse response, String user, String group) {
832 59 jones
833 309 bojilova
    Connection conn = null;
834
835 204 jones
    try {
836
      // Get the document indicated
837
      String[] doctext = (String[])params.get("doctext");
838
      StringReader xml = null;
839
      try {
840
        xml = new StringReader(doctext[0]);
841 59 jones
842 204 jones
        String[] action = (String[])params.get("action");
843
        String[] docid = (String[])params.get("docid");
844
        String newdocid = null;
845 203 jones
846 204 jones
        String doAction = null;
847
        if (action[0].equals("insert")) {
848
          doAction = "INSERT";
849
        } else if (action[0].equals("update")) {
850
          doAction = "UPDATE";
851
        }
852 203 jones
853 204 jones
        try {
854 309 bojilova
            // get a connection from the pool
855
            conn = util.getConnection();
856 408 jones
857 309 bojilova
            // write the document to the database
858
            try {
859
                String accNumber = docid[0];
860
                if (accNumber.equals("")) {
861
                    accNumber = null;
862
                }
863 425 bojilova
                newdocid = DocumentImpl.write(conn, xml, doAction, accNumber,
864 465 berkley
                                              user, group);
865
866 309 bojilova
            } catch (NullPointerException npe) {
867 425 bojilova
              newdocid = DocumentImpl.write(conn,xml,doAction,null,user,group);
868 309 bojilova
            }
869 462 bojilova
//        } catch (Exception e) {
870
//          response.setContentType("text/html");
871
//          out.println(e.getMessage());
872 309 bojilova
        } finally {
873 320 bojilova
          util.returnConnection(conn);
874 309 bojilova
        }
875
876 204 jones
        // set content type and other response header fields first
877
        response.setContentType("text/xml");
878
        out.println("<?xml version=\"1.0\"?>");
879
        out.println("<success>");
880
        out.println("<docid>" + newdocid + "</docid>");
881
        out.println("</success>");
882
883 203 jones
      } catch (NullPointerException npe) {
884 204 jones
        response.setContentType("text/xml");
885
        out.println("<?xml version=\"1.0\"?>");
886
        out.println("<error>");
887
        out.println(npe.getMessage());
888
        out.println("</error>");
889 55 jones
      }
890 204 jones
    } catch (Exception e) {
891
      response.setContentType("text/xml");
892
      out.println("<?xml version=\"1.0\"?>");
893
      out.println("<error>");
894
      out.println(e.getMessage());
895
      if (e instanceof SAXException) {
896
        Exception e2 = ((SAXException)e).getException();
897
        out.println("<error>");
898
        out.println(e2.getMessage());
899
        out.println("</error>");
900
      }
901
      //e.printStackTrace(out);
902
      out.println("</error>");
903 203 jones
    }
904 55 jones
  }
905 203 jones
906
  /**
907
   * Handle the database delete request and delete an XML document
908
   * from the database connection
909
   */
910
  private void handleDeleteAction(PrintWriter out, Hashtable params,
911 425 bojilova
               HttpServletResponse response, String user, String group) {
912 203 jones
913
    String[] docid = (String[])params.get("docid");
914 309 bojilova
    Connection conn = null;
915 203 jones
916
    // delete the document from the database
917
    try {
918 309 bojilova
      // get a connection from the pool
919
      conn = util.getConnection();
920 203 jones
                                      // NOTE -- NEED TO TEST HERE
921 408 jones
                                      // FOR EXISTENCE OF DOCID PARAM
922 203 jones
                                      // BEFORE ACCESSING ARRAY
923 375 berkley
      try {
924 425 bojilova
        DocumentImpl.delete(conn, docid[0], user, group);
925 204 jones
        response.setContentType("text/xml");
926
        out.println("<?xml version=\"1.0\"?>");
927
        out.println("<success>");
928 203 jones
        out.println("Document deleted.");
929 204 jones
        out.println("</success>");
930 203 jones
      } catch (AccessionNumberException ane) {
931 204 jones
        response.setContentType("text/xml");
932
        out.println("<?xml version=\"1.0\"?>");
933
        out.println("<error>");
934
        out.println("Error deleting document!!!");
935 203 jones
        out.println(ane.getMessage());
936 204 jones
        out.println("</error>");
937 203 jones
      }
938 204 jones
    } catch (Exception e) {
939
      response.setContentType("text/xml");
940
      out.println("<?xml version=\"1.0\"?>");
941
      out.println("<error>");
942
      out.println(e.getMessage());
943
      out.println("</error>");
944 309 bojilova
    } finally {
945 320 bojilova
      util.returnConnection(conn);
946 309 bojilova
    }
947 203 jones
  }
948 68 higgins
949
  /**
950 380 jones
   * Handle the validation request and return the results to the requestor
951 68 higgins
   */
952 185 jones
  private void handleValidateAction(PrintWriter out, Hashtable params,
953
               HttpServletResponse response) {
954 68 higgins
955 103 jones
    // Get the document indicated
956
    String valtext = null;
957 309 bojilova
958 103 jones
    try {
959
      valtext = ((String[])params.get("valtext"))[0];
960
    } catch (Exception nullpe) {
961 68 higgins
962 309 bojilova
      Connection conn = null;
963 162 bojilova
      String docid = null;
964 103 jones
      try {
965
        // Find the document id number
966 185 jones
        docid = ((String[])params.get("docid"))[0];
967 309 bojilova
968
        // get a connection from the pool
969
        conn = util.getConnection();
970 393 jones
971 309 bojilova
        // Get the document indicated from the db
972 393 jones
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
973
        valtext = xmldoc.toString();
974 185 jones
975 103 jones
      } catch (NullPointerException npe) {
976 253 jones
        response.setContentType("text/xml");
977
        out.println("<error>Error getting document ID: " + docid + "</error>");
978 320 bojilova
        if ( conn != null ) { util.returnConnection(conn); }
979 380 jones
        return;
980 309 bojilova
      } catch (Exception e) {
981
        response.setContentType("text/html");
982
        out.println(e.getMessage());
983
      } finally {
984 320 bojilova
        util.returnConnection(conn);
985 309 bojilova
      }
986 103 jones
    }
987 68 higgins
988 309 bojilova
    Connection conn = null;
989 103 jones
    try {
990 309 bojilova
      // get a connection from the pool
991
      conn = util.getConnection();
992 253 jones
      DBValidate valobj = new DBValidate(saxparser,conn);
993 185 jones
      boolean valid = valobj.validateString(valtext);
994 68 higgins
995
      // set content type and other response header fields first
996 253 jones
      response.setContentType("text/xml");
997
      out.println(valobj.returnErrors());
998
999 103 jones
    } catch (NullPointerException npe2) {
1000
      // set content type and other response header fields first
1001 253 jones
      response.setContentType("text/xml");
1002
      out.println("<error>Error validating document.</error>");
1003 309 bojilova
    } catch (Exception e) {
1004
      response.setContentType("text/html");
1005
      out.println(e.getMessage());
1006
    } finally {
1007 320 bojilova
      util.returnConnection(conn);
1008 309 bojilova
    }
1009 103 jones
  }
1010 87 jones
1011
  /**
1012 380 jones
   * Handle the document request and return the results to the requestor
1013 458 berkley
   * If a docid is passed in through the params then that document
1014
   * will be retrieved form the DB and put in the zip file.
1015
   * In addition if 1 or more relations parameters are passed, those file
1016
   * will be zipped as well.  Currently this is only implemented for
1017
   * metacat:// and http:// files.  Support should be added for srb:// files
1018
   * as well.
1019 91 higgins
   */
1020 458 berkley
  private void handleGetDataDocumentAction(ServletOutputStream out,
1021
               Hashtable params,
1022 185 jones
               HttpServletResponse response) {
1023 458 berkley
  //find the related files, get them from their source and zip them into
1024
  //a zip file.
1025
  try
1026
  {
1027
    Connection conn = util.getConnection();
1028
    String currentDocid = ((String[])params.get("docid"))[0];
1029
    ZipOutputStream zout = new ZipOutputStream(out);
1030
    byte[] bytestring = null;
1031
    ZipEntry zentry = null;
1032
    DocumentImpl xmldoc = null;
1033
    String[] reldocs = null;
1034
1035
    if(params.containsKey("relation"))
1036
    { //get the relations from the parameters.
1037
      reldocs = ((String[])params.get("relation"));
1038
    }
1039
    else
1040
    { //let the for loop know that there are no relations to zip
1041
      reldocs = new String[0];
1042
    }
1043
1044
    //write the base file to the zip file.
1045
    xmldoc = new DocumentImpl(conn, currentDocid);
1046
    bytestring = (xmldoc.toString()).getBytes();
1047
    zentry = new ZipEntry(currentDocid + ".xml");
1048
    //create a new zip entry and write the file to the stream
1049
    zentry.setSize(bytestring.length);
1050
    zout.putNextEntry(zentry);
1051
    zout.write(bytestring, 0, bytestring.length);
1052
    zout.closeEntry(); //get ready for the next entry.
1053
1054
    //zip up the related documents
1055
    for(int i=0; i<reldocs.length; i++)
1056
    {
1057
      metacatURL murl = new metacatURL(((String)reldocs[i]));
1058
      if(murl.getURLType().equals("metacat"))
1059
      {
1060
        //get the document from the database
1061 473 berkley
        xmldoc = new DocumentImpl(conn, (String)murl.getHashParam("docid"));
1062 458 berkley
        bytestring = (xmldoc.toString()).getBytes();
1063 473 berkley
        zentry = new ZipEntry(murl.getHashParam("docid") + ".xml");
1064 458 berkley
        //create a new zip entry and write the file to the stream
1065
        zentry.setSize(bytestring.length);
1066
        zout.putNextEntry(zentry);
1067
        zout.write(bytestring, 0, bytestring.length);
1068
        zout.closeEntry(); //get ready for the next entry.
1069
      }
1070
      else if(murl.getURLType().equals("http"))
1071
      {
1072 473 berkley
        Hashtable murlParams = murl.getHashParams();
1073
        if(murlParams.containsKey("httpurl"))
1074 458 berkley
        {//httpurl is the param name for an http url.
1075 473 berkley
          URL urlconn = new URL((String)murlParams.get("httpurl"));
1076
          //create a new url obj.
1077 458 berkley
          BufferedReader htmldoc = new BufferedReader(
1078
                                   new InputStreamReader(urlconn.openStream()));
1079
          //get the data from the web server
1080
          try
1081
          { //zip the document
1082
            String line=null;
1083 473 berkley
            zentry = new ZipEntry((String)murlParams.get("filename"));
1084 458 berkley
            //get just the filename from the URL.
1085
            zout.putNextEntry(zentry);
1086
            //make a new entry in the zip file stream
1087
            while((line = htmldoc.readLine()) != null)
1088
            {
1089
              bytestring = (line.toString()).getBytes();
1090
              zout.write(bytestring, 0, bytestring.length);
1091
              //write out the file line by line
1092
            }
1093
            zout.closeEntry(); //close the entry in the file
1094
          }
1095
          catch(Exception e)
1096
          {
1097
            util.debugMessage("error downloading html document");
1098
          }
1099
        }
1100
      }
1101
    }
1102
    zout.finish();  //terminate the zip file
1103
    zout.close();   //close the stream.
1104
    util.returnConnection(conn); //return the connection to the pool
1105
  }
1106
  catch(Exception e)
1107
  {
1108
    System.out.println("Error creating zip file: " + e.getMessage());
1109
    e.printStackTrace(System.out);
1110
  }
1111
1112
   /*
1113
   //////////old code using a shell script/////////////////////////////////
1114
1115 91 higgins
      boolean error_flag = false;
1116
      String error_message = "";
1117
      // Get the document indicated
1118
      String[] datadoc = (String[])params.get("datadoc");
1119 185 jones
      // defaultdatapath = "C:\\Temp\\";    // for testing only!!!
1120
      // executescript = "test.bat";        // for testing only!!!
1121 91 higgins
1122
      // set content type and other response header fields first
1123
      response.setContentType("application/octet-stream");
1124 185 jones
      if (defaultdatapath!=null) {
1125
        if(!defaultdatapath.endsWith(System.getProperty("file.separator"))) {
1126
          defaultdatapath=defaultdatapath+System.getProperty("file.separator");
1127 91 higgins
        }
1128 185 jones
        System.out.println("Path= "+defaultdatapath+datadoc[0]);
1129
        if (executescript!=null) {
1130
          String command = null;
1131
          File scriptfile = new File(executescript);
1132
          if (scriptfile.exists()) {
1133
            command=executescript+" "+datadoc[0]; // script includes path
1134
        } else {     // look in defaultdatapath
1135
            // on Win98 one MUST include the .bat extender
1136
            command = defaultdatapath+executescript+" "+datadoc[0];
1137
        }
1138 91 higgins
      System.out.println(command);
1139
      try {
1140
      Process proc = Runtime.getRuntime().exec(command);
1141
      proc.waitFor();
1142
      }
1143
      catch (Exception eee) {
1144
        System.out.println("Error running process!");
1145
        error_flag = true;
1146
        error_message = "Error running process!";}
1147
      } // end executescript not null if
1148
      File datafile = new File(defaultdatapath+datadoc[0]);
1149
      try {
1150
      FileInputStream fw = new FileInputStream(datafile);
1151
      int x;
1152 185 jones
      while ((x = fw.read())!=-1) {
1153 91 higgins
        out.write(x); }
1154 185 jones
        fw.close();
1155
      } catch (Exception e) {
1156 91 higgins
        System.out.println("Error in returning file\n"+e.getMessage());
1157
        error_flag=true;
1158 185 jones
        error_message = error_message+"\nError in returning file\n"+
1159
                        e.getMessage();
1160
      }
1161
    } // end defaultdatapath not null if
1162 458 berkley
    */
1163 91 higgins
  }
1164 302 bojilova
1165
  /**
1166
   * Handle the getdoctypes Action.
1167
   * Read all doctypes from db connection in XML format
1168
   */
1169
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1170
                                       HttpServletResponse response) {
1171
1172 309 bojilova
    Connection conn = null;
1173
1174 302 bojilova
    try {
1175
1176 309 bojilova
        // get connection from the pool
1177
        conn = util.getConnection();
1178
        DBUtil dbutil = new DBUtil(conn);
1179 302 bojilova
        String doctypes = dbutil.readDoctypes();
1180
        out.println(doctypes);
1181
1182
    } catch (Exception e) {
1183
      out.println("<?xml version=\"1.0\"?>");
1184
      out.println("<error>");
1185
      out.println(e.getMessage());
1186
      out.println("</error>");
1187 309 bojilova
    } finally {
1188 320 bojilova
      util.returnConnection(conn);
1189 309 bojilova
    }
1190 302 bojilova
1191
  }
1192
1193
  /**
1194
   * Handle the getdataguide Action.
1195
   * Read Data Guide for a given doctype from db connection in XML format
1196
   */
1197
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
1198
                                        HttpServletResponse response) {
1199
1200 309 bojilova
    Connection conn = null;
1201 316 bojilova
    String doctype = null;
1202
    String[] doctypeArr = (String[])params.get("doctype");
1203 309 bojilova
1204 316 bojilova
    // get only the first doctype specified in the list of doctypes
1205
    // it could be done for all doctypes in that list
1206
    if (doctypeArr != null) {
1207
        doctype = ((String[])params.get("doctype"))[0];
1208
    }
1209
1210 302 bojilova
    try {
1211
1212 309 bojilova
        // get connection from the pool
1213
        conn = util.getConnection();
1214
        DBUtil dbutil = new DBUtil(conn);
1215 316 bojilova
        String dataguide = dbutil.readDataGuide(doctype);
1216 302 bojilova
        out.println(dataguide);
1217
1218
    } catch (Exception e) {
1219
      out.println("<?xml version=\"1.0\"?>");
1220
      out.println("<error>");
1221
      out.println(e.getMessage());
1222
      out.println("</error>");
1223 309 bojilova
    } finally {
1224 320 bojilova
      util.returnConnection(conn);
1225 309 bojilova
    }
1226 302 bojilova
1227
  }
1228
1229 46 jones
}