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 669 jones
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 51 jones
 */
27
28
package edu.ucsb.nceas.metacat;
29
30 798 jones
import com.oreilly.servlet.multipart.FilePart;
31
import com.oreilly.servlet.multipart.MultipartParser;
32
import com.oreilly.servlet.multipart.ParamPart;
33
import com.oreilly.servlet.multipart.Part;
34
35 733 bojilova
import java.io.File;
36 46 jones
import java.io.PrintWriter;
37
import java.io.IOException;
38 50 jones
import java.io.StringReader;
39 185 jones
import java.io.FileInputStream;
40 731 bojilova
import java.io.BufferedInputStream;
41 46 jones
import java.util.Enumeration;
42
import java.util.Hashtable;
43 341 berkley
import java.util.ResourceBundle;
44 648 berkley
import java.util.Random;
45 82 jones
import java.util.PropertyResourceBundle;
46 50 jones
import java.net.URL;
47
import java.net.MalformedURLException;
48 85 jones
import java.sql.PreparedStatement;
49
import java.sql.ResultSet;
50 50 jones
import java.sql.Connection;
51 55 jones
import java.sql.SQLException;
52 361 berkley
import java.lang.reflect.*;
53 453 berkley
import java.net.*;
54 458 berkley
import java.util.zip.*;
55 46 jones
56
import javax.servlet.ServletConfig;
57
import javax.servlet.ServletContext;
58
import javax.servlet.ServletException;
59 48 jones
import javax.servlet.ServletInputStream;
60 46 jones
import javax.servlet.http.HttpServlet;
61
import javax.servlet.http.HttpServletRequest;
62
import javax.servlet.http.HttpServletResponse;
63 210 bojilova
import javax.servlet.http.HttpSession;
64 47 jones
import javax.servlet.http.HttpUtils;
65 458 berkley
import javax.servlet.ServletOutputStream;
66 46 jones
67 50 jones
import oracle.xml.parser.v2.XSLStylesheet;
68
import oracle.xml.parser.v2.XSLException;
69
import oracle.xml.parser.v2.XMLDocumentFragment;
70
import oracle.xml.parser.v2.XSLProcessor;
71
72 204 jones
import org.xml.sax.SAXException;
73
74 46 jones
/**
75
 * A metadata catalog server implemented as a Java Servlet
76 154 jones
 *
77
 * <p>Valid parameters are:<br>
78
 * action=query -- query the values of all elements and attributes
79
 *                     and return a result set of nodes<br>
80 205 jones
 * action=squery -- structured query (see pathquery.dtd)<br>
81 731 bojilova
 * action=read -- read any metadata/data file from Metacat and from Internet<br>
82 205 jones
 * action=insert -- insert an XML document into the database store<br>
83
 * action=update -- update an XML document that is in the database store<br>
84
 * action=delete --  delete an XML document from the database store<br>
85
 * action=validate -- vallidate the xml contained in valtext<br>
86
 * doctype -- document type list returned by the query (publicID)<br>
87 154 jones
 * qformat=xml -- display resultset from query in XML<br>
88
 * qformat=html -- display resultset from query in HTML<br>
89 731 bojilova
 * qformat=zip -- zip resultset from query<br>
90 154 jones
 * docid=34 -- display the document with the document ID number 34<br>
91 205 jones
 * doctext -- XML text of the document to load into the database<br>
92 598 bojilova
 * acltext -- XML access text for a document to load into the database<br>
93
 * dtdtext -- XML DTD text for a new DTD to load into Metacat XML Catalog<br>
94 183 jones
 * query -- actual query text (to go with 'action=query' or 'action=squery')<br>
95 205 jones
 * valtext -- XML text to be validated<br>
96 731 bojilova
 * abstractpath -- XPath in metadata document to read from<br>
97 688 bojilova
 * action=getaccesscontrol -- retrieve acl info for Metacat document<br>
98
 * action=getdoctypes -- retrieve all doctypes (publicID)<br>
99 699 bojilova
 * action=getdtdschema -- retrieve a DTD or Schema file<br>
100 688 bojilova
 * action=getdataguide -- retrieve a Data Guide<br>
101 725 bojilova
 * action=getprincipals -- retrieve a list of principals in XML<br>
102 205 jones
 * datadoc -- data document name (id)<br>
103
 * <p>
104
 * The particular combination of parameters that are valid for each
105
 * particular action value is quite specific.  This documentation
106
 * will be reorganized to reflect this information.
107 46 jones
 */
