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

    
410
    AuthSession sess = null;
411
    String un = ((String[])params.get("username"))[0];
412
    String pw = ((String[])params.get("password"))[0];
413
    String action = ((String[])params.get("action"))[0];
414
    String qformat = ((String[])params.get("qformat"))[0];
415
    
416
    try {
417
      sess = new AuthSession();
418
    } catch (Exception e) {
419
      System.out.println("error in MetacatServlet.handleLoginAction: " +
420
                          e.getMessage());
421
      out.println(e.getMessage());
422
      return;
423
    }
424
    
425
    boolean isValid = sess.authenticate(request, un, pw);
426

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

    
448
  /** 
449
   * Handle the logout request. Close the connection.
450
   */
451
  private void handleLogoutAction(PrintWriter out, Hashtable params, 
452
               HttpServletRequest request, HttpServletResponse response) {
453

    
454
    String qformat = ((String[])params.get("qformat"))[0];
455

    
456
    // close the connection
457
    HttpSession sess = request.getSession(false);
458
    if (sess != null) { sess.invalidate();  }    
459

    
460
    // produce output
461
    StringBuffer output = new StringBuffer();
462
    output.append("<?xml version=\"1.0\"?>");
463
    output.append("<logout>");
464
    output.append("User logged out");
465
    output.append("</logout>");
466

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

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

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

    
655
    if(doclist != null)
656
    {
657
      Enumeration doclistkeys = doclist.keys(); 
658
      while (doclistkeys.hasMoreElements()) 
659
      {
660
        docid = (String)doclistkeys.nextElement();
661
        document = (String)doclist.get(docid);
662
        resultset.append("  <document>" + document + "</document>");
663
      }
664
    }
665

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

    
719
          URL murl = new URL(docs[i]);
720
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
721
          // case docid="http://.../?docid=aaa" 
722
          // or docid="metacat://.../?docid=bbb"
723
          if (murlQueryStr.containsKey("docid")) {
724
            // get only docid, eliminate the rest
725
            docid = (String)murlQueryStr.get("docid");
726
            if ( zip ) {
727
              addDocToZip(docid, zout);
728
            } else {
729
              readFromMetacat(response, docid, qformat, abstrpath,
730
                              user, group, zip, zout);
731
            }
732

    
733
          // case docid="http://.../filename"
734
          } else {
735
            docid = docs[i];
736
            if ( zip ) {
737
              addDocToZip(docid, zout);
738
            } else {
739
              readFromURLConnection(response, docid);
740
            }
741
          }
742

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

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

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

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

    
921
    try {
922
      URL url = new URL(docid);
923

    
924
      // this http url; read from URLConnection; add to zip
925
      zentry = new ZipEntry(docid);
926
      zout.putNextEntry(zentry);
927
      BufferedInputStream bis = null;
928
      try {
929
        bis = new BufferedInputStream(url.openStream());
930
        byte[] buf = new byte[4 * 1024]; // 4K buffer
931
        int b = bis.read(buf);
932
        while(b != -1) {
933
          zout.write(buf, 0, b);
934
          b = bis.read(buf);
935
        }
936
      } finally {
937
        if (bis != null) bis.close();
938
      }
939
      zout.closeEntry();
940

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

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

    
1010
    } finally {
1011
      util.returnConnection(conn);
1012
    }
1013
  }
1014
  // END OF READ SECTION
1015
    
1016
  // INSERT/UPDATE SECTION
1017
  /** 
1018
   * Handle the database putdocument request and write an XML document 
1019
   * to the database connection
1020
   */
