Project

General

Profile

1
/**
2
 *  '$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
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2001-07-20 11:23:06 -0700 (Fri, 20 Jul 2001) $'
11
 * '$Revision: 800 $'
12
 *
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
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
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
import java.io.File;
36
import java.io.PrintWriter;
37
import java.io.IOException;
38
import java.io.StringReader;
39
import java.io.FileInputStream;
40
import java.io.BufferedInputStream;
41
import java.util.Enumeration;
42
import java.util.Hashtable;
43
import java.util.ResourceBundle; 
44
import java.util.Random;
45
import java.util.PropertyResourceBundle;
46
import java.net.URL;
47
import java.net.MalformedURLException;
48
import java.sql.PreparedStatement;
49
import java.sql.ResultSet;
50
import java.sql.Connection;
51
import java.sql.SQLException;
52
import java.lang.reflect.*;
53
import java.net.*;
54
import java.util.zip.*;
55

    
56
import javax.servlet.ServletConfig;
57
import javax.servlet.ServletContext;
58
import javax.servlet.ServletException;
59
import javax.servlet.ServletInputStream;
60
import javax.servlet.http.HttpServlet;
61
import javax.servlet.http.HttpServletRequest;
62
import javax.servlet.http.HttpServletResponse;
63
import javax.servlet.http.HttpSession;
64
import javax.servlet.http.HttpUtils;
65
import javax.servlet.ServletOutputStream;
66

    
67
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
import org.xml.sax.SAXException;
73

    
74
/**
75
 * A metadata catalog server implemented as a Java Servlet
76
 *
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
 * action=squery -- structured query (see pathquery.dtd)<br>
81
 * action=read -- read any metadata/data file from Metacat and from Internet<br>
82
 * 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
 * qformat=xml -- display resultset from query in XML<br>
88
 * qformat=html -- display resultset from query in HTML<br>
89
 * qformat=zip -- zip resultset from query<br>
90
 * docid=34 -- display the document with the document ID number 34<br>
91
 * doctext -- XML text of the document to load into the database<br>
92
 * 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
 * query -- actual query text (to go with 'action=query' or 'action=squery')<br>
95
 * valtext -- XML text to be validated<br>
96
 * abstractpath -- XPath in metadata document to read from<br>
97
 * action=getaccesscontrol -- retrieve acl info for Metacat document<br>
98
 * action=getdoctypes -- retrieve all doctypes (publicID)<br>
99
 * action=getdtdschema -- retrieve a DTD or Schema file<br>
100
 * action=getdataguide -- retrieve a Data Guide<br>
101
 * action=getprincipals -- retrieve a list of principals in XML<br>
102
 * 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
 */