108
public class MetaCatServlet extends HttpServlet {
109
110 370 berkley
  private ServletConfig config = null;
111
  private ServletContext context = null;
112
  private Hashtable connectionPool = new Hashtable();
113
  private String resultStyleURL = null;
114
  private String xmlcatalogfile = null;
115
  private String saxparser = null;
116 798 jones
  private String datafilepath = null;
117
  private File dataDirectory = null;
118 370 berkley
  private String servletpath = null;
119 822 jones
  private String htmlpath = null;
120 380 jones
  private PropertyResourceBundle options = null;
121
  private MetaCatUtil util = null;
122
123 50 jones
  /**
124
   * Initialize the servlet by creating appropriate database connections
125
   */
126 46 jones
  public void init( ServletConfig config ) throws ServletException {
127
    try {
128
      super.init( config );
129
      this.config = config;
130 332 bojilova
      this.context = config.getServletContext();
131 184 jones
      System.out.println("MetaCatServlet Initialize");
132 82 jones
133 184 jones
      util = new MetaCatUtil();
134
135 83 jones
      // Get the configuration file information
136 184 jones
      resultStyleURL = util.getOption("resultStyleURL");
137
      xmlcatalogfile = util.getOption("xmlcatalogfile");
138
      saxparser = util.getOption("saxparser");
139 798 jones
      datafilepath = util.getOption("datafilepath");
140
      dataDirectory = new File(datafilepath);
141 360 bojilova
      servletpath = util.getOption("servletpath");
142
      htmlpath = util.getOption("htmlpath");
143 598 bojilova
144 731 bojilova
// MOVED IT TO doGet() & doPost()
145 598 bojilova
//      try {
146
//        // Open a pool of db connections
147
//        connectionPool = util.getConnectionPool();
148
//      } catch (Exception e) {
149
//        System.err.println("Error creating pool of database connections");
150
//        System.err.println(e.getMessage());
151
//      }
152 46 jones
    } catch ( ServletException ex ) {
153
      throw ex;
154
    }
155
  }
156
157 320 bojilova
  /**
158
   * Close all db connections from the pool
159
   */
160
  public void destroy() {
161
162
    if (util != null) {
163
        util.closeConnections();
164
    }
165
  }
166
167 50 jones
  /** Handle "GET" method requests from HTTP clients */
168 46 jones
  public void doGet (HttpServletRequest request, HttpServletResponse response)
169
    throws ServletException, IOException {
170
171 48 jones
    // Process the data and send back the response
172 59 jones
    handleGetOrPost(request, response);
173 48 jones
  }
174
175 50 jones
  /** Handle "POST" method requests from HTTP clients */
176 48 jones
  public void doPost( HttpServletRequest request, HttpServletResponse response)
177
    throws ServletException, IOException {
178
179
    // Process the data and send back the response
180 59 jones
    handleGetOrPost(request, response);
181 48 jones
  }
182
183 49 jones
  /**
184 50 jones
   * Control servlet response depending on the action parameter specified
185 49 jones
   */
186 382 berkley
  private void handleGetOrPost(HttpServletRequest request,
187 798 jones
                               HttpServletResponse response)
188
                               throws ServletException, IOException
189
  {
190 48 jones
191 309 bojilova
    if ( util == null ) {
192
        util = new MetaCatUtil();
193
    }
194 598 bojilova
    if ( connectionPool.isEmpty() ) {
195 309 bojilova
      try {
196
        // Open a pool of db connections
197
        connectionPool = util.getConnectionPool();
198
      } catch (Exception e) {
199 675 berkley
        System.err.println("Error creating pool of database connections in " +
200
                            " MetaCatServlet.handleGetOrPost");
201 309 bojilova
        System.err.println(e.getMessage());
202
      }
203
    }
204 49 jones
    // Get a handle to the output stream back to the client
205 566 jones
    //PrintWriter pwout = response.getWriter();
206 102 jones
    //response.setContentType("text/html");
207 798 jones
208
    // Deal with forms that are encoded as "multipart/form-data" differently
209
    // this is mainly used for uploading non-xml files using that may be binary
210 800 jones
    String ctype = request.getContentType();
211
    if (ctype != null && ctype.startsWith("multipart/form-data")) {
212 798 jones
      handleMultipartForm(request, response);
213
    } else {
214
      // This probably means the data is "application/x-www-url-encoded", we hope :-)
215 49 jones
216 798 jones
      String name = null;
217
      String[] value = null;
218
      String[] docid = new String[3];
219
      Hashtable params = new Hashtable();
220
      Enumeration paramlist = request.getParameterNames();
221
      while (paramlist.hasMoreElements()) {
222
        name = (String)paramlist.nextElement();
223
        value = request.getParameterValues(name);
224
225
        // Decode the docid and mouse click information
226
        if (name.endsWith(".y")) {
227
          docid[0] = name.substring(0,name.length()-2);
228
          params.put("docid", docid);
229
          name = "ypos";
230 648 berkley
        }
231 798 jones
        if (name.endsWith(".x")) {
232
          name = "xpos";
233
        }
234
235
        params.put(name,value);
236 425 bojilova
      }
237 798 jones
238
      //if the user clicked on the input images, decode which image
239
      //was clicked then set the action.
240
      String action = ((String[])params.get("action"))[0];
241
      util.debugMessage("Line 213: Action is: " + action);
242
243
      // This block handles session management for the servlet
244
      // by looking up the current session information for all actions
245
      // other than "login" and "logout"
246
      String username = null;
247
      String password = null;
248 802 bojilova
      String[] groupnames = null;
249 798 jones
      String sess_id = null;
250
251
      // handle login action
252
      if (action.equals("login")) {
253
254
        handleLoginAction(response.getWriter(), params, request, response);
255
256
      // handle logout action
257
      } else if (action.equals("logout")) {
258
259
        handleLogoutAction(response.getWriter(), params, request, response);
260
261
      // aware of session expiration on every request
262
      } else {
263
264
        HttpSession sess = request.getSession(true);
265
        if (sess.isNew()) {
266
          // session expired or has not been stored b/w user requests
267
          username = "public";
268
          sess.setAttribute("username", username);
269
        } else {
270
          username = (String)sess.getAttribute("username");
271
          password = (String)sess.getAttribute("password");
272 802 bojilova
          groupnames = (String[])sess.getAttribute("groupnames");
273 798 jones
          try {
274
            sess_id = (String)sess.getId();
275
          } catch(IllegalStateException ise) {
276
            System.out.println("error in handleGetOrPost: this shouldn't " +
277
                               "happen: the session should be valid: " +
278
                               ise.getMessage());
279
          }
280
        }
281
      }
282
283
      // Now that we know the session is valid, we can delegate the request
284
      // to a particular action handler
285
      if(action.equals("query")) {
286 802 bojilova
        handleQuery(response.getWriter(),params,response,username,groupnames);
287 798 jones
      } else if(action.equals("squery")) {
288
        if(params.containsKey("query")) {
289 802 bojilova
          handleSQuery(response.getWriter(),params,response,username,groupnames);
290 798 jones
        } else {
291
          PrintWriter out = response.getWriter();
292
          out.println("Illegal action squery without \"query\" parameter");
293
        }
294
      } else if (action.equals("read")) {
295 802 bojilova
        handleReadAction(params, response, username, groupnames);
296 798 jones
      } else if (action.equals("insert") || action.equals("update")) {
297 458 berkley
        PrintWriter out = response.getWriter();
298 798 jones
        if ( (username != null) &&  !username.equals("public") ) {
299 802 bojilova
          handleInsertOrUpdateAction(out,params,response,username,groupnames);
300 798 jones
        } else {
301
          out.println("Permission denied for " + action);
302
        }
303
      } else if (action.equals("delete")) {
304
        PrintWriter out = response.getWriter();
305
        if ( (username != null) &&  !username.equals("public") ) {
306 802 bojilova
          handleDeleteAction(out, params, response, username, groupnames);
307 798 jones
        } else {
308
          out.println("Permission denied for " + action);
309
        }
310
      } else if (action.equals("validate")) {
311
        PrintWriter out = response.getWriter();
312
        handleValidateAction(out, params, response);
313
      } else if (action.equals("getaccesscontrol")) {
314
        PrintWriter out = response.getWriter();
315 802 bojilova
        handleGetAccessControlAction(out,params,response,username,groupnames);
316 798 jones
      } else if (action.equals("getprincipals")) {
317
        PrintWriter out = response.getWriter();
318
        handleGetPrincipalsAction(out, username, password);
319
      } else if (action.equals("getdoctypes")) {
320
        PrintWriter out = response.getWriter();
321
        handleGetDoctypesAction(out, params, response);
322
      } else if (action.equals("getdtdschema")) {
323
        PrintWriter out = response.getWriter();
324
        handleGetDTDSchemaAction(out, params, response);
325
      } else if (action.equals("getdataguide")) {
326
        PrintWriter out = response.getWriter();
327
        handleGetDataGuideAction(out, params, response);
328
      } else if (action.equals("getlastdocid")) {
329
        PrintWriter out = response.getWriter();
330 847 jones
        handleGetMaxDocidAction(out, params, response);
331 798 jones
      } else if (action.equals("login") || action.equals("logout")) {
332
      } else if (action.equals("protocoltest")) {
333
        String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
334
        try {
335
          testURL = ((String[])params.get("url"))[0];
336
        } catch (Throwable t) {
337
        }
338
        String phandler = System.getProperty("java.protocol.handler.pkgs");
339
        response.setContentType("text/html");
340
        PrintWriter out = response.getWriter();
341
        out.println("<body bgcolor=\"white\">");
342
        out.println("<p>Handler property: <code>" + phandler + "</code></p>");
343
        out.println("<p>Starting test for:<br>");
344
        out.println("    " + testURL + "</p>");
345
        try {
346
          URL u = new URL(testURL);
347
          out.println("<pre>");
348
          out.println("Protocol: " + u.getProtocol());
349
          out.println("    Host: " + u.getHost());
350
          out.println("    Port: " + u.getPort());
351
          out.println("    Path: " + u.getPath());
352
          out.println("     Ref: " + u.getRef());
353
          String pquery = u.getQuery();
354
          out.println("   Query: " + pquery);
355
          out.println("  Params: ");
356
          if (pquery != null) {
357
            Hashtable qparams = util.parseQuery(u.getQuery());
358
            for (Enumeration en = qparams.keys(); en.hasMoreElements(); ) {
359
              String pname = (String)en.nextElement();
360
              String pvalue = (String)qparams.get(pname);
361
              out.println("    " + pname + ": " + pvalue);
362
            }
363 566 jones
          }
364 798 jones
          out.println("</pre>");
365
          out.println("</body>");
366
          out.close();
367
        } catch (MalformedURLException mue) {
368
          System.out.println("bad url from MetacatServlet.handleGetOrPost");
369
          out.println(mue.getMessage());
370
          mue.printStackTrace(out);
371
          out.close();
372 566 jones
        }
373 798 jones
      } else {
374
        PrintWriter out = response.getWriter();
375
        out.println("<?xml version=\"1.0\"?>");
376
        out.println("<error>");
377
        out.println("Error: action not registered.  Please report this error.");
378
        out.println("</error>");
379 566 jones
      }
380 798 jones
381
      util.closeConnections();
382
      // Close the stream to the client
383
      // out.close();
384 46 jones
    }
385
  }
386 355 berkley
387 731 bojilova
  // LOGIN & LOGOUT SECTION
388 50 jones
  /**
389 509 bojilova
   * Handle the login request. Create a new session object.
390 503 bojilova
   * Do user authentication through the session.
391 210 bojilova
   */
392
  private void handleLoginAction(PrintWriter out, Hashtable params,
393
               HttpServletRequest request, HttpServletResponse response) {
394 251 bojilova
395 503 bojilova
    AuthSession sess = null;
396 228 bojilova
    String un = ((String[])params.get("username"))[0];
397
    String pw = ((String[])params.get("password"))[0];
398 297 bojilova
    String action = ((String[])params.get("action"))[0];
399 509 bojilova
    String qformat = ((String[])params.get("qformat"))[0];
400 332 bojilova
401 297 bojilova
    try {
402 509 bojilova
      sess = new AuthSession();
403 297 bojilova
    } catch (Exception e) {
404 675 berkley
      System.out.println("error in MetacatServlet.handleLoginAction: " +
405
                          e.getMessage());
406 297 bojilova
      out.println(e.getMessage());
407 509 bojilova
      return;
408 297 bojilova
    }
409 411 bojilova
410 509 bojilova
    boolean isValid = sess.authenticate(request, un, pw);
411
412
    // format and transform the output
413 832 jones
    if (qformat.equals("xml")) {
414
      response.setContentType("text/xml");
415
      out.println(sess.getMessage());
416
    } else {
417 509 bojilova
      Connection conn = null;
418 503 bojilova
      try {
419 509 bojilova
        conn = util.getConnection();
420
        DBTransform trans = new DBTransform(conn);
421
        response.setContentType("text/html");
422 510 bojilova
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
423 832 jones
                                   "-//W3C//HTML//EN", qformat, out);
424 509 bojilova
        util.returnConnection(conn);
425
      } catch(Exception e) {
426
        util.returnConnection(conn);
427
      }
428
429
    // any output is returned
430 503 bojilova
    }
431 370 berkley
  }