1021
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params, 
1022
               HttpServletResponse response, String user, String group) {
1023

    
1024
    Connection conn = null;
1025

    
1026
    try {
1027
      // Get the document indicated
1028
      String[] doctext = (String[])params.get("doctext");
1029

    
1030
      String pub = null;
1031
      if (params.containsKey("public")) {
1032
        pub = ((String[])params.get("public"))[0];
1033
      }
1034

    
1035
      StringReader dtd = null;
1036
      if (params.containsKey("dtdtext")) {
1037
        String[] dtdtext = (String[])params.get("dtdtext");
1038
        try {
1039
          if ( !dtdtext[0].equals("") ) {
1040
            dtd = new StringReader(dtdtext[0]);
1041
          }
1042
        } catch (NullPointerException npe) {}
1043
      }
1044
      
1045
      StringReader xml = null;
1046
      boolean validate = false;
1047
      try {
1048
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1049
        // in order to decide whether to use validation parser
1050
        validate = validateXML(doctext[0]);
1051
        xml = new StringReader(doctext[0]);
1052

    
1053
        String[] action = (String[])params.get("action");
1054
        String[] docid = (String[])params.get("docid");
1055
        String newdocid = null;
1056

    
1057
        String doAction = null;
1058
        if (action[0].equals("insert")) {
1059
          doAction = "INSERT";
1060
        } else if (action[0].equals("update")) {
1061
          doAction = "UPDATE";
1062
        }
1063

    
1064
        try {
1065
          // get a connection from the pool
1066
          conn = util.getConnection();
1067

    
1068
          // write the document to the database
1069
          try {
1070
            String accNumber = docid[0];
1071
            if (accNumber.equals("")) {
1072
              accNumber = null;
1073
            }
1074
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1075
                                          accNumber, user, group, validate);
1076
          } catch (NullPointerException npe) {
1077
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1078
                                          null, user, group, validate);
1079
          }
1080
        } finally {
1081
          util.returnConnection(conn);
1082
        }    
1083

    
1084
        // set content type and other response header fields first
1085
        response.setContentType("text/xml");
1086
        out.println("<?xml version=\"1.0\"?>");
1087
        out.println("<success>");
1088
        out.println("<docid>" + newdocid + "</docid>"); 
1089
        out.println("</success>");
1090

    
1091
      } catch (NullPointerException npe) {
1092
        response.setContentType("text/xml");
1093
        out.println("<?xml version=\"1.0\"?>");
1094
        out.println("<error>");
1095
        out.println(npe.getMessage()); 
1096
        out.println("</error>");
1097
      }
1098
    } catch (Exception e) {
1099
      response.setContentType("text/xml");
1100
      out.println("<?xml version=\"1.0\"?>");
1101
      out.println("<error>");
1102
      out.println(e.getMessage()); 
1103
      if (e instanceof SAXException) {
1104
        Exception e2 = ((SAXException)e).getException();
1105
        out.println("<error>");
1106
        try
1107
        {
1108
          out.println(e2.getMessage());
1109
        }
1110
        catch(NullPointerException npe)
1111
        {
1112
          out.println(e.getMessage());
1113
        }
1114
        out.println("</error>");
1115
      }
1116
      //e.printStackTrace(out);
1117
      out.println("</error>");
1118
    }
1119
  }
1120

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

    
1138
      // "<!DOCTYPE" keyword is found; put it in the stack
1139
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1140
        cbuff = new StringBuffer();
1141
        st.push("<!DOCTYPE");
1142
      }
1143
      // "PUBLIC" keyword is found; put it in the stack
1144
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1145
        cbuff = new StringBuffer();
1146
        st.push("PUBLIC");
1147
      }
1148
      // "SYSTEM" keyword is found; put it in the stack
1149
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1150
        cbuff = new StringBuffer();
1151
        st.push("SYSTEM");
1152
      }
1153
      // ">" character is found; put it in the stack
1154
      // ">" is found twice: fisrt from <?xml ...?> 
1155
      // and second from <!DOCTYPE ... >
1156
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1157
        cbuff = new StringBuffer();
1158
        st.push(">");
1159
      }
1160
    }
1161

    
1162
    // close the stream
1163
    xmlreader.close();
1164

    
1165
    // check the stack whether it contains the keywords:
1166
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1167
    if ( st.size() == 4 ) {
1168
      if ( ((String)st.pop()).equals(">") &&
1169
           ( ((String)st.peek()).equals("PUBLIC") |
1170
             ((String)st.pop()).equals("SYSTEM") ) &&
1171
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1172
        validate = true;
1173
      }
1174
    }
1175

    
1176
System.out.println("Validation is " + validate);
1177
    return validate;
1178
  }
1179
  // END OF INSERT/UPDATE SECTION
1180

    
1181
  // DELETE SECTION
1182
  /** 
1183
   * Handle the database delete request and delete an XML document 
1184
   * from the database connection
1185
   */