108
public class MetaCatServlet extends HttpServlet {
109

    
110
  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
  private String datafilepath = null; 
117
  private File dataDirectory = null;
118
  private String servletpath = null; 
119
  private PropertyResourceBundle options = null;
120
  private MetaCatUtil util = null;
121

    
122
  // path to directory where data files 
123
  // that can be downloaded will be stored
124
  private String htmlpath = null; 
125
  // script to get data file and put it 
126
  // in defaultdocpath dir
127
  //private String executescript  = null;  
128

    
129
  /**
130
   * Initialize the servlet by creating appropriate database connections
131
   */
132
  public void init( ServletConfig config ) throws ServletException {
133
    try {
134
      super.init( config );
135
      this.config = config;
136
      this.context = config.getServletContext(); 
137
      System.out.println("MetaCatServlet Initialize");
138

    
139
      util = new MetaCatUtil();
140

    
141
      // Get the configuration file information
142
      resultStyleURL = util.getOption("resultStyleURL");
143
      xmlcatalogfile = util.getOption("xmlcatalogfile");
144
      saxparser = util.getOption("saxparser");
145
      datafilepath = util.getOption("datafilepath");
146
      dataDirectory = new File(datafilepath);
147
      //executescript = util.getOption("executescript"); 
148
      servletpath = util.getOption("servletpath");
149
      htmlpath = util.getOption("htmlpath");
150

    
151
// MOVED IT TO doGet() & doPost()
152
//      try {
153
//        // Open a pool of db connections
154
//        connectionPool = util.getConnectionPool();
155
//      } catch (Exception e) {
156
//        System.err.println("Error creating pool of database connections");
157
//        System.err.println(e.getMessage());
158
//      }
159
    } catch ( ServletException ex ) {
160
      throw ex;
161
    }
162
  }
163

    
164
  /**
165
   * Close all db connections from the pool
166
   */
167
  public void destroy() {
168
    
169
    if (util != null) {
170
        util.closeConnections();
171
    }
172
  }
173

    
174
  /** Handle "GET" method requests from HTTP clients */
175
  public void doGet (HttpServletRequest request, HttpServletResponse response)
176
    throws ServletException, IOException {
177

    
178
    // Process the data and send back the response
179
    handleGetOrPost(request, response);
180
  }
181

    
182
  /** Handle "POST" method requests from HTTP clients */
183
  public void doPost( HttpServletRequest request, HttpServletResponse response)
184
    throws ServletException, IOException {
185

    
186
    // Process the data and send back the response
187
    handleGetOrPost(request, response);
188
  }
189

    
190
  /**
191
   * Control servlet response depending on the action parameter specified
192
   */
193
  private void handleGetOrPost(HttpServletRequest request, 
194
                               HttpServletResponse response) 
195
                               throws ServletException, IOException 
196
  {
197

    
198
    if ( util == null ) {
199
        util = new MetaCatUtil(); 
200
    }
201
    if ( connectionPool.isEmpty() ) {
202
      try {
203
        // Open a pool of db connections
204
        connectionPool = util.getConnectionPool();
205
      } catch (Exception e) {
206
        System.err.println("Error creating pool of database connections in " +
207
                            " MetaCatServlet.handleGetOrPost");
208
        System.err.println(e.getMessage());
209
      }
210
    }    
211
    // Get a handle to the output stream back to the client
212
    //PrintWriter pwout = response.getWriter();
213
    //response.setContentType("text/html");
214

    
215
    // Deal with forms that are encoded as "multipart/form-data" differently
216
    // this is mainly used for uploading non-xml files using that may be binary
217
    String ctype = request.getContentType();
218
    if (ctype != null && ctype.startsWith("multipart/form-data")) {
219
      handleMultipartForm(request, response);
220
    } else {
221
      // This probably means the data is "application/x-www-url-encoded", we hope :-)
222
  
223
      String name = null;
224
      String[] value = null;
225
      String[] docid = new String[3];
226
      Hashtable params = new Hashtable();
227
      Enumeration paramlist = request.getParameterNames();
228
      while (paramlist.hasMoreElements()) {
229
        name = (String)paramlist.nextElement();
230
        value = request.getParameterValues(name);
231
  
232
        // Decode the docid and mouse click information
233
        if (name.endsWith(".y")) {
234
          docid[0] = name.substring(0,name.length()-2);
235
          params.put("docid", docid);
236
          name = "ypos";
237
        }
238
        if (name.endsWith(".x")) {
239
          name = "xpos";
240
        } 
241
  
242
        params.put(name,value); 
243
      }  
244
      
245
      //if the user clicked on the input images, decode which image
246
      //was clicked then set the action.
247
      String action = ((String[])params.get("action"))[0];  
248
      util.debugMessage("Line 213: Action is: " + action);
249
  
250
      // This block handles session management for the servlet
251
      // by looking up the current session information for all actions
252
      // other than "login" and "logout"
253
      String username = null;
254
      String password = null;
255
      String groupname = null;
256
      String sess_id = null;
257
  
258
      // handle login action
259
      if (action.equals("login")) {
260
  
261
        handleLoginAction(response.getWriter(), params, request, response);
262
  
263
      // handle logout action  
264
      } else if (action.equals("logout")) {
265
  
266
        handleLogoutAction(response.getWriter(), params, request, response);
267
  
268
      // aware of session expiration on every request  
269
      } else {   
270
  
271
        HttpSession sess = request.getSession(true);
272
        if (sess.isNew()) { 
273
          // session expired or has not been stored b/w user requests
274
          username = "public";
275
          sess.setAttribute("username", username);
276
        } else {
277
          username = (String)sess.getAttribute("username");
278
          password = (String)sess.getAttribute("password");
279
          groupname = (String)sess.getAttribute("groupname");
280
          try {
281
            sess_id = (String)sess.getId();
282
          } catch(IllegalStateException ise) {
283
            System.out.println("error in handleGetOrPost: this shouldn't " +
284
                               "happen: the session should be valid: " + 
285
                               ise.getMessage());
286
          }
287
        }  
288
      }    
289
  
290
      // Now that we know the session is valid, we can delegate the request
291
      // to a particular action handler
292
      if(action.equals("query")) {
293
        handleQuery(response.getWriter(), params, response, username, groupname); 
294
      } else if(action.equals("squery")) {
295
        if(params.containsKey("query")) {
296
          handleSQuery(response.getWriter(), params, response, username, groupname); 
297
        } else {
298
          PrintWriter out = response.getWriter();
299
          out.println("Illegal action squery without \"query\" parameter");
300
        }
301
      } else if (action.equals("read")) {
302
        handleReadAction(params, response, username, groupname);
303
      } else if (action.equals("insert") || action.equals("update")) {
304
        PrintWriter out = response.getWriter();
305
        if ( (username != null) &&  !username.equals("public") ) {
306
          handleInsertOrUpdateAction(out, params, response, username, groupname);
307
        } else {  
308
          out.println("Permission denied for " + action);
309
        }  
310
      } else if (action.equals("delete")) {
311
        PrintWriter out = response.getWriter();
312
        if ( (username != null) &&  !username.equals("public") ) {
313
          handleDeleteAction(out, params, response, username, groupname);
314
        } else {  
315
          out.println("Permission denied for " + action);
316
        }  
317
      } else if (action.equals("validate")) {
318
        PrintWriter out = response.getWriter();
319
        handleValidateAction(out, params, response); 
320
      } else if (action.equals("getaccesscontrol")) {
321
        PrintWriter out = response.getWriter();
322
        handleGetAccessControlAction(out, params, response, username, groupname);
323
      } else if (action.equals("getprincipals")) {
324
        PrintWriter out = response.getWriter();
325
        handleGetPrincipalsAction(out, username, password);  
326
      } else if (action.equals("getdoctypes")) {
327
        PrintWriter out = response.getWriter();
328
        handleGetDoctypesAction(out, params, response);  
329
      } else if (action.equals("getdtdschema")) {
330
        PrintWriter out = response.getWriter();
331
        handleGetDTDSchemaAction(out, params, response);  
332
      } else if (action.equals("getdataguide")) {
333
        PrintWriter out = response.getWriter();
334
        handleGetDataGuideAction(out, params, response);  
335
      } else if (action.equals("getlastdocid")) {
336
        PrintWriter out = response.getWriter();
337
        handleGetLastDocidAction(out, params, response);  
338
      } else if (action.equals("login") || action.equals("logout")) {
339
      } else if (action.equals("protocoltest")) {
340
        String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
341
        try {
342
          testURL = ((String[])params.get("url"))[0];
343
        } catch (Throwable t) {
344
        }
345
        String phandler = System.getProperty("java.protocol.handler.pkgs");
346
        response.setContentType("text/html");
347
        PrintWriter out = response.getWriter();
348
        out.println("<body bgcolor=\"white\">");
349
        out.println("<p>Handler property: <code>" + phandler + "</code></p>");
350
        out.println("<p>Starting test for:<br>");
351
        out.println("    " + testURL + "</p>");
352
        try {
353
          URL u = new URL(testURL);
354
          out.println("<pre>");
355
          out.println("Protocol: " + u.getProtocol());
356
          out.println("    Host: " + u.getHost());
357
          out.println("    Port: " + u.getPort());
358
          out.println("    Path: " + u.getPath());
359
          out.println("     Ref: " + u.getRef());
360
          String pquery = u.getQuery();
361
          out.println("   Query: " + pquery);
362
          out.println("  Params: ");
363
          if (pquery != null) {
364
            Hashtable qparams = util.parseQuery(u.getQuery());
365
            for (Enumeration en = qparams.keys(); en.hasMoreElements(); ) {
366
              String pname = (String)en.nextElement();
367
              String pvalue = (String)qparams.get(pname);
368
              out.println("    " + pname + ": " + pvalue);
369
            }
370
          }
371
          out.println("</pre>");
372
          out.println("</body>");
373
          out.close();
374
        } catch (MalformedURLException mue) {
375
          System.out.println("bad url from MetacatServlet.handleGetOrPost");
376
          out.println(mue.getMessage());
377
          mue.printStackTrace(out);
378
          out.close();
379
        }
380
      } else {
381
        PrintWriter out = response.getWriter();
382
        out.println("<?xml version=\"1.0\"?>");
383
        out.println("<error>");
384
        out.println("Error: action not registered.  Please report this error.");
385
        out.println("</error>");
386
      }
387
      
388
      util.closeConnections();
389
      // Close the stream to the client
390
      // out.close();
391
    }
392
  }
393
  
394
  // LOGIN & LOGOUT SECTION
395
  /** 
396
   * Handle the login request. Create a new session object.
397
   * Do user authentication through the session.
398
   */
399
  private void handleLoginAction(PrintWriter out, Hashtable params, 
400
               HttpServletRequest request, HttpServletResponse response) {
401

    
402
    AuthSession sess = null;
403
    String un = ((String[])params.get("username"))[0];
404
    String pw = ((String[])params.get("password"))[0];
405
    String action = ((String[])params.get("action"))[0];
406
    String qformat = ((String[])params.get("qformat"))[0];
407
    
408
    try {
409
      sess = new AuthSession();
410
    } catch (Exception e) {
411
      System.out.println("error in MetacatServlet.handleLoginAction: " +
412
                          e.getMessage());
413
      out.println(e.getMessage());
414
      return;
415
    }
416
    
417
    boolean isValid = sess.authenticate(request, un, pw);
418

    
419
    // format and transform the output
420
    if (qformat.equals("html")) {
421
      Connection conn = null;
422
      try {
423
        conn = util.getConnection();
424
        DBTransform trans = new DBTransform(conn);
425
        response.setContentType("text/html");
426
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
427
                                   "-//W3C//HTML//EN", out);
428
        util.returnConnection(conn); 
429
      } catch(Exception e) {
430
        util.returnConnection(conn); 
431
      } 
432
      
433
    // any output is returned  
434
    } else {
435
      response.setContentType("text/xml");
436
      out.println(sess.getMessage()); 
437
    }
438
  }    