432 509 bojilova
433
  /**
434
   * Handle the logout request. Close the connection.
435
   */
436
  private void handleLogoutAction(PrintWriter out, Hashtable params,
437
               HttpServletRequest request, HttpServletResponse response) {
438
439
    String qformat = ((String[])params.get("qformat"))[0];
440
441
    // close the connection
442
    HttpSession sess = request.getSession(false);
443
    if (sess != null) { sess.invalidate();  }
444
445
    // produce output
446
    StringBuffer output = new StringBuffer();
447
    output.append("<?xml version=\"1.0\"?>");
448 510 bojilova
    output.append("<logout>");
449
    output.append("User logged out");
450
    output.append("</logout>");
451 509 bojilova
452
    //format and transform the output
453 832 jones
    if (qformat.equals("xml")) {
454
      response.setContentType("text/xml");
455
      out.println(output.toString());
456
    } else {
457 509 bojilova
      Connection conn = null;
458
      try {
459
        conn = util.getConnection();
460
        DBTransform trans = new DBTransform(conn);
461
        response.setContentType("text/html");
462 510 bojilova
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
463 832 jones
                                   "-//W3C//HTML//EN", qformat, out);
464 509 bojilova
        util.returnConnection(conn);
465
      } catch(Exception e) {
466
        util.returnConnection(conn);
467
      }
468
    }
469
  }
470 731 bojilova
  // END OF LOGIN & LOGOUT SECTION
471 370 berkley
472 731 bojilova
  // SQUERY & QUERY SECTION
473 373 berkley
  /**
474 380 jones
   * Retreive the squery xml, execute it and display it
475
   *
476
   * @param out the output stream to the client
477
   * @param params the Hashtable of parameters that should be included
478
   * in the squery.
479
   * @param response the response object linked to the client
480
   * @param conn the database connection
481
   */
482
  protected void handleSQuery(PrintWriter out, Hashtable params,
483 802 bojilova
                 HttpServletResponse response, String user, String[] groups)
484 373 berkley
  {
485 380 jones
    String xmlquery = ((String[])params.get("query"))[0];
486
    String qformat = ((String[])params.get("qformat"))[0];
487 465 berkley
    String resultdoc = null;
488
489 802 bojilova
    Hashtable doclist = runQuery(xmlquery, user, groups);
490 444 berkley
491 465 berkley
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
492
493 380 jones
    //format and transform the results
494 832 jones
    if(qformat.equals("xml")) {
495 380 jones
      response.setContentType("text/xml");
496
      out.println(resultdoc);
497
    } else {
498 832 jones
      transformResultset(resultdoc, response, out, qformat);
499 380 jones
    }
500 341 berkley
  }
501
502
   /**
503 380 jones
    * Create the xml query, execute it and display the results.
504
    *
505
    * @param out the output stream to the client
506
    * @param params the Hashtable of parameters that should be included
507 370 berkley
    * in the squery.
508 380 jones
    * @param response the response object linked to the client
509 370 berkley
    */
510 375 berkley
  protected void handleQuery(PrintWriter out, Hashtable params,
511 802 bojilova
                 HttpServletResponse response, String user, String[] groups)
512 341 berkley
  {
513 370 berkley
    //create the query and run it
514 373 berkley
    String xmlquery = DBQuery.createSQuery(params);
515 802 bojilova
    Hashtable doclist = runQuery(xmlquery, user, groups);
516 465 berkley
    String qformat = ((String[])params.get("qformat"))[0];
517
    String resultdoc = null;
518
519
    resultdoc = createResultDocument(doclist, transformQuery(params));
520 425 bojilova
521 370 berkley
    //format and transform the results
522 832 jones
    if(qformat.equals("xml")) {
523 370 berkley
      response.setContentType("text/xml");
524
      out.println(resultdoc);
525 443 berkley
    } else {
526 832 jones
      transformResultset(resultdoc, response, out, qformat);
527 370 berkley
    }
528 341 berkley
  }
529
530
  /**
531 384 berkley
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
532
   * so it can properly be placed in the <query> tag of the resultset.
533
   * This method is overwritable so that other applications can customize
534
   * the structure of what is in the <query> tag.
535
   *
536
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
537
   */
538
  protected String transformQuery(Hashtable params)
539
  {
540
    //DBQuery.createSQuery is a re-calling of a previously called
541
    //function but it is necessary
542
    //so that overriding methods have access to the params hashtable
543
    String xmlquery = DBQuery.createSQuery(params);
544
    //the <?xml version="1.0"?> tag is the first 22 characters of the
545
    xmlquery = xmlquery.trim();
546
    int index = xmlquery.indexOf("?>");
547
    return xmlquery.substring(index + 2, xmlquery.length());
548
  }
549
550
  /**
551 443 berkley
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
552
   * string as a param instead of a hashtable.
553
   *
554
   * @param xmlquery a string representing a query.
555
   */
556
  protected String transformQuery(String xmlquery)
557
  {
558
    xmlquery = xmlquery.trim();
559
    int index = xmlquery.indexOf("?>");
560
    return xmlquery.substring(index + 2, xmlquery.length());
561
  }
562
563
  /**
564 380 jones
   * Run the query and return a hashtable of results.
565
   *
566
   * @param xmlquery the query to run
567
   */
568 802 bojilova
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
569 341 berkley
  {
570
    Hashtable doclist=null;
571
    Connection conn = null;
572
    try
573
    {
574 441 bojilova
      conn = util.getConnection();
575
      DBQuery queryobj = new DBQuery(conn, saxparser);
576 802 bojilova
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
577 441 bojilova
      util.returnConnection(conn);
578
      return doclist;
579 341 berkley
    }
580
    catch (Exception e)
581
    {
582 441 bojilova
      util.returnConnection(conn);
583 675 berkley
      util.debugMessage("Error in MetacatServlet.runQuery: " + e.getMessage());
584 341 berkley
      doclist = null;
585
      return doclist;
586
    }
587
  }
588
589 380 jones
  /**
590 370 berkley
   * Transorms an xml resultset document to html and sends it to the browser
591 380 jones
   *
592 370 berkley
   * @param resultdoc the string representation of the document that needs
593
   * to be transformed.
594
   * @param response the HttpServletResponse object bound to the client.
595
   * @param out the output stream to the client
596 832 jones
   * @param qformat the name of the style-set to use for transformations
597 375 berkley
   */