1186
  private void handleDeleteAction(PrintWriter out, Hashtable params, 
1187
               HttpServletResponse response, String user, String group) {
1188

    
1189
    String[] docid = (String[])params.get("docid");
1190
    Connection conn = null;
1191

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

    
1233
    // Get the document indicated
1234
    String valtext = null;
1235
    
1236
    try {
1237
      valtext = ((String[])params.get("valtext"))[0];
1238
    } catch (Exception nullpe) {
1239

    
1240
      Connection conn = null;
1241
      String docid = null;
1242
      try {
1243
        // Find the document id number
1244
        docid = ((String[])params.get("docid"))[0]; 
1245

    
1246
        // get a connection from the pool
1247
        conn = util.getConnection();
1248

    
1249
        // Get the document indicated from the db
1250
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
1251
        valtext = xmldoc.toString();
1252

    
1253
      } catch (NullPointerException npe) {
1254
        response.setContentType("text/xml");
1255
        out.println("<error>Error getting document ID: " + docid + "</error>");
1256
        if ( conn != null ) { util.returnConnection(conn); }
1257
        return;
1258
      } catch (Exception e) {
1259
        response.setContentType("text/html");
1260
        out.println(e.getMessage()); 
1261
      } finally {
1262
        util.returnConnection(conn);
1263
      }  
1264
    }
1265

    
1266
    Connection conn = null;
1267
    try {
1268
      // get a connection from the pool
1269
      conn = util.getConnection();
1270
      DBValidate valobj = new DBValidate(saxparser,conn);
1271
      boolean valid = valobj.validateString(valtext);
1272

    
1273
      // set content type and other response header fields first
1274
      response.setContentType("text/xml");
1275
      out.println(valobj.returnErrors());
1276

    
1277
    } catch (NullPointerException npe2) {
1278
      // set content type and other response header fields first
1279
      response.setContentType("text/xml");
1280
      out.println("<error>Error validating document.</error>"); 
1281
    } catch (Exception e) {
1282
      response.setContentType("text/html");
1283
      out.println(e.getMessage()); 
1284
    } finally {
1285
      util.returnConnection(conn);
1286
    }  
1287
  }
1288
  // END OF VALIDATE SECTION
1289
 
1290
  // OTHER ACTION HANDLERS
1291
  /**
1292
   * sends the port number that the data socket is running on.
1293
   * This is a parameter set in the metacat.properties file.
1294
   */
1295
  private void handleGetDataPortAction(PrintWriter out, Hashtable params, 
1296
                                       HttpServletResponse response, 
1297
                                       String username, String groupname,
1298
                                       String sess_id)
1299
  {
1300
    int port;
1301
    String filedir = null;
1302
    try
1303
    {
1304
      filedir = util.getOption("datafilepath");
1305
      
1306
      Random r = new Random();
1307
      port = r.nextInt(65000);  //pick a random port between 0-65000
1308
      //System.out.println("random port is: " + port);
1309
      while(!DataFileServer.portIsAvailable(port))
1310
      {
1311
        port = r.nextInt(65000);
1312
        //System.out.println("next port used: " + port);
1313
      }
1314
      DataFileServer dfs = new DataFileServer(port, username, sess_id);
1315
      dfs.start();
1316
      
1317
      //System.out.println("filedir: " + filedir);
1318
      //System.out.println("port: " + port);
1319
      response.setContentType("text/xml");
1320
      out.println("<?xml version=\"1.0\"?>");
1321
      out.println("<port>");
1322
      out.print(port);
1323
      out.print("</port>");
1324
      
1325
    }
1326
	  catch (Exception e) 
1327
    {
1328
      System.out.println("error in MetacatServlet.handleGetDataPortAction: " + 
1329
                          e.getMessage());
1330
    }
1331
  }
1332
  
1333
  /** 
1334
   * Handle "getaccesscontrol" action.
1335
   * Read Access Control List from db connection in XML format
1336
   */
1337
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params, 
1338
                                       HttpServletResponse response, 