439

    
440
  /** 
441
   * Handle the logout request. Close the connection.
442
   */
443
  private void handleLogoutAction(PrintWriter out, Hashtable params, 
444
               HttpServletRequest request, HttpServletResponse response) {
445

    
446
    String qformat = ((String[])params.get("qformat"))[0];
447

    
448
    // close the connection
449
    HttpSession sess = request.getSession(false);
450
    if (sess != null) { sess.invalidate();  }    
451

    
452
    // produce output
453
    StringBuffer output = new StringBuffer();
454
    output.append("<?xml version=\"1.0\"?>");
455
    output.append("<logout>");
456
    output.append("User logged out");
457
    output.append("</logout>");
458

    
459
    //format and transform the output
460
    if (qformat.equals("html")) {
461
      Connection conn = null;
462
      try {
463
        conn = util.getConnection();
464
        DBTransform trans = new DBTransform(conn);
465
        response.setContentType("text/html");
466
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN", 
467
                                   "-//W3C//HTML//EN", out);
468
        util.returnConnection(conn); 
469
      } catch(Exception e) {
470
        util.returnConnection(conn); 
471
      } 
472
    // any output is returned  
473
    } else {
474
      response.setContentType("text/xml");
475
      out.println(output.toString()); 
476
    }
477
  }
478
  // END OF LOGIN & LOGOUT SECTION
479
  
480
  // SQUERY & QUERY SECTION
481
  /**      
482
   * Retreive the squery xml, execute it and display it
483
   *
484
   * @param out the output stream to the client
485
   * @param params the Hashtable of parameters that should be included
486
   * in the squery.
487
   * @param response the response object linked to the client
488
   * @param conn the database connection 
489
   */
490
  protected void handleSQuery(PrintWriter out, Hashtable params, 
491
                 HttpServletResponse response, String user, String group)
492
  { 
493
    String xmlquery = ((String[])params.get("query"))[0];
494
    String qformat = ((String[])params.get("qformat"))[0];
495
    String resultdoc = null;
496
    
497
    Hashtable doclist = runQuery(xmlquery, user, group);
498

    
499
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
500
    
501
    //format and transform the results                                        
502
    if(qformat.equals("html")) {
503
      transformResultset(resultdoc, response, out);
504
    } else if(qformat.equals("xml")) {
505
      response.setContentType("text/xml");
506
      out.println(resultdoc);
507
    } else {
508
      out.println("invalid qformat: " + qformat); 
509
    }
510
  }
511
  
512
   /**
513
    * Create the xml query, execute it and display the results.
514
    *
515
    * @param out the output stream to the client
516
    * @param params the Hashtable of parameters that should be included
517
    * in the squery.
518
    * @param response the response object linked to the client
519
    */ 
520
  protected void handleQuery(PrintWriter out, Hashtable params, 
521
                 HttpServletResponse response, String user, String group)
522
  {
523
    //create the query and run it
524
    String xmlquery = DBQuery.createSQuery(params);
525
    Hashtable doclist = runQuery(xmlquery, user, group);
526
    String qformat = ((String[])params.get("qformat"))[0];
527
    String resultdoc = null;
528
    
529
    resultdoc = createResultDocument(doclist, transformQuery(params));
530

    
531
    //format and transform the results                                        
532
    if(qformat.equals("html")) {
533
      transformResultset(resultdoc, response, out);
534
    } else if(qformat.equals("xml")) {
535
      response.setContentType("text/xml");
536
      out.println(resultdoc);
537
    } else { 
538
      out.println("invalid qformat: " + qformat); 
539
    }
540
  }
541
  
542
  /**
543
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
544
   * so it can properly be placed in the <query> tag of the resultset.
545
   * This method is overwritable so that other applications can customize
546
   * the structure of what is in the <query> tag.
547
   * 
548
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
549
   */
550
  protected String transformQuery(Hashtable params)
551
  {
552
    //DBQuery.createSQuery is a re-calling of a previously called 
553
    //function but it is necessary
554
    //so that overriding methods have access to the params hashtable
555
    String xmlquery = DBQuery.createSQuery(params);
556
    //the <?xml version="1.0"?> tag is the first 22 characters of the
557
    xmlquery = xmlquery.trim();
558
    int index = xmlquery.indexOf("?>");
559
    return xmlquery.substring(index + 2, xmlquery.length());
560
  }
561
  
562
  /**
563
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
564
   * string as a param instead of a hashtable.
565
   * 
566
   * @param xmlquery a string representing a query.
567
   */
568
  protected String transformQuery(String xmlquery)
569
  {
570
    xmlquery = xmlquery.trim();
571
    int index = xmlquery.indexOf("?>");
572
    return xmlquery.substring(index + 2, xmlquery.length());
573
  }
574
  
575
  /**
576
   * Run the query and return a hashtable of results.
577
   *
578
   * @param xmlquery the query to run
579
   */
580
  private Hashtable runQuery(String xmlquery, String user, String group)
581
  {
582
    Hashtable doclist=null;
583
    Connection conn = null;
584
    try
585
    {
586
      conn = util.getConnection();
587
      DBQuery queryobj = new DBQuery(conn, saxparser);
588
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,group);
589
      util.returnConnection(conn);
590
      return doclist;
591
    } 
592
    catch (Exception e) 
593
    {
594
      util.returnConnection(conn); 
595
      util.debugMessage("Error in MetacatServlet.runQuery: " + e.getMessage());
596
      doclist = null;
597
      return doclist;
598
    }    
599
  }
600
  
601
  /**
602
   * Transorms an xml resultset document to html and sends it to the browser
603
   *
604
   * @param resultdoc the string representation of the document that needs
605
   * to be transformed.
606
   * @param response the HttpServletResponse object bound to the client.
607
   * @param out the output stream to the client
608
   */ 
609
  protected void transformResultset(String resultdoc, 
610
                                    HttpServletResponse response,
611
                                    PrintWriter out)
612
  {
613
    Connection conn = null;
614
    try {
615
      conn = util.getConnection();
616
      DBTransform trans = new DBTransform(conn);
617
      response.setContentType("text/html");
618
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN", 
619
                                 "-//W3C//HTML//EN", out);
620
      util.returnConnection(conn); 
621
    }
622
    catch(Exception e)
623
    {
624
      util.returnConnection(conn); 
625
    } 
626
  }
627
  