598
  protected void transformResultset(String resultdoc,
599 380 jones
                                    HttpServletResponse response,
600 832 jones
                                    PrintWriter out, String qformat)
601 370 berkley
  {
602
    Connection conn = null;
603 380 jones
    try {
604 370 berkley
      conn = util.getConnection();
605
      DBTransform trans = new DBTransform(conn);
606
      response.setContentType("text/html");
607
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
608 832 jones
                                 "-//W3C//HTML//EN", qformat, out);
609 382 berkley
      util.returnConnection(conn);
610
    }
611
    catch(Exception e)
612
    {
613 441 bojilova
      util.returnConnection(conn);
614 370 berkley
    }
615
  }
616
617 355 berkley
  /**
618
   * Transforms a hashtable of documents to an xml or html result.
619 380 jones
   *
620 355 berkley
   * @param doclist- the hashtable to transform
621 744 jones
   * @param xmlquery- the query that returned the doclist result
622 355 berkley
   */
623 375 berkley
  protected String createResultDocument(Hashtable doclist, String xmlquery)
624 341 berkley
  {
625
    // Create a buffer to hold the xml result
626
    StringBuffer resultset = new StringBuffer();
627
628 382 berkley
    // Print the resulting root nodes
629 341 berkley
    String docid = null;
630
    String document = null;
631
    resultset.append("<?xml version=\"1.0\"?>\n");
632
    resultset.append("<resultset>\n");
633 465 berkley
634 384 berkley
    resultset.append("  <query>" + xmlquery + "</query>");
635 478 berkley
636
    if(doclist != null)
637 341 berkley
    {
638 478 berkley
      Enumeration doclistkeys = doclist.keys();
639
      while (doclistkeys.hasMoreElements())
640
      {
641
        docid = (String)doclistkeys.nextElement();
642
        document = (String)doclist.get(docid);
643
        resultset.append("  <document>" + document + "</document>");
644
      }
645
    }
646
647 341 berkley
    resultset.append("</resultset>");
648 370 berkley
    return resultset.toString();
649 341 berkley
  }
650 731 bojilova
  // END OF SQUERY & QUERY SECTION
651 437 berkley
652 731 bojilova
  // READ SECTION
653
  /**
654
   * Handle the "read" request of metadata/data files from Metacat
655
   * or any files from Internet;
656
   * transformed metadata XML document into HTML presentation if requested;
657
   * zip files when more than one were requested.
658
   *
659
   * @param params the Hashtable of HTTP request parameters
660
   * @param response the HTTP response object linked to the client
661
   * @param user the username sent the request
662 802 bojilova
   * @param groups the user's groupnames
663 437 berkley
   */
664 731 bojilova
  private void handleReadAction(Hashtable params, HttpServletResponse response,
665 802 bojilova
                                String user, String[] groups)
666 437 berkley
  {
667 731 bojilova
    ServletOutputStream out = null;
668
    ZipOutputStream zout = null;
669
670
    try {
671
      String[] docs = new String[0];
672
      String docid = "";
673
      String qformat = "";
674
      String abstrpath = null;
675
      boolean zip = false;
676
      // read the params
677
      if (params.containsKey("docid")) {
678
        docs = (String[])params.get("docid");
679 437 berkley
      }
680 731 bojilova
      if (params.containsKey("qformat")) {
681
        qformat = ((String[])params.get("qformat"))[0];
682 437 berkley
      }
683 731 bojilova
      if (params.containsKey("abstractpath")) {
684
        abstrpath = ((String[])params.get("abstractpath"))[0];
685 738 bojilova
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
686
          viewAbstract(response, abstrpath, docs[0]);
687
          return;
688
        }
689 437 berkley
      }
690 731 bojilova
      if ( (docs.length > 1) || qformat.equals("zip") ) {
691
        zip = true;
692
        out = response.getOutputStream();
693
        response.setContentType("application/zip"); //MIME type
694
        zout = new ZipOutputStream(out);
695
      }
696
      // go through the list of docs to read
697
      for (int i=0; i < docs.length; i++ ) {
698
        try {
699
700
          URL murl = new URL(docs[i]);
701
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
702
          // case docid="http://.../?docid=aaa"
703
          // or docid="metacat://.../?docid=bbb"
704
          if (murlQueryStr.containsKey("docid")) {
705
            // get only docid, eliminate the rest
706
            docid = (String)murlQueryStr.get("docid");
707
            if ( zip ) {
708
              addDocToZip(docid, zout);
709
            } else {
710
              readFromMetacat(response, docid, qformat, abstrpath,
711 802 bojilova
                              user, groups, zip, zout);
712 731 bojilova
            }
713
714
          // case docid="http://.../filename"
715
          } else {
716
            docid = docs[i];
717
            if ( zip ) {
718
              addDocToZip(docid, zout);
719
            } else {
720
              readFromURLConnection(response, docid);
721
            }
722
          }
723
724
        // case docid="ccc"
725
        } catch (MalformedURLException mue) {
726
          docid = docs[i];
727
          if ( zip ) {
728
            addDocToZip(docid, zout);
729
          } else {
730
            readFromMetacat(response, docid, qformat, abstrpath,
731 802 bojilova
                            user, groups, zip, zout);
732 731 bojilova
          }
733
        }
734
735
      } /* end for */
736
737
      if ( zip ) {
738
        zout.finish(); //terminate the zip file
739
        zout.close();  //close the zip stream
740
      }
741
742 845 jones
        /*
743
    } catch (ClassNotFoundException cnfe) {
744
    } catch (IOException ioe1) {
745
    } catch (SQLException se) {
746
    } catch (McdbException mcdbe) {
747 731 bojilova
    } catch (Exception e) {
748 845 jones
      */
749
    } catch (Exception e) {
750 731 bojilova
      try {
751 845 jones
        response.setContentType("text/xml"); //MIME type
752
        //PrintWriter pw = response.getWriter();
753
        if (out != null) {
754
            PrintWriter pw = new PrintWriter(out);
755
            pw.println("<?xml version=\"1.0\"?>");
756
            pw.println("<error>");
757
            pw.println(e.getMessage());
758
            pw.println("</error>");
759
            pw.close();
760
        }
761
        //if ( out != null ) { out.close(); }
762 731 bojilova
        if ( zout != null ) { zout.close(); }
763
      } catch (IOException ioe) {
764
        System.out.println("Problem with the servlet output " +
765
                           "in MetacatServlet.handleReadAction: " +
766
                           ioe.getMessage());
767
        ioe.printStackTrace(System.out);
768
769
      }
770
771
      System.out.println("Error in MetacatServlet.handleReadAction: " +
772 675 berkley
                         e.getMessage());
773 731 bojilova
      e.printStackTrace(System.out);
774 437 berkley
    }
775
776
  }
777 731 bojilova
778
  // read metadata or data from Metacat
779
  private void readFromMetacat(HttpServletResponse response, String docid,
780
                               String qformat, String abstrpath, String user,
781 802 bojilova
                               String[] groups, boolean zip, ZipOutputStream zout)
782 731 bojilova
               throws ClassNotFoundException, IOException, SQLException,
783
                      McdbException, Exception