1339
                                       String username, String groupname) {
1340

    
1341
    Connection conn = null;
1342
    String docid = ((String[])params.get("docid"))[0];
1343
    
1344
    try {
1345

    
1346
        // get connection from the pool
1347
        conn = util.getConnection();
1348
        AccessControlList aclobj = new AccessControlList(conn);
1349
        String acltext = aclobj.getACL(docid, username, groupname);
1350
        out.println(acltext);
1351

    
1352
    } catch (Exception e) {
1353
      out.println("<?xml version=\"1.0\"?>");
1354
      out.println("<error>");
1355
      out.println(e.getMessage());
1356
      out.println("</error>");
1357
    } finally {
1358
      util.returnConnection(conn);
1359
    }  
1360
    
1361
  }
1362

    
1363
  /** 
1364
   * Handle the "getprincipals" action.
1365
   * Read all principals from authentication scheme in XML format
1366
   */
1367
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1368
                                         String password) {
1369

    
1370
    Connection conn = null;
1371

    
1372
    try {
1373

    
1374
        // get connection from the pool
1375
        AuthSession auth = new AuthSession();
1376
        String principals = auth.getPrincipals(user, password);
1377
        out.println(principals);
1378

    
1379
    } catch (Exception e) {
1380
      out.println("<?xml version=\"1.0\"?>");
1381
      out.println("<error>");
1382
      out.println(e.getMessage());
1383
      out.println("</error>");
1384
    } finally {
1385
      util.returnConnection(conn);
1386
    }  
1387
    
1388
  }
1389

    
1390
  /** 
1391
   * Handle "getdoctypes" action.
1392
   * Read all doctypes from db connection in XML format
1393
   */
1394
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params, 
1395
                                       HttpServletResponse response) {
1396

    
1397
    Connection conn = null;
1398
    
1399
    try {
1400

    
1401
        // get connection from the pool
1402
        conn = util.getConnection();
1403
        DBUtil dbutil = new DBUtil(conn);
1404
        String doctypes = dbutil.readDoctypes();
1405
        out.println(doctypes);
1406

    
1407
    } catch (Exception e) {
1408
      out.println("<?xml version=\"1.0\"?>");
1409
      out.println("<error>");
1410
      out.println(e.getMessage());
1411
      out.println("</error>");
1412
    } finally {
1413
      util.returnConnection(conn);
1414
    }  
1415
    
1416
  }
1417

    
1418
  /** 
1419
   * Handle the "getdtdschema" action.
1420
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1421
   */
1422
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1423
                                        HttpServletResponse response) {
1424

    
1425
    Connection conn = null;
1426
    String doctype = null;
1427
    String[] doctypeArr = (String[])params.get("doctype");
1428

    
1429
    // get only the first doctype specified in the list of doctypes
1430
    // it could be done for all doctypes in that list
1431
    if (doctypeArr != null) {
1432
        doctype = ((String[])params.get("doctype"))[0]; 
1433
    }
1434

    
1435
    try {
1436

    
1437
        // get connection from the pool
1438
        conn = util.getConnection();
1439
        DBUtil dbutil = new DBUtil(conn);
1440
        String dtdschema = dbutil.readDTDSchema(doctype);
1441
        out.println(dtdschema);
1442

    
1443
    } catch (Exception e) {
1444
      out.println("<?xml version=\"1.0\"?>");
1445
      out.println("<error>");
1446
      out.println(e.getMessage());
1447
      out.println("</error>");
1448
    } finally {
1449
      util.returnConnection(conn);
1450
    }  
1451
    
1452
  }
1453

    
1454
  /** 
1455
   * Handle the "getdataguide" action.
1456
   * Read Data Guide for a given doctype from db connection in XML format
1457
   */
1458
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params, 
1459
                                        HttpServletResponse response) {
1460

    
1461
    Connection conn = null;
1462
    String doctype = null;
1463
    String[] doctypeArr = (String[])params.get("doctype");
1464

    
1465
    // get only the first doctype specified in the list of doctypes
1466
    // it could be done for all doctypes in that list
1467
    if (doctypeArr != null) {
1468
        doctype = ((String[])params.get("doctype"))[0]; 
1469
    }
1470

    
1471
    try {
1472

    
1473
        // get connection from the pool
1474
        conn = util.getConnection();
1475
        DBUtil dbutil = new DBUtil(conn);
1476
        String dataguide = dbutil.readDataGuide(doctype);
1477
        out.println(dataguide);
1478

    
1479
    } catch (Exception e) {
1480
      out.println("<?xml version=\"1.0\"?>");
1481
      out.println("<error>");
1482
      out.println(e.getMessage());
1483
      out.println("</error>");
1484
    } finally {
1485
      util.returnConnection(conn);
1486
    }  
1487
    
1488
  }