628
  /**
629
   * Transforms a hashtable of documents to an xml or html result.
630
   *
631
   * @param doclist- the hashtable to transform
632
   * @param xmlquery- the query that returned the doclist result
633
   */
634
  protected String createResultDocument(Hashtable doclist, String xmlquery)
635
  {
636
    // Create a buffer to hold the xml result
637
    StringBuffer resultset = new StringBuffer();
638
 
639
    // Print the resulting root nodes 
640
    String docid = null;
641
    String document = null;
642
    resultset.append("<?xml version=\"1.0\"?>\n");
643
    resultset.append("<resultset>\n");
644
      
645
    resultset.append("  <query>" + xmlquery + "</query>");   
646

    
647
    if(doclist != null)
648
    {
649
      Enumeration doclistkeys = doclist.keys(); 
650
      while (doclistkeys.hasMoreElements()) 
651
      {
652
        docid = (String)doclistkeys.nextElement();
653
        document = (String)doclist.get(docid);
654
        resultset.append("  <document>" + document + "</document>");
655
      }
656
    }
657

    
658
    resultset.append("</resultset>");
659
    return resultset.toString();
660
  }
661
  // END OF SQUERY & QUERY SECTION
662
  
663
  // READ SECTION
664
  /** 
665
   * Handle the "read" request of metadata/data files from Metacat
666
   * or any files from Internet;
667
   * transformed metadata XML document into HTML presentation if requested;
668
   * zip files when more than one were requested.
669
   *
670
   * @param params the Hashtable of HTTP request parameters
671
   * @param response the HTTP response object linked to the client
672
   * @param user the username sent the request
673
   * @param group the user's groupname
674
   */
675
  private void handleReadAction(Hashtable params, HttpServletResponse response,
676
                                String user, String group) 
677
  {
678
    ServletOutputStream out = null;
679
    ZipOutputStream zout = null;
680
    
681
    try {
682
      String[] docs = new String[0];
683
      String docid = "";
684
      String qformat = "";
685
      String abstrpath = null;
686
      boolean zip = false;
687
      // read the params
688
      if (params.containsKey("docid")) {
689
        docs = (String[])params.get("docid");
690
      }
691
      if (params.containsKey("qformat")) {
692
        qformat = ((String[])params.get("qformat"))[0];
693
      }
694
      if (params.containsKey("abstractpath")) {
695
        abstrpath = ((String[])params.get("abstractpath"))[0];
696
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
697
          viewAbstract(response, abstrpath, docs[0]);
698
          return;
699
        }
700
      }
701
      if ( (docs.length > 1) || qformat.equals("zip") ) {
702
        zip = true;
703
        out = response.getOutputStream();
704
        response.setContentType("application/zip"); //MIME type
705
        zout = new ZipOutputStream(out);
706
      }
707
      // go through the list of docs to read
708
      for (int i=0; i < docs.length; i++ ) {
709
        try {
710

    
711
          URL murl = new URL(docs[i]);
712
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
713
          // case docid="http://.../?docid=aaa" 
714
          // or docid="metacat://.../?docid=bbb"
715
          if (murlQueryStr.containsKey("docid")) {
716
            // get only docid, eliminate the rest
717
            docid = (String)murlQueryStr.get("docid");
718
            if ( zip ) {
719
              addDocToZip(docid, zout);
720
            } else {
721
              readFromMetacat(response, docid, qformat, abstrpath,
722
                              user, group, zip, zout);
723
            }
724

    
725
          // case docid="http://.../filename"
726
          } else {
727
            docid = docs[i];
728
            if ( zip ) {
729
              addDocToZip(docid, zout);
730
            } else {
731
              readFromURLConnection(response, docid);
732
            }
733
          }
734

    
735
        // case docid="ccc"
736
        } catch (MalformedURLException mue) {
737
          docid = docs[i];
738
          if ( zip ) {
739
            addDocToZip(docid, zout);
740
          } else {
741
            readFromMetacat(response, docid, qformat, abstrpath,
742
                            user, group, zip, zout);
743
          }
744
        }
745
        
746
      } /* end for */
747
      
748
      if ( zip ) {
749
        zout.finish(); //terminate the zip file
750
        zout.close();  //close the zip stream
751
      }
752
      
753
    } catch (Exception e) {
754
      try {
755
        if ( out != null ) { out.close(); }
756
        if ( zout != null ) { zout.close(); }
757
        response.setContentType("text/xml"); //MIME type
758
        PrintWriter pw = response.getWriter();
759
        pw.println(e.getMessage());
760
      } catch (IOException ioe) {
761
        System.out.println("Problem with the servlet output " +
762
                           "in MetacatServlet.handleReadAction: " +
763
                           ioe.getMessage());
764
        ioe.printStackTrace(System.out);
765
        
766
      }
767

    
768
      System.out.println("Error in MetacatServlet.handleReadAction: " +
769
                         e.getMessage());
770
      e.printStackTrace(System.out);
771
    }
772
    
773
  }
774
  
775
  // read metadata or data from Metacat
776
  private void readFromMetacat(HttpServletResponse response, String docid,
777
                               String qformat, String abstrpath, String user,
778
                               String group, boolean zip, ZipOutputStream zout)
779
               throws ClassNotFoundException, IOException, SQLException, 
780
                      McdbException, Exception
781
  {
782
    Connection conn = null;
783
    try {
784
      conn = util.getConnection();
785
      DocumentImpl doc = new DocumentImpl(conn, docid);
786
      
787
      if ( doc.getRootNodeID() == 0 ) {
788
        // this is data file
789
        ServletOutputStream out = response.getOutputStream(); 
790
        String filepath = util.getOption("datafilepath");
791
        if(!filepath.endsWith("/")) {
792
          filepath += "/";
793
        }
794
        String filename = filepath + doc.getDocname();      //MIME type
795
        String contentType = getServletContext().getMimeType(filename);
796
        if (contentType == null) {
797
          if (filename.endsWith(".xml")) {
798
            contentType="text/xml";
799
          } else if (filename.endsWith(".css")) {
800
            contentType="text/css";
801
          } else if (filename.endsWith(".dtd")) {
802
            contentType="text/plain";
803
          } else if (filename.endsWith(".xsd")) {
804
            contentType="text/xml";
805
          } else if (filename.endsWith("/")) {
806
            contentType="text/html";
807
          } else {
808
            File f = new File(filename);
809
            if ( f.isDirectory() ) {
810
              contentType="text/html";
811
            } else {
812
              contentType="application/octet-stream";
813
            }
814
          }
815
        }
816
        response.setContentType(contentType);
817
        // if we decide to use "application/octet-stream" for all data returns
818
        // response.setContentType("application/octet-stream");
819
        FileInputStream fin = null;
820
        try {
821
          fin = new FileInputStream(filename);
822
          byte[] buf = new byte[4 * 1024]; // 4K buffer
823
          int b = fin.read(buf);
824
          while (b != -1) {
825
            out.write(buf, 0, b);
826
            b = fin.read(buf);
827
          }
828
        } finally {
829
          if (fin != null) fin.close();
830
        }
831

    
832
      } else {
833
        // this is metadata doc
834
        if ( qformat.equals("html") ) { 
835
          response.setContentType("text/html");  //MIME type
836
          PrintWriter out = response.getWriter();
837
    
838
          // Look up the document type
839
          String doctype = doc.getDoctype();
840
          // Transform the document to the new doctype
841
          DBTransform dbt = new DBTransform(conn);
842
          dbt.transformXMLDocument(doc.toString(),
843
                                   doctype,"-//W3C//HTML//EN",out);
844
        } else {
845
          // set content type first
846
          response.setContentType("text/xml");   //MIME type
847
          PrintWriter out = response.getWriter();
848
          doc.toXml(out);
849
        }
850
      
851
      }
852
    } finally {
853
      util.returnConnection(conn);
854
    }
855
    
856
  }