784 453 berkley
  {
785
    Connection conn = null;
786 731 bojilova
    try {
787
      conn = util.getConnection();
788
      DocumentImpl doc = new DocumentImpl(conn, docid);
789 453 berkley
790 731 bojilova
      if ( doc.getRootNodeID() == 0 ) {
791
        // this is data file
792
        ServletOutputStream out = response.getOutputStream();
793
        String filepath = util.getOption("datafilepath");
794
        if(!filepath.endsWith("/")) {
795
          filepath += "/";
796
        }
797 846 berkley
        String filename = filepath + docid;      //MIME type
798 731 bojilova
        String contentType = getServletContext().getMimeType(filename);
799
        if (contentType == null) {
800
          if (filename.endsWith(".xml")) {
801
            contentType="text/xml";
802
          } else if (filename.endsWith(".css")) {
803
            contentType="text/css";
804
          } else if (filename.endsWith(".dtd")) {
805
            contentType="text/plain";
806
          } else if (filename.endsWith(".xsd")) {
807 733 bojilova
            contentType="text/xml";
808 731 bojilova
          } else if (filename.endsWith("/")) {
809 733 bojilova
            contentType="text/html";
810 731 bojilova
          } else {
811 733 bojilova
            File f = new File(filename);
812
            if ( f.isDirectory() ) {
813
              contentType="text/html";
814
            } else {
815
              contentType="application/octet-stream";
816
            }
817 453 berkley
          }
818
        }
819 731 bojilova
        response.setContentType(contentType);
820 733 bojilova
        // if we decide to use "application/octet-stream" for all data returns
821
        // response.setContentType("application/octet-stream");
822 731 bojilova
        FileInputStream fin = null;
823
        try {
824
          fin = new FileInputStream(filename);
825
          byte[] buf = new byte[4 * 1024]; // 4K buffer
826
          int b = fin.read(buf);
827
          while (b != -1) {
828
            out.write(buf, 0, b);
829
            b = fin.read(buf);
830 453 berkley
          }
831 731 bojilova
        } finally {
832
          if (fin != null) fin.close();
833 453 berkley
        }
834 731 bojilova
835
      } else {
836
        // this is metadata doc
837 832 jones
        if ( qformat.equals("xml") ) {
838
          // set content type first
839
          response.setContentType("text/xml");   //MIME type
840
          PrintWriter out = response.getWriter();
841
          doc.toXml(out);
842
        } else {
843 731 bojilova
          response.setContentType("text/html");  //MIME type
844
          PrintWriter out = response.getWriter();
845
846
          // Look up the document type
847
          String doctype = doc.getDoctype();
848
          // Transform the document to the new doctype
849
          DBTransform dbt = new DBTransform(conn);
850
          dbt.transformXMLDocument(doc.toString(),
851 832 jones
                                   doctype,"-//W3C//HTML//EN", qformat, out);
852 731 bojilova
        }
853
854 453 berkley
      }
855 731 bojilova
    } finally {
856
      util.returnConnection(conn);
857
    }
858
859
  }
860 453 berkley
861 731 bojilova
  // read data from URLConnection
862
  private void readFromURLConnection(HttpServletResponse response, String docid)
863
               throws IOException, MalformedURLException
864 566 jones
  {
865 731 bojilova
    ServletOutputStream out = response.getOutputStream();
866
    String contentType = getServletContext().getMimeType(docid); //MIME type
867
    if (contentType == null) {
868
      if (docid.endsWith(".xml")) {
869
        contentType="text/xml";
870
      } else if (docid.endsWith(".css")) {
871
        contentType="text/css";
872
      } else if (docid.endsWith(".dtd")) {
873
        contentType="text/plain";
874
      } else if (docid.endsWith(".xsd")) {
875 733 bojilova
        contentType="text/xml";
876 731 bojilova
      } else if (docid.endsWith("/")) {
877 733 bojilova
        contentType="text/html";
878 731 bojilova
      } else {
879 733 bojilova
        File f = new File(docid);
880
        if ( f.isDirectory() ) {
881
          contentType="text/html";
882
        } else {
883
          contentType="application/octet-stream";
884
        }
885 731 bojilova
      }
886
    }
887
    response.setContentType(contentType);
888 733 bojilova
    // if we decide to use "application/octet-stream" for all data returns
889
    // response.setContentType("application/octet-stream");
890 731 bojilova
891
    // this is http url
892
    URL url = new URL(docid);
893
    BufferedInputStream bis = null;
894 566 jones
    try {
895 731 bojilova
      bis = new BufferedInputStream(url.openStream());
896
      byte[] buf = new byte[4 * 1024]; // 4K buffer
897
      int b = bis.read(buf);
898
      while (b != -1) {
899
        out.write(buf, 0, b);
900
        b = bis.read(buf);
901 636 berkley
      }
902 731 bojilova
    } finally {
903
      if (bis != null) bis.close();
904 566 jones
    }
905 731 bojilova
906 566 jones
  }
907 636 berkley
908 731 bojilova
  // read file/doc and write to ZipOutputStream
909
  private void addDocToZip(String docid, ZipOutputStream zout)
910
               throws ClassNotFoundException, IOException, SQLException,
911
                      McdbException, Exception
912 636 berkley
  {
913 731 bojilova
    byte[] bytestring = null;
914
    ZipEntry zentry = null;
915
916
    try {
917
      URL url = new URL(docid);
918
919
      // this http url; read from URLConnection; add to zip
920
      zentry = new ZipEntry(docid);
921
      zout.putNextEntry(zentry);
922
      BufferedInputStream bis = null;
923
      try {
924
        bis = new BufferedInputStream(url.openStream());
925
        byte[] buf = new byte[4 * 1024]; // 4K buffer
926
        int b = bis.read(buf);
927
        while(b != -1) {
928
          zout.write(buf, 0, b);
929
          b = bis.read(buf);
930
        }
931
      } finally {
932
        if (bis != null) bis.close();
933 636 berkley
      }
934 731 bojilova
      zout.closeEntry();
935
936
    } catch (MalformedURLException mue) {
937 661 berkley
938 731 bojilova
      // this is metacat doc (data file or metadata doc)
939
      Connection conn = null;
940
      try {
941
        conn = util.getConnection();
942
        DocumentImpl doc = new DocumentImpl(conn, docid);
943 661 berkley
944 731 bojilova
        if ( doc.getRootNodeID() == 0 ) {
945
          // this is data file; add file to zip
946
          String filepath = util.getOption("datafilepath");
947
          if(!filepath.endsWith("/")) {
948
            filepath += "/";
949
          }
950
          String filename = filepath + doc.getDocname();
951
          zentry = new ZipEntry(filename);
952
          zout.putNextEntry(zentry);
953
          FileInputStream fin = null;
954
          try {
955
            fin = new FileInputStream(filename);
956
            byte[] buf = new byte[4 * 1024]; // 4K buffer
957
            int b = fin.read(buf);
958
            while (b != -1) {
959
              zout.write(buf, 0, b);
960
              b = fin.read(buf);
961
            }
962
          } finally {
963
            if (fin != null) fin.close();
964
          }
965
          zout.closeEntry();
966
967
        } else {
968
          // this is metadata doc; add doc to zip
969
          bytestring = doc.toString().getBytes();
970
          zentry = new ZipEntry(docid + ".xml");
971
          zentry.setSize(bytestring.length);
972
          zout.putNextEntry(zentry);
973
          zout.write(bytestring, 0, bytestring.length);
974
          zout.closeEntry();
975 636 berkley
        }
976 731 bojilova
      } finally {
977
        util.returnConnection(conn);
978 636 berkley
      }
979
980
    }
981 731 bojilova
982 636 berkley
  }
983 731 bojilova
984
  // view abstract within document
985
  private void viewAbstract(HttpServletResponse response,
986
                            String abstractpath, String docid)
987
               throws ClassNotFoundException, IOException, SQLException,
988
                      McdbException, Exception
989
  {
990 309 bojilova
    Connection conn = null;
991 102 jones
    try {
992 309 bojilova
      conn = util.getConnection();
993 731 bojilova
994
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid, conn);
995
996
      response.setContentType("text/html");  //MIME type
997
      PrintWriter out = response.getWriter();
998
      out.println("<html><head><title>Abstract</title></head>");
999
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1000
      for (int i=0; i<abstracts.length; i++) {
1001
        out.println("<p>" + (String)abstracts[i] + "</p>");
1002
      }
1003
      out.println("</body></html>");
1004 85 jones
1005 309 bojilova
    } finally {
1006 320 bojilova
      util.returnConnection(conn);
1007 731 bojilova
    }
1008 49 jones
  }
1009 731 bojilova
  // END OF READ SECTION
1010
1011
  // INSERT/UPDATE SECTION
1012 55 jones
  /**
1013
   * Handle the database putdocument request and write an XML document
1014
   * to the database connection
1015
   */