1489

    
1490
  /** 
1491
   * Handle the "getlastdocid" action.
1492
   * Get the latest docid with rev number from db connection in XML format
1493
   */
1494
  private void handleGetLastDocidAction(PrintWriter out, Hashtable params, 
1495
                                        HttpServletResponse response) {
1496

    
1497
    Connection conn = null;
1498
    String username = ((String[])params.get("username"))[0];
1499

    
1500
    try {
1501

    
1502
        // get connection from the pool
1503
        conn = util.getConnection();
1504
        DBUtil dbutil = new DBUtil(conn);
1505
        String lastDocid = dbutil.getLastDocid(username);
1506
        out.println("<?xml version=\"1.0\"?>");
1507
        out.println("<lastDocid>");
1508
        out.println("  <username>" + username + "</username>");
1509
        out.println("  <docid>" + lastDocid + "</docid>");
1510
        out.println("</lastDocid>");
1511

    
1512
    } catch (Exception e) {
1513
      out.println("<?xml version=\"1.0\"?>");
1514
      out.println("<error>");
1515
      out.println(e.getMessage());
1516
      out.println("</error>");
1517
    } finally {
1518
      util.returnConnection(conn);
1519
    }  
1520
    
1521
  }
1522

    
1523
  /** 
1524
   * Handle documents passed to metacat that are encoded using the 
1525
   * "multipart/form-data" mime type.  This is typically used for uploading
1526
   * data files which may be binary and large.
1527
   */
1528
  private void handleMultipartForm(HttpServletRequest request,
1529
                                   HttpServletResponse response) 
1530
  {
1531
    PrintWriter out = null;
1532
    String action = null;
1533

    
1534
    // Parse the multipart form, and save the parameters in a Hashtable and
1535
    // save the FileParts in a hashtable
1536

    
1537
    Hashtable params = new Hashtable();
1538
    Hashtable fileList = new Hashtable();
1539

    
1540
    try {
1541
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1542
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); // 200MB
1543
      Part part;
1544
      while ((part = mp.readNextPart()) != null) {
1545
        String name = part.getName();
1546

    
1547
        if (part.isParam()) {
1548
          // it's a parameter part
1549
          ParamPart paramPart = (ParamPart) part;
1550
          String value = paramPart.getStringValue();
1551
          params.put(name, value);
1552
          if (name.equals("action")) {
1553
            action = value;
1554
          }
1555
        } else if (part.isFile()) {
1556
          // it's a file part
1557
          FilePart filePart = (FilePart) part;
1558
          fileList.put(name, filePart);
1559

    
1560
          // Stop once the first file part is found, otherwise going onto the
1561
          // next part prevents access to the file contents.  So...for upload
1562
          // to work, the datafile must be the last part
1563
          break;
1564
        }
1565
      }
1566
    } catch (IOException ioe) {
1567
      try {
1568
        out = response.getWriter();
1569
      } catch (IOException ioe2) {
1570
        System.err.println("Fatal Error: couldn't get response output stream.");
1571
      }
1572
      out.println("<?xml version=\"1.0\"?>");
1573
      out.println("<error>");
1574
      out.println("Error: problem reading multipart data.");
1575
      out.println("</error>");
1576
    }
1577

    
1578
    // Get the session information
1579
    String username = null;
1580
    String password = null;
1581
    String groupname = null;
1582
    String sess_id = null;
1583

    
1584
    // be aware of session expiration on every request  
1585
    HttpSession sess = request.getSession(true);
1586
    if (sess.isNew()) {
1587
      // session expired or has not been stored b/w user requests
1588
      username = "public";
1589
      sess.setAttribute("username", username);
1590
    } else {
1591
      username = (String)sess.getAttribute("username");
1592
      password = (String)sess.getAttribute("password");
1593
      groupname = (String)sess.getAttribute("groupname");
1594
      try {
1595
        sess_id = (String)sess.getId();
1596
      } catch(IllegalStateException ise) {
1597
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1598
                           "happen: the session should be valid: " + 
1599
                           ise.getMessage());
1600
      }