857
  
858
  // read data from URLConnection
859
  private void readFromURLConnection(HttpServletResponse response, String docid)
860
               throws IOException, MalformedURLException
861
  {
862
    ServletOutputStream out = response.getOutputStream(); 
863
    String contentType = getServletContext().getMimeType(docid); //MIME type
864
    if (contentType == null) {
865
      if (docid.endsWith(".xml")) {
866
        contentType="text/xml";
867
      } else if (docid.endsWith(".css")) {
868
        contentType="text/css";
869
      } else if (docid.endsWith(".dtd")) {
870
        contentType="text/plain";
871
      } else if (docid.endsWith(".xsd")) {
872
        contentType="text/xml";
873
      } else if (docid.endsWith("/")) {
874
        contentType="text/html";
875
      } else {
876
        File f = new File(docid);
877
        if ( f.isDirectory() ) {
878
          contentType="text/html";
879
        } else {
880
          contentType="application/octet-stream";
881
        }
882
      }
883
    }
884
    response.setContentType(contentType);
885
    // if we decide to use "application/octet-stream" for all data returns
886
    // response.setContentType("application/octet-stream");
887

    
888
    // this is http url
889
    URL url = new URL(docid);
890
    BufferedInputStream bis = null;
891
    try {
892
      bis = new BufferedInputStream(url.openStream());
893
      byte[] buf = new byte[4 * 1024]; // 4K buffer
894
      int b = bis.read(buf);
895
      while (b != -1) {
896
        out.write(buf, 0, b);
897
        b = bis.read(buf);
898
      }
899
    } finally {
900
      if (bis != null) bis.close();
901
    }
902
    
903
  }
904
  
905
  // read file/doc and write to ZipOutputStream
906
  private void addDocToZip(String docid, ZipOutputStream zout)
907
               throws ClassNotFoundException, IOException, SQLException, 
908
                      McdbException, Exception
909
  {
910
    byte[] bytestring = null;
911
    ZipEntry zentry = null;
912

    
913
    try {
914
      URL url = new URL(docid);
915

    
916
      // this http url; read from URLConnection; add to zip
917
      zentry = new ZipEntry(docid);
918
      zout.putNextEntry(zentry);
919
      BufferedInputStream bis = null;
920
      try {
921
        bis = new BufferedInputStream(url.openStream());
922
        byte[] buf = new byte[4 * 1024]; // 4K buffer
923
        int b = bis.read(buf);
924
        while(b != -1) {
925
          zout.write(buf, 0, b);
926
          b = bis.read(buf);
927
        }
928
      } finally {
929
        if (bis != null) bis.close();
930
      }
931
      zout.closeEntry();
932

    
933
    } catch (MalformedURLException mue) {
934
      
935
      // this is metacat doc (data file or metadata doc)
936
      Connection conn = null;
937
      try {
938
        conn = util.getConnection();
939
        DocumentImpl doc = new DocumentImpl(conn, docid);
940
      
941
        if ( doc.getRootNodeID() == 0 ) {
942
          // this is data file; add file to zip
943
          String filepath = util.getOption("datafilepath");
944
          if(!filepath.endsWith("/")) {
945
            filepath += "/";
946
          }
947
          String filename = filepath + doc.getDocname();
948
          zentry = new ZipEntry(filename);
949
          zout.putNextEntry(zentry);
950
          FileInputStream fin = null;
951
          try {
952
            fin = new FileInputStream(filename);
953
            byte[] buf = new byte[4 * 1024]; // 4K buffer
954
            int b = fin.read(buf);
955
            while (b != -1) {
956
              zout.write(buf, 0, b);
957
              b = fin.read(buf);
958
            }
959
          } finally {
960
            if (fin != null) fin.close();
961
          }
962
          zout.closeEntry();
963

    
964
        } else {
965
          // this is metadata doc; add doc to zip
966
          bytestring = doc.toString().getBytes();
967
          zentry = new ZipEntry(docid + ".xml");
968
          zentry.setSize(bytestring.length);
969
          zout.putNextEntry(zentry);
970
          zout.write(bytestring, 0, bytestring.length);
971
          zout.closeEntry();
972
        }
973
      } finally {
974
        util.returnConnection(conn);
975
      }
976
      
977
    }
978
      
979
  }
980
  
981
  // view abstract within document
982
  private void viewAbstract(HttpServletResponse response,
983
                            String abstractpath, String docid)
984
               throws ClassNotFoundException, IOException, SQLException,
985
                      McdbException, Exception
986
  {
987
    Connection conn = null;
988
    try {
989
      conn = util.getConnection();
990
    
991
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid, conn);
992
    
993
      response.setContentType("text/html");  //MIME type
994
      PrintWriter out = response.getWriter();
995
      out.println("<html><head><title>Abstract</title></head>");
996
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
997
      for (int i=0; i<abstracts.length; i++) {
998
        out.println("<p>" + (String)abstracts[i] + "</p>");
999
      }
1000
      out.println("</body></html>");
1001

    
1002
    } finally {
1003
      util.returnConnection(conn);
1004
    }
1005
  }
1006
  // END OF READ SECTION
1007
    
1008
  // INSERT/UPDATE SECTION
1009
  /** 
1010
   * Handle the database putdocument request and write an XML document 
1011
   * to the database connection
1012
   */