1016 382 berkley
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1017 802 bojilova
               HttpServletResponse response, String user, String[] groups) {
1018 59 jones
1019 309 bojilova
    Connection conn = null;
1020
1021 204 jones
    try {
1022
      // Get the document indicated
1023
      String[] doctext = (String[])params.get("doctext");
1024 557 bojilova
1025 680 bojilova
      String pub = null;
1026
      if (params.containsKey("public")) {
1027
        pub = ((String[])params.get("public"))[0];
1028 557 bojilova
      }
1029 680 bojilova
1030 598 bojilova
      StringReader dtd = null;
1031 680 bojilova
      if (params.containsKey("dtdtext")) {
1032 598 bojilova
        String[] dtdtext = (String[])params.get("dtdtext");
1033
        try {
1034 619 bojilova
          if ( !dtdtext[0].equals("") ) {
1035
            dtd = new StringReader(dtdtext[0]);
1036
          }
1037 598 bojilova
        } catch (NullPointerException npe) {}
1038
      }
1039 557 bojilova
1040 204 jones
      StringReader xml = null;
1041 695 bojilova
      boolean validate = false;
1042 204 jones
      try {
1043 695 bojilova
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1044
        // in order to decide whether to use validation parser
1045
        validate = validateXML(doctext[0]);
1046 204 jones
        xml = new StringReader(doctext[0]);
1047 59 jones
1048 204 jones
        String[] action = (String[])params.get("action");
1049
        String[] docid = (String[])params.get("docid");
1050
        String newdocid = null;
1051 203 jones
1052 204 jones
        String doAction = null;
1053
        if (action[0].equals("insert")) {
1054
          doAction = "INSERT";
1055
        } else if (action[0].equals("update")) {
1056
          doAction = "UPDATE";
1057
        }
1058 203 jones
1059 204 jones
        try {
1060 680 bojilova
          // get a connection from the pool
1061
          conn = util.getConnection();
1062 408 jones
1063 680 bojilova
          // write the document to the database
1064
          try {
1065
            String accNumber = docid[0];
1066
            if (accNumber.equals("")) {
1067
              accNumber = null;
1068 309 bojilova
            }
1069 680 bojilova
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1070 802 bojilova
                                          accNumber, user, groups, validate);
1071 680 bojilova
          } catch (NullPointerException npe) {
1072
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1073 802 bojilova
                                          null, user, groups, validate);
1074 680 bojilova
          }
1075 309 bojilova
        } finally {
1076 320 bojilova
          util.returnConnection(conn);
1077 309 bojilova
        }
1078
1079 204 jones
        // set content type and other response header fields first
1080
        response.setContentType("text/xml");
1081
        out.println("<?xml version=\"1.0\"?>");
1082
        out.println("<success>");
1083
        out.println("<docid>" + newdocid + "</docid>");
1084
        out.println("</success>");
1085
1086 203 jones
      } catch (NullPointerException npe) {
1087 204 jones
        response.setContentType("text/xml");
1088
        out.println("<?xml version=\"1.0\"?>");
1089
        out.println("<error>");
1090
        out.println(npe.getMessage());
1091
        out.println("</error>");
1092 55 jones
      }
1093 204 jones
    } catch (Exception e) {
1094
      response.setContentType("text/xml");
1095
      out.println("<?xml version=\"1.0\"?>");
1096
      out.println("<error>");
1097
      out.println(e.getMessage());
1098
      if (e instanceof SAXException) {
1099
        Exception e2 = ((SAXException)e).getException();
1100
        out.println("<error>");
1101 780 berkley
        try
1102
        {
1103
          out.println(e2.getMessage());
1104
        }
1105
        catch(NullPointerException npe)
1106
        {
1107
          out.println(e.getMessage());
1108
        }
1109 204 jones
        out.println("</error>");
1110
      }
1111
      //e.printStackTrace(out);
1112
      out.println("</error>");
1113 203 jones
    }
1114 55 jones
  }
1115 203 jones
1116
  /**
1117 695 bojilova
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1118
   * in order to decide whether to use validation parser
1119
   */
1120
  private static boolean validateXML(String xmltext) throws IOException {
1121
1122
    StringReader xmlreader = new StringReader(xmltext);
1123
    StringBuffer cbuff = new StringBuffer();
1124
    java.util.Stack st = new java.util.Stack();
1125
    boolean validate = false;
1126
    int c;
1127
    int inx;
1128
1129
    // read from the stream until find the keywords
1130
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1131
      cbuff.append((char)c);
1132
1133
      // "<!DOCTYPE" keyword is found; put it in the stack
1134
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1135
        cbuff = new StringBuffer();
1136
        st.push("<!DOCTYPE");
1137
      }
1138
      // "PUBLIC" keyword is found; put it in the stack
1139
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1140
        cbuff = new StringBuffer();
1141
        st.push("PUBLIC");
1142
      }
1143
      // "SYSTEM" keyword is found; put it in the stack
1144
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1145
        cbuff = new StringBuffer();
1146
        st.push("SYSTEM");
1147
      }
1148
      // ">" character is found; put it in the stack
1149
      // ">" is found twice: fisrt from <?xml ...?>
1150
      // and second from <!DOCTYPE ... >
1151
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1152
        cbuff = new StringBuffer();
1153
        st.push(">");
1154
      }
1155
    }
1156
1157
    // close the stream
1158
    xmlreader.close();
1159
1160
    // check the stack whether it contains the keywords:
1161
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1162
    if ( st.size() == 4 ) {
1163
      if ( ((String)st.pop()).equals(">") &&
1164
           ( ((String)st.peek()).equals("PUBLIC") |
1165
             ((String)st.pop()).equals("SYSTEM") ) &&
1166
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1167
        validate = true;
1168
      }
1169
    }
1170
1171
System.out.println("Validation is " + validate);
1172
    return validate;
1173
  }
1174 731 bojilova
  // END OF INSERT/UPDATE SECTION
1175 695 bojilova
1176 731 bojilova
  // DELETE SECTION
1177 695 bojilova
  /**
1178 203 jones
   * Handle the database delete request and delete an XML document
1179
   * from the database connection
1180
   */
1181
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1182 802 bojilova
               HttpServletResponse response, String user, String[] groups) {
1183 203 jones
1184
    String[] docid = (String[])params.get("docid");
1185 309 bojilova
    Connection conn = null;
1186 203 jones
1187
    // delete the document from the database
1188
    try {
1189 309 bojilova
      // get a connection from the pool
1190
      conn = util.getConnection();
1191 203 jones
                                      // NOTE -- NEED TO TEST HERE
1192 408 jones
                                      // FOR EXISTENCE OF DOCID PARAM
1193 203 jones
                                      // BEFORE ACCESSING ARRAY
1194 375 berkley
      try {
1195 802 bojilova
        DocumentImpl.delete(conn, docid[0], user, groups);
1196 204 jones
        response.setContentType("text/xml");
1197
        out.println("<?xml version=\"1.0\"?>");
1198
        out.println("<success>");
1199 203 jones
        out.println("Document deleted.");
1200 204 jones
        out.println("</success>");
1201 203 jones
      } catch (AccessionNumberException ane) {
1202 204 jones
        response.setContentType("text/xml");
1203
        out.println("<?xml version=\"1.0\"?>");
1204
        out.println("<error>");
1205
        out.println("Error deleting document!!!");
1206 203 jones
        out.println(ane.getMessage());
1207 204 jones
        out.println("</error>");
1208 203 jones
      }
1209 204 jones
    } catch (Exception e) {
1210
      response.setContentType("text/xml");
1211
      out.println("<?xml version=\"1.0\"?>");
1212
      out.println("<error>");
1213
      out.println(e.getMessage());
1214
      out.println("</error>");
1215 309 bojilova
    } finally {
1216 320 bojilova
      util.returnConnection(conn);
1217 309 bojilova
    }
1218 203 jones
  }
1219 731 bojilova
  // END OF DELETE SECTION
1220 68 higgins
1221 731 bojilova
  // VALIDATE SECTION