1601
    }  
1602

    
1603
    if ( action.equals("upload")) {
1604
      if (username != null &&  !username.equals("public")) {
1605
        handleUploadAction(request, response, params, fileList, 
1606
                           username, groupname);
1607
      } else {
1608
        try {
1609
          out = response.getWriter();
1610
        } catch (IOException ioe2) {
1611
          System.err.println("Fatal Error: couldn't get response output stream.");
1612
        }
1613
        out.println("<?xml version=\"1.0\"?>");
1614
        out.println("<error>");
1615
        out.println("Permission denied for " + action);
1616
        out.println("</error>");
1617
      }
1618
    } else {
1619
      try {
1620
        out = response.getWriter();
1621
      } catch (IOException ioe2) {
1622
        System.err.println("Fatal Error: couldn't get response output stream.");
1623
      }
1624
      out.println("<?xml version=\"1.0\"?>");
1625
      out.println("<error>");
1626
      out.println("Error: action not registered.  Please report this error.");
1627
      out.println("</error>");
1628
    }
1629
  }
1630

    
1631
  /** 
1632
   * Handle the upload action by saving the attached file to disk and 
1633
   * registering it in the Metacat db
1634
   */
1635
  private void handleUploadAction(HttpServletRequest request,
1636
                                  HttpServletResponse response, 
1637
                                  Hashtable params, Hashtable fileList, 
1638
                                  String username, String groupname)
1639
  {
1640
    PrintWriter out = null;
1641
    Connection conn = null;
1642
    String action = null;
1643
    String docid = null;
1644

    
1645
    response.setContentType("text/xml");
1646
    try {
1647
      out = response.getWriter();
1648
    } catch (IOException ioe2) {
1649
      System.err.println("Fatal Error: couldn't get response output stream.");
1650
    }
1651

    
1652
    if (params.containsKey("docid")) {
1653
      docid = (String)params.get("docid");
1654
    }
1655

    
1656
    // Make sure we have a docid and datafile
1657
    if (docid != null && fileList.containsKey("datafile")) {
1658

    
1659
      // Get a reference to the file part of the form
1660
      FilePart filePart = (FilePart)fileList.get("datafile");
1661
      String fileName = filePart.getFileName();
1662
      MetaCatUtil.debugMessage("Uploading filename: " + fileName);
1663

    
1664
      // Check if the right file existed in the uploaded data
1665
      if (fileName != null) {
1666
  
1667
        try {
1668
          // register the file in the database (which generates an exception if
1669
          // the docid is not acceptable or other untoward things happen
1670
          DocumentImpl.registerDocument(fileName, "BIN", docid, username, 1);
1671
    
1672
          // Save the data file to disk using "docid" as the name
1673
          dataDirectory.mkdirs();
1674
          File newFile = new File(dataDirectory, docid);
1675
          long size = filePart.writeTo(newFile);
1676

    
1677
          // set content type and other response header fields first
1678
          out.println("<?xml version=\"1.0\"?>");
1679
          out.println("<success>");
1680
          out.println("<docid>" + docid + "</docid>"); 
1681
          out.println("<size>" + size + "</size>"); 
1682
          out.println("</success>");
1683
    
1684
        } catch (Exception e) {
1685
          out.println("<?xml version=\"1.0\"?>");
1686
          out.println("<error>");
1687
          out.println(e.getMessage()); 
1688
          out.println("</error>");
1689
        }
1690
      } else {
1691
        // the field did not contain a file
1692
        out.println("<?xml version=\"1.0\"?>");
1693
        out.println("<error>");
1694
        out.println("The uploaded data did not contain a valid file."); 
1695
        out.println("</error>");
1696
      }
1697
    } else {
1698
      // Error bcse docid missing or file missing
1699
      out.println("<?xml version=\"1.0\"?>");
1700
      out.println("<error>");
1701
      out.println("The uploaded data did not contain a valid docid " +
1702
                  "or valid file."); 
1703
      out.println("</error>");
1704
    }
1705
  }
1706
}
(32-32/43)