1013
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params, 
1014
               HttpServletResponse response, String user, String group) {
1015

    
1016
    Connection conn = null;
1017

    
1018
    try {
1019
      // Get the document indicated
1020
      String[] doctext = (String[])params.get("doctext");
1021

    
1022
      String pub = null;
1023
      if (params.containsKey("public")) {
1024
        pub = ((String[])params.get("public"))[0];
1025
      }
1026

    
1027
      StringReader dtd = null;
1028
      if (params.containsKey("dtdtext")) {
1029
        String[] dtdtext = (String[])params.get("dtdtext");
1030
        try {
1031
          if ( !dtdtext[0].equals("") ) {
1032
            dtd = new StringReader(dtdtext[0]);
1033
          }
1034
        } catch (NullPointerException npe) {}
1035
      }
1036
      
1037
      StringReader xml = null;
1038
      boolean validate = false;
1039
      try {
1040
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1041
        // in order to decide whether to use validation parser
1042
        validate = validateXML(doctext[0]);
1043
        xml = new StringReader(doctext[0]);
1044

    
1045
        String[] action = (String[])params.get("action");
1046
        String[] docid = (String[])params.get("docid");
1047
        String newdocid = null;
1048

    
1049
        String doAction = null;
1050
        if (action[0].equals("insert")) {
1051
          doAction = "INSERT";
1052
        } else if (action[0].equals("update")) {
1053
          doAction = "UPDATE";
1054
        }
1055

    
1056
        try {
1057
          // get a connection from the pool
1058
          conn = util.getConnection();
1059

    
1060
          // write the document to the database
1061
          try {
1062
            String accNumber = docid[0];
1063
            if (accNumber.equals("")) {
1064
              accNumber = null;
1065
            }
1066
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1067
                                          accNumber, user, group, validate);
1068
          } catch (NullPointerException npe) {
1069
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1070
                                          null, user, group, validate);
1071
          }
1072
        } finally {
1073
          util.returnConnection(conn);
1074
        }    
1075

    
1076
        // set content type and other response header fields first
1077
        response.setContentType("text/xml");
1078
        out.println("<?xml version=\"1.0\"?>");
1079
        out.println("<success>");
1080
        out.println("<docid>" + newdocid + "</docid>"); 
1081
        out.println("</success>");
1082

    
1083
      } catch (NullPointerException npe) {
1084
        response.setContentType("text/xml");
1085
        out.println("<?xml version=\"1.0\"?>");
1086
        out.println("<error>");
1087
        out.println(npe.getMessage()); 
1088
        out.println("</error>");
1089
      }
1090
    } catch (Exception e) {
1091
      response.setContentType("text/xml");
1092
      out.println("<?xml version=\"1.0\"?>");
1093
      out.println("<error>");
1094
      out.println(e.getMessage()); 
1095
      if (e instanceof SAXException) {
1096
        Exception e2 = ((SAXException)e).getException();
1097
        out.println("<error>");
1098
        try
1099
        {
1100
          out.println(e2.getMessage());
1101
        }
1102
        catch(NullPointerException npe)
1103
        {
1104
          out.println(e.getMessage());
1105
        }
1106
        out.println("</error>");
1107
      }
1108
      //e.printStackTrace(out);
1109
      out.println("</error>");
1110
    }
1111
  }
1112

    
1113
  /** 
1114
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1115
   * in order to decide whether to use validation parser
1116
   */
1117
  private static boolean validateXML(String xmltext) throws IOException {
1118
    
1119
    StringReader xmlreader = new StringReader(xmltext);
1120
    StringBuffer cbuff = new StringBuffer();
1121
    java.util.Stack st = new java.util.Stack();
1122
    boolean validate = false;
1123
    int c;
1124
    int inx;
1125
    
1126
    // read from the stream until find the keywords
1127
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1128
      cbuff.append((char)c);
1129

    
1130
      // "<!DOCTYPE" keyword is found; put it in the stack
1131
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1132
        cbuff = new StringBuffer();
1133
        st.push("<!DOCTYPE");
1134
      }
1135
      // "PUBLIC" keyword is found; put it in the stack
1136
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1137
        cbuff = new StringBuffer();
1138
        st.push("PUBLIC");
1139
      }
1140
      // "SYSTEM" keyword is found; put it in the stack
1141
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1142
        cbuff = new StringBuffer();
1143
        st.push("SYSTEM");
1144
      }
1145
      // ">" character is found; put it in the stack
1146
      // ">" is found twice: fisrt from <?xml ...?> 
1147
      // and second from <!DOCTYPE ... >
1148
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1149
        cbuff = new StringBuffer();
1150
        st.push(">");
1151
      }
1152
    }
1153

    
1154
    // close the stream
1155
    xmlreader.close();
1156

    
1157
    // check the stack whether it contains the keywords:
1158
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1159
    if ( st.size() == 4 ) {
1160
      if ( ((String)st.pop()).equals(">") &&
1161
           ( ((String)st.peek()).equals("PUBLIC") |
1162
             ((String)st.pop()).equals("SYSTEM") ) &&
1163
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1164
        validate = true;
1165
      }
1166
    }
1167

    
1168
System.out.println("Validation is " + validate);
1169
    return validate;
1170
  }
1171
  // END OF INSERT/UPDATE SECTION
1172

    
1173
  // DELETE SECTION
1174
  /** 
1175
   * Handle the database delete request and delete an XML document 
1176
   * from the database connection
1177
   */
1178
  private void handleDeleteAction(PrintWriter out, Hashtable params, 
1179
               HttpServletResponse response, String user, String group) {
1180

    
1181
    String[] docid = (String[])params.get("docid");
1182
    Connection conn = null;
1183

    
1184
    // delete the document from the database
1185
    try {
1186
      // get a connection from the pool
1187
      conn = util.getConnection();
1188
                                      // NOTE -- NEED TO TEST HERE
1189
                                      // FOR EXISTENCE OF DOCID PARAM
1190
                                      // BEFORE ACCESSING ARRAY
1191
      try { 
1192
        DocumentImpl.delete(conn, docid[0], user, group);
1193
        response.setContentType("text/xml");
1194
        out.println("<?xml version=\"1.0\"?>");
1195
        out.println("<success>");
1196
        out.println("Document deleted."); 
1197
        out.println("</success>");
1198
      } catch (AccessionNumberException ane) {
1199
        response.setContentType("text/xml");
1200
        out.println("<?xml version=\"1.0\"?>");
1201
        out.println("<error>");
1202
        out.println("Error deleting document!!!");
1203
        out.println(ane.getMessage()); 
1204
        out.println("</error>");
1205
      }
1206
    } catch (Exception e) {
1207
      response.setContentType("text/xml");
1208
      out.println("<?xml version=\"1.0\"?>");
1209
      out.println("<error>");
1210
      out.println(e.getMessage()); 
1211
      out.println("</error>");
1212
    } finally {
1213
      util.returnConnection(conn);
1214
    }  
1215
  }
1216
  // END OF DELETE SECTION
1217
  
1218
  // VALIDATE SECTION
1219
  /** 
1220
   * Handle the validation request and return the results to the requestor
1221
   */