1222 68 higgins
  /**
1223 380 jones
   * Handle the validation request and return the results to the requestor
1224 68 higgins
   */
1225 185 jones
  private void handleValidateAction(PrintWriter out, Hashtable params,
1226
               HttpServletResponse response) {
1227 68 higgins
1228 103 jones
    // Get the document indicated
1229
    String valtext = null;
1230 309 bojilova
1231 103 jones
    try {
1232
      valtext = ((String[])params.get("valtext"))[0];
1233
    } catch (Exception nullpe) {
1234 68 higgins
1235 309 bojilova
      Connection conn = null;
1236 162 bojilova
      String docid = null;
1237 103 jones
      try {
1238
        // Find the document id number
1239 185 jones
        docid = ((String[])params.get("docid"))[0];
1240 309 bojilova
1241
        // get a connection from the pool
1242
        conn = util.getConnection();
1243 393 jones
1244 309 bojilova
        // Get the document indicated from the db
1245 393 jones
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
1246
        valtext = xmldoc.toString();
1247 185 jones
1248 103 jones
      } catch (NullPointerException npe) {
1249 253 jones
        response.setContentType("text/xml");
1250
        out.println("<error>Error getting document ID: " + docid + "</error>");
1251 320 bojilova
        if ( conn != null ) { util.returnConnection(conn); }
1252 380 jones
        return;
1253 309 bojilova
      } catch (Exception e) {
1254
        response.setContentType("text/html");
1255
        out.println(e.getMessage());
1256
      } finally {
1257 320 bojilova
        util.returnConnection(conn);
1258 309 bojilova
      }
1259 103 jones
    }
1260 68 higgins
1261 309 bojilova
    Connection conn = null;
1262 103 jones
    try {
1263 309 bojilova
      // get a connection from the pool
1264
      conn = util.getConnection();
1265 253 jones
      DBValidate valobj = new DBValidate(saxparser,conn);
1266 185 jones
      boolean valid = valobj.validateString(valtext);
1267 68 higgins
1268
      // set content type and other response header fields first
1269 253 jones
      response.setContentType("text/xml");
1270
      out.println(valobj.returnErrors());
1271
1272 103 jones
    } catch (NullPointerException npe2) {
1273
      // set content type and other response header fields first
1274 253 jones
      response.setContentType("text/xml");
1275
      out.println("<error>Error validating document.</error>");
1276 309 bojilova
    } catch (Exception e) {
1277
      response.setContentType("text/html");
1278
      out.println(e.getMessage());
1279
    } finally {
1280 320 bojilova
      util.returnConnection(conn);
1281 309 bojilova
    }
1282 103 jones
  }
1283 731 bojilova
  // END OF VALIDATE SECTION
1284
1285
  // OTHER ACTION HANDLERS
1286 302 bojilova
1287
  /**
1288 688 bojilova
   * Handle "getaccesscontrol" action.
1289
   * Read Access Control List from db connection in XML format
1290
   */
1291
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
1292
                                       HttpServletResponse response,
1293 802 bojilova
                                       String username, String[] groupnames) {
1294 688 bojilova
1295
    Connection conn = null;
1296
    String docid = ((String[])params.get("docid"))[0];
1297
1298
    try {
1299
1300
        // get connection from the pool
1301
        conn = util.getConnection();
1302
        AccessControlList aclobj = new AccessControlList(conn);
1303 802 bojilova
        String acltext = aclobj.getACL(docid, username, groupnames);
1304 688 bojilova
        out.println(acltext);
1305
1306
    } catch (Exception e) {
1307
      out.println("<?xml version=\"1.0\"?>");
1308
      out.println("<error>");
1309
      out.println(e.getMessage());
1310
      out.println("</error>");
1311
    } finally {
1312
      util.returnConnection(conn);
1313
    }
1314
1315
  }
1316
1317
  /**
1318 731 bojilova
   * Handle the "getprincipals" action.
1319
   * Read all principals from authentication scheme in XML format
1320
   */
1321
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1322
                                         String password) {
1323
1324
    Connection conn = null;
1325
1326
    try {
1327
1328
        // get connection from the pool
1329
        AuthSession auth = new AuthSession();
1330
        String principals = auth.getPrincipals(user, password);
1331
        out.println(principals);
1332
1333
    } catch (Exception e) {
1334
      out.println("<?xml version=\"1.0\"?>");
1335
      out.println("<error>");
1336
      out.println(e.getMessage());
1337
      out.println("</error>");
1338
    } finally {
1339
      util.returnConnection(conn);
1340
    }
1341
1342
  }
1343
1344
  /**
1345 688 bojilova
   * Handle "getdoctypes" action.
1346 302 bojilova
   * Read all doctypes from db connection in XML format
1347
   */
1348
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1349
                                       HttpServletResponse response) {
1350
1351 309 bojilova
    Connection conn = null;
1352
1353 302 bojilova
    try {
1354
1355 309 bojilova
        // get connection from the pool
1356
        conn = util.getConnection();
1357
        DBUtil dbutil = new DBUtil(conn);
1358 302 bojilova
        String doctypes = dbutil.readDoctypes();
1359
        out.println(doctypes);
1360
1361
    } catch (Exception e) {
1362
      out.println("<?xml version=\"1.0\"?>");
1363
      out.println("<error>");
1364
      out.println(e.getMessage());
1365
      out.println("</error>");
1366 309 bojilova
    } finally {
1367 320 bojilova
      util.returnConnection(conn);
1368 309 bojilova
    }
1369 302 bojilova
1370
  }
1371
1372
  /**
1373 699 bojilova
   * Handle the "getdtdschema" action.
1374
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1375
   */
1376
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1377
                                        HttpServletResponse response) {
1378
1379
    Connection conn = null;
1380
    String doctype = null;
1381
    String[] doctypeArr = (String[])params.get("doctype");
1382
1383
    // get only the first doctype specified in the list of doctypes
1384
    // it could be done for all doctypes in that list
1385
    if (doctypeArr != null) {
1386
        doctype = ((String[])params.get("doctype"))[0];
1387
    }
1388
1389
    try {
1390
1391
        // get connection from the pool
1392
        conn = util.getConnection();
1393
        DBUtil dbutil = new DBUtil(conn);
1394
        String dtdschema = dbutil.readDTDSchema(doctype);
1395
        out.println(dtdschema);
1396
1397
    } catch (Exception e) {
1398
      out.println("<?xml version=\"1.0\"?>");
1399
      out.println("<error>");
1400
      out.println(e.getMessage());
1401
      out.println("</error>");
1402
    } finally {
1403
      util.returnConnection(conn);
1404
    }
1405
1406
  }
1407
1408
  /**
1409 688 bojilova
   * Handle the "getdataguide" action.
1410 302 bojilova
   * Read Data Guide for a given doctype from db connection in XML format
1411
   */
1412
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
1413
                                        HttpServletResponse response) {
1414
1415 309 bojilova
    Connection conn = null;
1416 316 bojilova
    String doctype = null;
1417
    String[] doctypeArr = (String[])params.get("doctype");
1418 309 bojilova
1419 316 bojilova
    // get only the first doctype specified in the list of doctypes
1420
    // it could be done for all doctypes in that list
1421
    if (doctypeArr != null) {
1422
        doctype = ((String[])params.get("doctype"))[0];
1423
    }
1424
1425 302 bojilova
    try {
1426
1427 309 bojilova
        // get connection from the pool
1428
        conn = util.getConnection();
1429
        DBUtil dbutil = new DBUtil(conn);
1430 316 bojilova
        String dataguide = dbutil.readDataGuide(doctype);
1431 302 bojilova
        out.println(dataguide);
1432
1433
    } catch (Exception e) {
1434
      out.println("<?xml version=\"1.0\"?>");
1435
      out.println("<error>");
1436
      out.println(e.getMessage());
1437
      out.println("</error>");
1438 309 bojilova
    } finally {
1439 320 bojilova
      util.returnConnection(conn);
1440 309 bojilova
    }
1441 302 bojilova
1442
  }
