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: bojilova $'
10
 *     '$Date: 2001-07-20 21:03:32 -0700 (Fri, 20 Jul 2001) $'
11
 * '$Revision: 802 $'
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[] groupnames = 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
          groupnames = (String[])sess.getAttribute("groupnames");
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,groupnames);
294
      } else if(action.equals("squery")) {
295
        if(params.containsKey("query")) {
296
          handleSQuery(response.getWriter(),params,response,username,groupnames); 
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, groupnames);
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,groupnames);
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, groupnames);
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,groupnames);
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[] groups)
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, groups);
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[] groups)
522
  {
523
    //create the query and run it
524
    String xmlquery = DBQuery.createSQuery(params);
525
    Hashtable doclist = runQuery(xmlquery, user, groups);
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[] groups)
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,groups);
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 groups the user's groupnames
674
   */
675
  private void handleReadAction(Hashtable params, HttpServletResponse response,
676
                                String user, String[] groups) 
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, groups, 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, groups, 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[] groups, 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[] groups) {
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, groups, validate);
1068
          } catch (NullPointerException npe) {
1069
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1070
                                          null, user, groups, 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[] groups) {
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, groups);
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[] groupnames) {
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, groupnames);
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[] groupnames = 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
      groupnames = (String[])sess.getAttribute("groupnames");
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, groupnames);
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[] groupnames)
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)