1222
  private void handleValidateAction(PrintWriter out, Hashtable params, 
1223
               HttpServletResponse response) {
1224

    
1225
    // Get the document indicated
1226
    String valtext = null;
1227
    
1228
    try {
1229
      valtext = ((String[])params.get("valtext"))[0];
1230
    } catch (Exception nullpe) {
1231

    
1232
      Connection conn = null;
1233
      String docid = null;
1234
      try {
1235
        // Find the document id number
1236
        docid = ((String[])params.get("docid"))[0]; 
1237

    
1238
        // get a connection from the pool
1239
        conn = util.getConnection();
1240

    
1241
        // Get the document indicated from the db
1242
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
1243
        valtext = xmldoc.toString();
1244

    
1245
      } catch (NullPointerException npe) {
1246
        response.setContentType("text/xml");
1247
        out.println("<error>Error getting document ID: " + docid + "</error>");
1248
        if ( conn != null ) { util.returnConnection(conn); }
1249
        return;
1250
      } catch (Exception e) {
1251
        response.setContentType("text/html");
1252
        out.println(e.getMessage()); 
1253
      } finally {
1254
        util.returnConnection(conn);
1255
      }  
1256
    }
1257

    
1258
    Connection conn = null;
1259
    try {
1260
      // get a connection from the pool
1261
      conn = util.getConnection();
1262
      DBValidate valobj = new DBValidate(saxparser,conn);
1263
      boolean valid = valobj.validateString(valtext);
1264

    
1265
      // set content type and other response header fields first
1266
      response.setContentType("text/xml");
1267
      out.println(valobj.returnErrors());
1268

    
1269
    } catch (NullPointerException npe2) {
1270
      // set content type and other response header fields first
1271
      response.setContentType("text/xml");
1272
      out.println("<error>Error validating document.</error>"); 
1273
    } catch (Exception e) {
1274
      response.setContentType("text/html");
1275
      out.println(e.getMessage()); 
1276
    } finally {
1277
      util.returnConnection(conn);
1278
    }  
1279
  }
1280
  // END OF VALIDATE SECTION
1281
 
1282
  // OTHER ACTION HANDLERS
1283
  
1284
  /** 
1285
   * Handle "getaccesscontrol" action.
1286
   * Read Access Control List from db connection in XML format
1287
   */
1288
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params, 
1289
                                       HttpServletResponse response, 
1290
                                       String username, String groupname) {
1291

    
1292
    Connection conn = null;
1293
    String docid = ((String[])params.get("docid"))[0];
1294
    
1295
    try {
1296

    
1297
        // get connection from the pool
1298
        conn = util.getConnection();
1299
        AccessControlList aclobj = new AccessControlList(conn);
1300
        String acltext = aclobj.getACL(docid, username, groupname);
1301
        out.println(acltext);
1302

    
1303
    } catch (Exception e) {
1304
      out.println("<?xml version=\"1.0\"?>");
1305
      out.println("<error>");
1306
      out.println(e.getMessage());
1307
      out.println("</error>");
1308
    } finally {
1309
      util.returnConnection(conn);
1310
    }  
1311
    
1312
  }
1313

    
1314
  /** 
1315
   * Handle the "getprincipals" action.
1316
   * Read all principals from authentication scheme in XML format
1317
   */
1318
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1319
                                         String password) {
1320

    
1321
    Connection conn = null;
1322

    
1323
    try {
1324

    
1325
        // get connection from the pool
1326
        AuthSession auth = new AuthSession();
1327
        String principals = auth.getPrincipals(user, password);
1328
        out.println(principals);
1329

    
1330
    } catch (Exception e) {
1331
      out.println("<?xml version=\"1.0\"?>");
1332
      out.println("<error>");
1333
      out.println(e.getMessage());
1334
      out.println("</error>");
1335
    } finally {
1336
      util.returnConnection(conn);
1337
    }  
1338
    
1339
  }
1340

    
1341
  /** 
1342
   * Handle "getdoctypes" action.
1343
   * Read all doctypes from db connection in XML format
1344
   */
1345
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params, 
1346
                                       HttpServletResponse response) {
1347

    
1348
    Connection conn = null;
1349
    
1350
    try {
1351

    
1352
        // get connection from the pool
1353
        conn = util.getConnection();
1354
        DBUtil dbutil = new DBUtil(conn);
1355
        String doctypes = dbutil.readDoctypes();
1356
        out.println(doctypes);
1357

    
1358
    } catch (Exception e) {
1359
      out.println("<?xml version=\"1.0\"?>");
1360
      out.println("<error>");
1361
      out.println(e.getMessage());
1362
      out.println("</error>");
1363
    } finally {
1364
      util.returnConnection(conn);
1365
    }  
1366
    
1367
  }
1368

    
1369
  /** 
1370
   * Handle the "getdtdschema" action.
1371
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1372
   */
1373
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1374
                                        HttpServletResponse response) {
1375

    
1376
    Connection conn = null;
1377
    String doctype = null;
1378
    String[] doctypeArr = (String[])params.get("doctype");
1379

    
1380
    // get only the first doctype specified in the list of doctypes
1381
    // it could be done for all doctypes in that list
1382
    if (doctypeArr != null) {
1383
        doctype = ((String[])params.get("doctype"))[0]; 
1384
    }
1385

    
1386
    try {
1387

    
1388
        // get connection from the pool
1389
        conn = util.getConnection();
1390
        DBUtil dbutil = new DBUtil(conn);
1391
        String dtdschema = dbutil.readDTDSchema(doctype);
1392
        out.println(dtdschema);
1393

    
1394
    } catch (Exception e) {
1395
      out.println("<?xml version=\"1.0\"?>");
1396
      out.println("<error>");
1397
      out.println(e.getMessage());
1398
      out.println("</error>");
1399
    } finally {
1400
      util.returnConnection(conn);
1401
    }  
1402
    
1403
  }
1404

    
1405
  /** 
1406
   * Handle the "getdataguide" action.
1407
   * Read Data Guide for a given doctype from db connection in XML format
1408
   */
1409
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params, 
1410
                                        HttpServletResponse response) {
1411

    
1412
    Connection conn = null;
1413
    String doctype = null;
1414
    String[] doctypeArr = (String[])params.get("doctype");
1415

    
1416
    // get only the first doctype specified in the list of doctypes
1417
    // it could be done for all doctypes in that list
1418
    if (doctypeArr != null) {
1419
        doctype = ((String[])params.get("doctype"))[0]; 
1420
    }
1421

    
1422
    try {
1423

    
1424
        // get connection from the pool
1425
        conn = util.getConnection();
1426
        DBUtil dbutil = new DBUtil(conn);
1427
        String dataguide = dbutil.readDataGuide(doctype);
1428
        out.println(dataguide);
1429

    
1430
    } catch (Exception e) {
1431
      out.println("<?xml version=\"1.0\"?>");
1432
      out.println("<error>");
1433
      out.println(e.getMessage());
1434
      out.println("</error>");
1435
    } finally {
1436
      util.returnConnection(conn);
1437
    }  
1438
    
1439
  }
1440

    
1441
  /** 
1442
   * Handle the "getlastdocid" action.
1443
   * Get the latest docid with rev number from db connection in XML format
1444
   */
1445
  private void handleGetLastDocidAction(PrintWriter out, Hashtable params, 
1446
                                        HttpServletResponse response) {
1447

    
1448
    Connection conn = null;
1449
    String username = ((String[])params.get("username"))[0];
1450

    
1451
    try {
1452

    
1453
        // get connection from the pool
1454
        conn = util.getConnection();
1455
        DBUtil dbutil = new DBUtil(conn);
1456
        String lastDocid = dbutil.getLastDocid(username);
1457
        out.println("<?xml version=\"1.0\"?>");
1458
        out.println("<lastDocid>");
1459
        out.println("  <username>" + username + "</username>");
1460
        out.println("  <docid>" + lastDocid + "</docid>");
1461
        out.println("</lastDocid>");
1462

    
1463
    } catch (Exception e) {
1464
      out.println("<?xml version=\"1.0\"?>");
1465
      out.println("<error>");
1466
      out.println(e.getMessage());
1467
      out.println("</error>");
1468
    } finally {
1469
      util.returnConnection(conn);
1470
    }  
1471
    
1472
  }