1443
1444 793 bojilova
  /**
1445
   * Handle the "getlastdocid" action.
1446
   * Get the latest docid with rev number from db connection in XML format
1447
   */
1448 847 jones
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
1449 793 bojilova
                                        HttpServletResponse response) {
1450
1451
    Connection conn = null;
1452 847 jones
    String scope = ((String[])params.get("scope"))[0];
1453
    if (scope == null) {
1454
        scope = ((String[])params.get("username"))[0];
1455
    }
1456 793 bojilova
1457
    try {
1458
1459
        // get connection from the pool
1460
        conn = util.getConnection();
1461
        DBUtil dbutil = new DBUtil(conn);
1462 847 jones
        String lastDocid = dbutil.getMaxDocid(scope);
1463 793 bojilova
        out.println("<?xml version=\"1.0\"?>");
1464
        out.println("<lastDocid>");
1465 847 jones
        out.println("  <scope>" + scope + "</scope>");
1466 793 bojilova
        out.println("  <docid>" + lastDocid + "</docid>");
1467
        out.println("</lastDocid>");
1468
1469
    } catch (Exception e) {
1470
      out.println("<?xml version=\"1.0\"?>");
1471
      out.println("<error>");
1472
      out.println(e.getMessage());
1473
      out.println("</error>");
1474
    } finally {
1475
      util.returnConnection(conn);
1476
    }
1477
1478
  }
1479
1480 798 jones
  /**
1481
   * Handle documents passed to metacat that are encoded using the
1482
   * "multipart/form-data" mime type.  This is typically used for uploading
1483
   * data files which may be binary and large.
1484
   */
1485
  private void handleMultipartForm(HttpServletRequest request,
1486
                                   HttpServletResponse response)
1487
  {
1488
    PrintWriter out = null;
1489
    String action = null;
1490
1491
    // Parse the multipart form, and save the parameters in a Hashtable and
1492
    // save the FileParts in a hashtable
1493
1494
    Hashtable params = new Hashtable();
1495
    Hashtable fileList = new Hashtable();
1496
1497
    try {
1498
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1499
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); // 200MB
1500
      Part part;
1501
      while ((part = mp.readNextPart()) != null) {
1502
        String name = part.getName();
1503
1504
        if (part.isParam()) {
1505
          // it's a parameter part
1506
          ParamPart paramPart = (ParamPart) part;
1507
          String value = paramPart.getStringValue();
1508
          params.put(name, value);
1509
          if (name.equals("action")) {
1510
            action = value;
1511
          }
1512
        } else if (part.isFile()) {
1513
          // it's a file part
1514
          FilePart filePart = (FilePart) part;
1515
          fileList.put(name, filePart);
1516
1517
          // Stop once the first file part is found, otherwise going onto the
1518
          // next part prevents access to the file contents.  So...for upload
1519
          // to work, the datafile must be the last part
1520
          break;
1521
        }
1522
      }
1523
    } catch (IOException ioe) {
1524
      try {
1525
        out = response.getWriter();
1526
      } catch (IOException ioe2) {
1527
        System.err.println("Fatal Error: couldn't get response output stream.");
1528
      }
1529
      out.println("<?xml version=\"1.0\"?>");
1530
      out.println("<error>");
1531
      out.println("Error: problem reading multipart data.");
1532
      out.println("</error>");
1533
    }
1534
1535
    // Get the session information
1536
    String username = null;
1537
    String password = null;
1538 802 bojilova
    String[] groupnames = null;
1539 798 jones
    String sess_id = null;
1540
1541
    // be aware of session expiration on every request
1542
    HttpSession sess = request.getSession(true);
1543
    if (sess.isNew()) {
1544
      // session expired or has not been stored b/w user requests
1545
      username = "public";
1546
      sess.setAttribute("username", username);
1547
    } else {
1548
      username = (String)sess.getAttribute("username");
1549
      password = (String)sess.getAttribute("password");
1550 802 bojilova
      groupnames = (String[])sess.getAttribute("groupnames");
1551 798 jones
      try {
1552
        sess_id = (String)sess.getId();
1553
      } catch(IllegalStateException ise) {
1554
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1555
                           "happen: the session should be valid: " +
1556
                           ise.getMessage());
1557
      }
1558
    }
1559
1560
    if ( action.equals("upload")) {
1561
      if (username != null &&  !username.equals("public")) {
1562
        handleUploadAction(request, response, params, fileList,
1563 802 bojilova
                           username, groupnames);
1564 798 jones
      } else {
1565
        try {
1566
          out = response.getWriter();
1567
        } catch (IOException ioe2) {
1568
          System.err.println("Fatal Error: couldn't get response output stream.");
1569
        }
1570
        out.println("<?xml version=\"1.0\"?>");
1571
        out.println("<error>");
1572
        out.println("Permission denied for " + action);
1573
        out.println("</error>");
1574
      }
1575
    } else {
1576
      try {
1577
        out = response.getWriter();
1578
      } catch (IOException ioe2) {
1579
        System.err.println("Fatal Error: couldn't get response output stream.");
1580
      }
1581
      out.println("<?xml version=\"1.0\"?>");
1582
      out.println("<error>");
1583
      out.println("Error: action not registered.  Please report this error.");
1584
      out.println("</error>");
1585
    }
1586
  }
1587
1588
  /**
1589
   * Handle the upload action by saving the attached file to disk and
1590
   * registering it in the Metacat db
1591
   */
1592
  private void handleUploadAction(HttpServletRequest request,
1593
                                  HttpServletResponse response,
1594
                                  Hashtable params, Hashtable fileList,
1595 802 bojilova
                                  String username, String[] groupnames)
1596 798 jones
  {
1597
    PrintWriter out = null;
1598
    Connection conn = null;
1599
    String action = null;
1600
    String docid = null;
1601
1602
    response.setContentType("text/xml");
1603
    try {
1604
      out = response.getWriter();
1605
    } catch (IOException ioe2) {
1606
      System.err.println("Fatal Error: couldn't get response output stream.");
1607
    }
1608
1609
    if (params.containsKey("docid")) {
1610
      docid = (String)params.get("docid");
1611
    }
1612
1613
    // Make sure we have a docid and datafile
1614
    if (docid != null && fileList.containsKey("datafile")) {
1615
1616
      // Get a reference to the file part of the form
1617
      FilePart filePart = (FilePart)fileList.get("datafile");
1618
      String fileName = filePart.getFileName();
1619
      MetaCatUtil.debugMessage("Uploading filename: " + fileName);
1620
1621
      // Check if the right file existed in the uploaded data
1622
      if (fileName != null) {
1623
1624
        try {
1625
          // register the file in the database (which generates an exception if
1626
          // the docid is not acceptable or other untoward things happen
1627
          DocumentImpl.registerDocument(fileName, "BIN", docid, username, 1);
1628
1629
          // Save the data file to disk using "docid" as the name
1630
          dataDirectory.mkdirs();
1631
          File newFile = new File(dataDirectory, docid);
1632
          long size = filePart.writeTo(newFile);
1633
1634
          // set content type and other response header fields first
1635
          out.println("<?xml version=\"1.0\"?>");
1636
          out.println("<success>");
1637
          out.println("<docid>" + docid + "</docid>");
1638
          out.println("<size>" + size + "</size>");
1639
          out.println("</success>");
1640
1641
        } catch (Exception e) {
1642
          out.println("<?xml version=\"1.0\"?>");
1643
          out.println("<error>");
1644
          out.println(e.getMessage());
1645
          out.println("</error>");
1646
        }
1647
      } else {
1648
        // the field did not contain a file
1649
        out.println("<?xml version=\"1.0\"?>");
1650
        out.println("<error>");
1651
        out.println("The uploaded data did not contain a valid file.");
1652
        out.println("</error>");
1653
      }
1654
    } else {
1655
      // Error bcse docid missing or file missing
1656
      out.println("<?xml version=\"1.0\"?>");
1657
      out.println("<error>");
1658
      out.println("The uploaded data did not contain a valid docid " +
1659
                  "or valid file.");
1660
      out.println("</error>");
1661
    }
1662
  }
1663 46 jones
}