1473

    
1474
  /** 
1475
   * Handle documents passed to metacat that are encoded using the 
1476
   * "multipart/form-data" mime type.  This is typically used for uploading
1477
   * data files which may be binary and large.
1478
   */
1479
  private void handleMultipartForm(HttpServletRequest request,
1480
                                   HttpServletResponse response) 
1481
  {
1482
    PrintWriter out = null;
1483
    String action = null;
1484

    
1485
    // Parse the multipart form, and save the parameters in a Hashtable and
1486
    // save the FileParts in a hashtable
1487

    
1488
    Hashtable params = new Hashtable();
1489
    Hashtable fileList = new Hashtable();
1490

    
1491
    try {
1492
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1493
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); // 200MB
1494
      Part part;
1495
      while ((part = mp.readNextPart()) != null) {
1496
        String name = part.getName();
1497

    
1498
        if (part.isParam()) {
1499
          // it's a parameter part
1500
          ParamPart paramPart = (ParamPart) part;
1501
          String value = paramPart.getStringValue();
1502
          params.put(name, value);
1503
          if (name.equals("action")) {
1504
            action = value;
1505
          }
1506
        } else if (part.isFile()) {
1507
          // it's a file part
1508
          FilePart filePart = (FilePart) part;
1509
          fileList.put(name, filePart);
1510

    
1511
          // Stop once the first file part is found, otherwise going onto the
1512
          // next part prevents access to the file contents.  So...for upload
1513
          // to work, the datafile must be the last part
1514
          break;
1515
        }
1516
      }
1517
    } catch (IOException ioe) {
1518
      try {
1519
        out = response.getWriter();
1520
      } catch (IOException ioe2) {
1521
        System.err.println("Fatal Error: couldn't get response output stream.");
1522
      }
1523
      out.println("<?xml version=\"1.0\"?>");
1524
      out.println("<error>");
1525
      out.println("Error: problem reading multipart data.");
1526
      out.println("</error>");
1527
    }
1528

    
1529
    // Get the session information
1530
    String username = null;
1531
    String password = null;
1532
    String groupname = null;
1533
    String sess_id = null;
1534

    
1535
    // be aware of session expiration on every request  
1536
    HttpSession sess = request.getSession(true);
1537
    if (sess.isNew()) {
1538
      // session expired or has not been stored b/w user requests
1539
      username = "public";
1540
      sess.setAttribute("username", username);
1541
    } else {
1542
      username = (String)sess.getAttribute("username");
1543
      password = (String)sess.getAttribute("password");
1544
      groupname = (String)sess.getAttribute("groupname");
1545
      try {
1546
        sess_id = (String)sess.getId();
1547
      } catch(IllegalStateException ise) {
1548
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1549
                           "happen: the session should be valid: " + 
1550
                           ise.getMessage());
1551
      }
1552
    }  
1553

    
1554
    if ( action.equals("upload")) {
1555
      if (username != null &&  !username.equals("public")) {
1556
        handleUploadAction(request, response, params, fileList, 
1557
                           username, groupname);
1558
      } else {
1559
        try {
1560
          out = response.getWriter();
1561
        } catch (IOException ioe2) {
1562
          System.err.println("Fatal Error: couldn't get response output stream.");
1563
        }
1564
        out.println("<?xml version=\"1.0\"?>");
1565
        out.println("<error>");
1566
        out.println("Permission denied for " + action);
1567
        out.println("</error>");
1568
      }
1569
    } else {
1570
      try {
1571
        out = response.getWriter();
1572
      } catch (IOException ioe2) {
1573
        System.err.println("Fatal Error: couldn't get response output stream.");
1574
      }
1575
      out.println("<?xml version=\"1.0\"?>");
1576
      out.println("<error>");
1577
      out.println("Error: action not registered.  Please report this error.");
1578
      out.println("</error>");
1579
    }
1580
  }
1581

    
1582
  /** 
1583
   * Handle the upload action by saving the attached file to disk and 
1584
   * registering it in the Metacat db
1585
   */
1586
  private void handleUploadAction(HttpServletRequest request,
1587
                                  HttpServletResponse response, 
1588
                                  Hashtable params, Hashtable fileList, 
1589
                                  String username, String groupname)
1590
  {
1591
    PrintWriter out = null;
1592
    Connection conn = null;
1593
    String action = null;
1594
    String docid = null;
1595

    
1596
    response.setContentType("text/xml");
1597
    try {
1598
      out = response.getWriter();
1599
    } catch (IOException ioe2) {
1600
      System.err.println("Fatal Error: couldn't get response output stream.");
1601
    }
1602

    
1603
    if (params.containsKey("docid")) {
1604
      docid = (String)params.get("docid");
1605
    }
1606

    
1607
    // Make sure we have a docid and datafile
1608
    if (docid != null && fileList.containsKey("datafile")) {
1609

    
1610
      // Get a reference to the file part of the form
1611
      FilePart filePart = (FilePart)fileList.get("datafile");
1612
      String fileName = filePart.getFileName();
1613
      MetaCatUtil.debugMessage("Uploading filename: " + fileName);
1614

    
1615
      // Check if the right file existed in the uploaded data
1616
      if (fileName != null) {
1617
  
1618
        try {
1619
          // register the file in the database (which generates an exception if
1620
          // the docid is not acceptable or other untoward things happen
1621
          DocumentImpl.registerDocument(fileName, "BIN", docid, username, 1);
1622
    
1623
          // Save the data file to disk using "docid" as the name
1624
          dataDirectory.mkdirs();
1625
          File newFile = new File(dataDirectory, docid);
1626
          long size = filePart.writeTo(newFile);
1627

    
1628
          // set content type and other response header fields first
1629
          out.println("<?xml version=\"1.0\"?>");
1630
          out.println("<success>");
1631
          out.println("<docid>" + docid + "</docid>"); 
1632
          out.println("<size>" + size + "</size>"); 
1633
          out.println("</success>");
1634
    
1635
        } catch (Exception e) {
1636
          out.println("<?xml version=\"1.0\"?>");
1637
          out.println("<error>");
1638
          out.println(e.getMessage()); 
1639
          out.println("</error>");
1640
        }
1641
      } else {
1642
        // the field did not contain a file
1643
        out.println("<?xml version=\"1.0\"?>");
1644
        out.println("<error>");
1645
        out.println("The uploaded data did not contain a valid file."); 
1646
        out.println("</error>");
1647
      }
1648
    } else {
1649
      // Error bcse docid missing or file missing
1650
      out.println("<?xml version=\"1.0\"?>");
1651
      out.println("<error>");
1652
      out.println("The uploaded data did not contain a valid docid " +
1653
                  "or valid file."); 
1654
      out.println("</error>");
1655
    }
1656
  }
1657
}
(29-29/40)