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: tao $'
10
 *     '$Date: 2002-02-26 08:37:53 -0800 (Tue, 26 Feb 2002) $'
11
 * '$Revision: 947 $'
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 org.xml.sax.SAXException;
68

    
69
/**
70
 * A metadata catalog server implemented as a Java Servlet
71
 *
72
 * <p>Valid parameters are:<br>
73
 * action=query -- query the values of all elements and attributes
74
 *                     and return a result set of nodes<br>
75
 * action=squery -- structured query (see pathquery.dtd)<br> 
76
 * action= -- export a zip format for data packadge<br>
77
 * action=read -- read any metadata/data file from Metacat and from Internet<br>
78
 * action=insert -- insert an XML document into the database store<br>
79
 * action=update -- update an XML document that is in the database store<br>
80
 * action=delete --  delete an XML document from the database store<br>
81
 * action=validate -- vallidate the xml contained in valtext<br>
82
 * doctype -- document type list returned by the query (publicID)<br>
83
 * qformat=xml -- display resultset from query in XML<br>
84
 * qformat=html -- display resultset from query in HTML<br>
85
 * qformat=zip -- zip resultset from query<br>
86
 * docid=34 -- display the document with the document ID number 34<br>
87
 * doctext -- XML text of the document to load into the database<br>
88
 * acltext -- XML access text for a document to load into the database<br>
89
 * dtdtext -- XML DTD text for a new DTD to load into Metacat XML Catalog<br>
90
 * query -- actual query text (to go with 'action=query' or 'action=squery')<br>
91
 * valtext -- XML text to be validated<br>
92
 * abstractpath -- XPath in metadata document to read from<br>
93
 * action=getaccesscontrol -- retrieve acl info for Metacat document<br>
94
 * action=getdoctypes -- retrieve all doctypes (publicID)<br>
95
 * action=getdtdschema -- retrieve a DTD or Schema file<br>
96
 * action=getdataguide -- retrieve a Data Guide<br>
97
 * action=getprincipals -- retrieve a list of principals in XML<br>
98
 * datadoc -- data document name (id)<br>
99
 * <p>
100
 * The particular combination of parameters that are valid for each 
101
 * particular action value is quite specific.  This documentation
102
 * will be reorganized to reflect this information.
103
 */
104
public class MetaCatServlet extends HttpServlet {
105

    
106
  private ServletConfig config = null;
107
  private ServletContext context = null;
108
  private Hashtable connectionPool = new Hashtable();
109
  private String resultStyleURL = null;
110
  private String xmlcatalogfile = null;
111
  private String saxparser = null;
112
  private String datafilepath = null; 
113
  private File dataDirectory = null;
114
  private String servletpath = null; 
115
  private String htmlpath = null; 
116
  private PropertyResourceBundle options = null;
117
  private MetaCatUtil util = null;
118

    
119
  /**
120
   * Initialize the servlet by creating appropriate database connections
121
   */
122
  public void init( ServletConfig config ) throws ServletException {
123
    try {
124
      super.init( config );
125
      this.config = config;
126
      this.context = config.getServletContext(); 
127
      System.out.println("MetaCatServlet Initialize");
128

    
129
      util = new MetaCatUtil();
130

    
131
      // Get the configuration file information
132
      resultStyleURL = util.getOption("resultStyleURL");
133
      xmlcatalogfile = util.getOption("xmlcatalogfile");
134
      saxparser = util.getOption("saxparser");
135
      datafilepath = util.getOption("datafilepath");
136
      dataDirectory = new File(datafilepath);
137
      servletpath = util.getOption("servletpath");
138
      htmlpath = util.getOption("htmlpath");
139

    
140
// MOVED IT TO doGet() & doPost()
141
//      try {
142
//        // Open a pool of db connections
143
//        connectionPool = util.getConnectionPool();
144
//      } catch (Exception e) {
145
//        System.err.println("Error creating pool of database connections");
146
//        System.err.println(e.getMessage());
147
//      }
148
    } catch ( ServletException ex ) {
149
      throw ex;
150
    }
151
  }
152

    
153
  /**
154
   * Close all db connections from the pool
155
   */
156
  public void destroy() {
157
    
158
    if (util != null) {
159
        util.closeConnections();
160
    }
161
  }
162

    
163
  /** Handle "GET" method requests from HTTP clients */
164
  public void doGet (HttpServletRequest request, HttpServletResponse response)
165
    throws ServletException, IOException {
166

    
167
    // Process the data and send back the response
168
    handleGetOrPost(request, response);
169
  }
170

    
171
  /** Handle "POST" method requests from HTTP clients */
172
  public void doPost( HttpServletRequest request, HttpServletResponse response)
173
    throws ServletException, IOException {
174

    
175
    // Process the data and send back the response
176
    handleGetOrPost(request, response);
177
  }
178

    
179
  /**
180
   * Control servlet response depending on the action parameter specified
181
   */
182
  private void handleGetOrPost(HttpServletRequest request, 
183
                               HttpServletResponse response) 
184
                               throws ServletException, IOException 
185
  {
186

    
187
    if ( util == null ) {
188
        util = new MetaCatUtil(); 
189
    }
190
    if ( connectionPool.isEmpty() ) {
191
      try {
192
        // Open a pool of db connections
193
        connectionPool = util.getConnectionPool();
194
      } catch (Exception e) {
195
        System.err.println("Error creating pool of database connections in " +
196
                            " MetaCatServlet.handleGetOrPost");
197
        System.err.println(e.getMessage());
198
      }
199
    }    
200
    // Get a handle to the output stream back to the client
201
    //PrintWriter pwout = response.getWriter();
202
    //response.setContentType("text/html");
203

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

    
395
    AuthSession sess = null;
396
    String un = ((String[])params.get("username"))[0];
397
    String pw = ((String[])params.get("password"))[0];
398
    String action = ((String[])params.get("action"))[0];
399
    String qformat = ((String[])params.get("qformat"))[0];
400
    
401
    try {
402
      sess = new AuthSession();
403
    } catch (Exception e) {
404
      System.out.println("error in MetacatServlet.handleLoginAction: " +
405
                          e.getMessage());
406
      out.println(e.getMessage());
407
      return;
408
    }
409
    boolean isValid = sess.authenticate(request, un, pw);
410
    // format and transform the output
411
    if (qformat.equals("xml")) {
412
      response.setContentType("text/xml");
413
      out.println(sess.getMessage()); 
414
    } else {
415
      Connection conn = null;
416
      try {
417
        conn = util.getConnection();
418
        DBTransform trans = new DBTransform(conn);
419
        response.setContentType("text/html");
420
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
421
                                   "-//W3C//HTML//EN", qformat, out);
422
        util.returnConnection(conn); 
423
      } catch(Exception e) {
424
        util.returnConnection(conn); 
425
      } 
426
      
427
    // any output is returned  
428
    }
429
  }    
430

    
431
  /** 
432
   * Handle the logout request. Close the connection.
433
   */
434
  private void handleLogoutAction(PrintWriter out, Hashtable params, 
435
               HttpServletRequest request, HttpServletResponse response) {
436

    
437
    String qformat = ((String[])params.get("qformat"))[0];
438

    
439
    // close the connection
440
    HttpSession sess = request.getSession(false);
441
    if (sess != null) { sess.invalidate();  }    
442

    
443
    // produce output
444
    StringBuffer output = new StringBuffer();
445
    output.append("<?xml version=\"1.0\"?>");
446
    output.append("<logout>");
447
    output.append("User logged out");
448
    output.append("</logout>");
449

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

    
489
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
490
    
491
    //format and transform the results                                        
492
    if(qformat.equals("xml")) {
493
      response.setContentType("text/xml");
494
      out.println(resultdoc);
495
    } else {
496
      transformResultset(resultdoc, response, out, qformat);
497
    }
498
  }
499
  
500
   /**
501
    * Create the xml query, execute it and display the results.
502
    *
503
    * @param out the output stream to the client
504
    * @param params the Hashtable of parameters that should be included
505
    * in the squery.
506
    * @param response the response object linked to the client
507
    */ 
508
  protected void handleQuery(PrintWriter out, Hashtable params, 
509
                 HttpServletResponse response, String user, String[] groups)
510
  {
511
    //create the query and run it
512
    String xmlquery = DBQuery.createSQuery(params);
513
    Hashtable doclist = runQuery(xmlquery, user, groups);
514
    String qformat = ((String[])params.get("qformat"))[0];
515
    String resultdoc = null;
516
    
517
    resultdoc = createResultDocument(doclist, transformQuery(params));
518

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

    
634
    if(doclist != null)
635
    {
636
      Enumeration doclistkeys = doclist.keys(); 
637
      while (doclistkeys.hasMoreElements()) 
638
      {
639
        docid = (String)doclistkeys.nextElement();
640
        document = (String)doclist.get(docid);
641
        resultset.append("  <document>" + document + "</document>");
642
      }
643
    }
644

    
645
    resultset.append("</resultset>");
646
    return resultset.toString();
647
  }
648
  // END OF SQUERY & QUERY SECTION
649
  
650
 //Exoport section
651
 /**
652
   * Handle the "export" request of data package from Metacat in zip format
653
   * @param params the Hashtable of HTTP request parameters
654
   * @param response the HTTP response object linked to the client
655
   * @param user the username sent the request
656
   * @param groups the user's groupnames
657
   */
658
  private void handleExportAction(Hashtable params,
659
                    HttpServletResponse response, String user, String[] groups)
660
  {
661
    ServletOutputStream out = null;
662
    ZipOutputStream zOut = null;
663
    DocumentImpl docImpls=null;
664
    DBQuery queryObj=null;
665
    Connection conn = null;
666
    String[] docs = new String[10];
667
    String docId = "";
668

    
669
    try
670
    {
671
      // read the params
672
      if (params.containsKey("docid")) {
673
        docs = (String[])params.get("docid");
674
      }
675

    
676
      //get the connection to database
677
      conn = util.getConnection();
678
      queryObj = new DBQuery(conn, saxparser);//"saxparser" have to use though
679
                                              //it is not standard
680
      docId=docs[0];
681
      out = response.getOutputStream();
682
      response.setContentType("application/zip"); //MIME type
683
      zOut = new ZipOutputStream(out);
684
      zOut =queryObj.getZippedPackage(docId, out, user, groups);
685
      zOut.finish(); //terminate the zip file
686
      zOut.close();  //close the zip stream
687
    } 
688
    catch (Exception e)
689
    {
690
      try
691
      {
692
        response.setContentType("text/xml"); //MIME type
693
        if (out != null)
694
        {
695
            PrintWriter pw = new PrintWriter(out);
696
            pw.println("<?xml version=\"1.0\"?>");
697
            pw.println("<error>");
698
            pw.println(e.getMessage());
699
            pw.println("</error>");
700
            pw.close();
701
        }
702

    
703
        if ( zOut != null )
704
        {
705
          zOut.close();
706
        }
707
      }
708
      catch (IOException ioe)
709
      {
710
        util.debugMessage("Problem with the servlet output " +
711
                           "in MetacatServlet.handleReadAction: " +
712
                           ioe.getMessage());
713
        
714

    
715
      }
716

    
717
      util.debugMessage("Error in MetacatServlet.handleReadAction: " +
718
                         e.getMessage());
719
      
720
    }//catch
721

    
722
  }//handleExportAction
723
  
724
  // READ SECTION
725
  /** 
726
   * Handle the "read" request of metadata/data files from Metacat
727
   * or any files from Internet;
728
   * transformed metadata XML document into HTML presentation if requested;
729
   * zip files when more than one were requested.
730
   *
731
   * @param params the Hashtable of HTTP request parameters
732
   * @param response the HTTP response object linked to the client
733
   * @param user the username sent the request
734
   * @param groups the user's groupnames
735
   */
736
  private void handleReadAction(Hashtable params, HttpServletResponse response,
737
                                String user, String[] groups) 
738
  {
739
    ServletOutputStream out = null;
740
    ZipOutputStream zout = null;
741
    
742
    try {
743
      String[] docs = new String[0];
744
      String docid = "";
745
      String qformat = "";
746
      String abstrpath = null;
747
      boolean zip = false;
748
      // read the params
749
      if (params.containsKey("docid")) {
750
        docs = (String[])params.get("docid");
751
      }
752
      if (params.containsKey("qformat")) {
753
        qformat = ((String[])params.get("qformat"))[0];
754
      }
755
      if (params.containsKey("abstractpath")) {
756
        abstrpath = ((String[])params.get("abstractpath"))[0];
757
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
758
          viewAbstract(response, abstrpath, docs[0]);
759
          return;
760
        }
761
      }
762
      if ( (docs.length > 1) || qformat.equals("zip") ) {
763
        zip = true;
764
        out = response.getOutputStream();
765
        response.setContentType("application/zip"); //MIME type
766
        zout = new ZipOutputStream(out);
767
      }
768
      // go through the list of docs to read
769
      for (int i=0; i < docs.length; i++ ) {
770
        try {
771

    
772
          URL murl = new URL(docs[i]);
773
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
774
          // case docid="http://.../?docid=aaa" 
775
          // or docid="metacat://.../?docid=bbb"
776
          if (murlQueryStr.containsKey("docid")) {
777
            // get only docid, eliminate the rest
778
            docid = (String)murlQueryStr.get("docid");
779
            if ( zip ) {
780
              addDocToZip(docid, zout, user, groups);
781
            } else {
782
              readFromMetacat(response, docid, qformat, abstrpath,
783
                              user, groups, zip, zout);
784
            }
785

    
786
          // case docid="http://.../filename"
787
          } else {
788
            docid = docs[i];
789
            if ( zip ) {
790
              addDocToZip(docid, zout, user, groups);
791
            } else {
792
              readFromURLConnection(response, docid);
793
            }
794
          }
795

    
796
        // case docid="ccc"
797
        } catch (MalformedURLException mue) {
798
          docid = docs[i];
799
          if ( zip ) {
800
            addDocToZip(docid, zout, user, groups);
801
          } else {
802
            readFromMetacat(response, docid, qformat, abstrpath,
803
                            user, groups, zip, zout);
804
          }
805
        }
806
        
807
      } /* end for */
808
      
809
      if ( zip ) {
810
        zout.finish(); //terminate the zip file
811
        zout.close();  //close the zip stream
812
      }
813
      
814
  
815
    } catch (Exception e) {
816
      try {
817
        response.setContentType("text/xml"); //MIME type
818
        //PrintWriter pw = response.getWriter();
819
        if (out != null) {
820
            PrintWriter pw = new PrintWriter(out);
821
            pw.println("<?xml version=\"1.0\"?>");
822
            pw.println("<error>");
823
            pw.println(e.getMessage());
824
            pw.println("</error>");
825
            pw.close();
826
        }
827
        //if ( out != null ) { out.close(); }
828
        if ( zout != null ) { zout.close(); }
829
      } catch (IOException ioe) {
830
        System.out.println("Problem with the servlet output " +
831
                           "in MetacatServlet.handleReadAction: " +
832
                           ioe.getMessage());
833
        ioe.printStackTrace(System.out);
834
        
835
      }
836

    
837
      System.out.println("Error in MetacatServlet.handleReadAction: " +
838
                         e.getMessage());
839
      e.printStackTrace(System.out);
840
    }
841
    
842
  }
843
  
844
  // read metadata or data from Metacat
845
  private void readFromMetacat(HttpServletResponse response, String docid,
846
                               String qformat, String abstrpath, String user,
847
                             String[] groups, boolean zip, ZipOutputStream zout)
848
               throws ClassNotFoundException, IOException, SQLException, 
849
                      McdbException, Exception
850
  {
851
    Connection conn = null;
852
    try {
853
      conn = util.getConnection();
854
      DocumentImpl doc = new DocumentImpl(conn, docid);
855
      
856
      //check the permission for read
857
      if (!doc.hasReadPermission(conn, user, groups, docid))
858
      {
859
        Exception e = new Exception("User " + user + " does not have permission"
860
                       +" to read the document with the docid " + docid);
861
        util.returnConnection(conn);
862
        throw e;
863
      }
864
     
865
      if ( doc.getRootNodeID() == 0 ) {
866
        // this is data file
867
        ServletOutputStream out = response.getOutputStream(); 
868
        String filepath = util.getOption("datafilepath");
869
        if(!filepath.endsWith("/")) {
870
          filepath += "/";
871
        }
872
        String filename = filepath + docid;      //MIME type
873
        String contentType = getServletContext().getMimeType(filename);
874
        if (contentType == null) {
875
          if (filename.endsWith(".xml")) {
876
            contentType="text/xml";
877
          } else if (filename.endsWith(".css")) {
878
            contentType="text/css";
879
          } else if (filename.endsWith(".dtd")) {
880
            contentType="text/plain";
881
          } else if (filename.endsWith(".xsd")) {
882
            contentType="text/xml";
883
          } else if (filename.endsWith("/")) {
884
            contentType="text/html";
885
          } else {
886
            File f = new File(filename);
887
            if ( f.isDirectory() ) {
888
              contentType="text/html";
889
            } else {
890
              contentType="application/octet-stream";
891
            }
892
          }
893
        }
894
        response.setContentType(contentType);
895
        // if we decide to use "application/octet-stream" for all data returns
896
        // response.setContentType("application/octet-stream");
897
        FileInputStream fin = null;
898
        try {
899
          fin = new FileInputStream(filename);
900
          byte[] buf = new byte[4 * 1024]; // 4K buffer
901
          int b = fin.read(buf);
902
          while (b != -1) {
903
            out.write(buf, 0, b);
904
            b = fin.read(buf);
905
          }
906
        } finally {
907
          if (fin != null) fin.close();
908
        }
909

    
910
      } else {
911
        // this is metadata doc
912
        if ( qformat.equals("xml") ) { 
913
          // set content type first
914
          response.setContentType("text/xml");   //MIME type
915
          PrintWriter out = response.getWriter();
916
          doc.toXml(out);
917
        } else {
918
          response.setContentType("text/html");  //MIME type
919
          PrintWriter out = response.getWriter();
920
    
921
          // Look up the document type
922
          String doctype = doc.getDoctype();
923
          // Transform the document to the new doctype
924
          DBTransform dbt = new DBTransform(conn);
925
          dbt.transformXMLDocument(doc.toString(),
926
                                   doctype,"-//W3C//HTML//EN", qformat, out);
927
        }
928
      
929
      }
930
    } finally {
931
      util.returnConnection(conn);
932
    }
933
    
934
  }
935
  
936
  // read data from URLConnection
937
  private void readFromURLConnection(HttpServletResponse response, String docid)
938
               throws IOException, MalformedURLException
939
  {
940
    ServletOutputStream out = response.getOutputStream(); 
941
    String contentType = getServletContext().getMimeType(docid); //MIME type
942
    if (contentType == null) {
943
      if (docid.endsWith(".xml")) {
944
        contentType="text/xml";
945
      } else if (docid.endsWith(".css")) {
946
        contentType="text/css";
947
      } else if (docid.endsWith(".dtd")) {
948
        contentType="text/plain";
949
      } else if (docid.endsWith(".xsd")) {
950
        contentType="text/xml";
951
      } else if (docid.endsWith("/")) {
952
        contentType="text/html";
953
      } else {
954
        File f = new File(docid);
955
        if ( f.isDirectory() ) {
956
          contentType="text/html";
957
        } else {
958
          contentType="application/octet-stream";
959
        }
960
      }
961
    }
962
    response.setContentType(contentType);
963
    // if we decide to use "application/octet-stream" for all data returns
964
    // response.setContentType("application/octet-stream");
965

    
966
    // this is http url
967
    URL url = new URL(docid);
968
    BufferedInputStream bis = null;
969
    try {
970
      bis = new BufferedInputStream(url.openStream());
971
      byte[] buf = new byte[4 * 1024]; // 4K buffer
972
      int b = bis.read(buf);
973
      while (b != -1) {
974
        out.write(buf, 0, b);
975
        b = bis.read(buf);
976
      }
977
    } finally {
978
      if (bis != null) bis.close();
979
    }
980
    
981
  }
982
  
983
  // read file/doc and write to ZipOutputStream
984
  private void addDocToZip(String docid, ZipOutputStream zout, 
985
                              String user, String[] groups)
986
               throws ClassNotFoundException, IOException, SQLException, 
987
                      McdbException, Exception
988
  {
989
    byte[] bytestring = null;
990
    ZipEntry zentry = null;
991

    
992
    try {
993
      URL url = new URL(docid);
994

    
995
      // this http url; read from URLConnection; add to zip
996
      zentry = new ZipEntry(docid);
997
      zout.putNextEntry(zentry);
998
      BufferedInputStream bis = null;
999
      try {
1000
        bis = new BufferedInputStream(url.openStream());
1001
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1002
        int b = bis.read(buf);
1003
        while(b != -1) {
1004
          zout.write(buf, 0, b);
1005
          b = bis.read(buf);
1006
        }
1007
      } finally {
1008
        if (bis != null) bis.close();
1009
      }
1010
      zout.closeEntry();
1011

    
1012
    } catch (MalformedURLException mue) {
1013
      
1014
      // this is metacat doc (data file or metadata doc)
1015
      Connection conn = null;
1016
      try {
1017
        conn = util.getConnection();
1018
        DocumentImpl doc = new DocumentImpl(conn, docid);
1019
        
1020
        //check the permission for read
1021
        if (!doc.hasReadPermission(conn, user, groups, docid))
1022
        {
1023
          Exception e = new Exception("User " + user + " does not have "
1024
                    +"permission to read the document with the docid " + docid);
1025
          util.returnConnection(conn);
1026
          throw e;
1027
        } 
1028
        
1029
        if ( doc.getRootNodeID() == 0 ) {
1030
          // this is data file; add file to zip
1031
          String filepath = util.getOption("datafilepath");
1032
          if(!filepath.endsWith("/")) {
1033
            filepath += "/";
1034
          }
1035
          String filename = filepath + doc.getDocname();
1036
          zentry = new ZipEntry(filename);
1037
          zout.putNextEntry(zentry);
1038
          FileInputStream fin = null;
1039
          try {
1040
            fin = new FileInputStream(filename);
1041
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1042
            int b = fin.read(buf);
1043
            while (b != -1) {
1044
              zout.write(buf, 0, b);
1045
              b = fin.read(buf);
1046
            }
1047
          } finally {
1048
            if (fin != null) fin.close();
1049
          }
1050
          zout.closeEntry();
1051

    
1052
        } else {
1053
          // this is metadata doc; add doc to zip
1054
          bytestring = doc.toString().getBytes();
1055
          zentry = new ZipEntry(docid + ".xml");
1056
          zentry.setSize(bytestring.length);
1057
          zout.putNextEntry(zentry);
1058
          zout.write(bytestring, 0, bytestring.length);
1059
          zout.closeEntry();
1060
        }
1061
      } finally {
1062
        util.returnConnection(conn);
1063
      }
1064
      
1065
    }
1066
      
1067
  }
1068
  
1069
  // view abstract within document
1070
  private void viewAbstract(HttpServletResponse response,
1071
                            String abstractpath, String docid)
1072
               throws ClassNotFoundException, IOException, SQLException,
1073
                      McdbException, Exception
1074
  {
1075
    Connection conn = null;
1076
    try {
1077
      conn = util.getConnection();
1078
    
1079
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid, conn);
1080
    
1081
      response.setContentType("text/html");  //MIME type
1082
      PrintWriter out = response.getWriter();
1083
      out.println("<html><head><title>Abstract</title></head>");
1084
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1085
      for (int i=0; i<abstracts.length; i++) {
1086
        out.println("<p>" + (String)abstracts[i] + "</p>");
1087
      }
1088
      out.println("</body></html>");
1089

    
1090
    } finally {
1091
      util.returnConnection(conn);
1092
    }
1093
  }
1094
  // END OF READ SECTION
1095
    
1096
  // INSERT/UPDATE SECTION
1097
  /** 
1098
   * Handle the database putdocument request and write an XML document 
1099
   * to the database connection
1100
   */
1101
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params, 
1102
               HttpServletResponse response, String user, String[] groups) {
1103

    
1104
    Connection conn = null;
1105

    
1106
    try {
1107
      // Get the document indicated
1108
      String[] doctext = (String[])params.get("doctext");
1109

    
1110
      String pub = null;
1111
      if (params.containsKey("public")) {
1112
        pub = ((String[])params.get("public"))[0];
1113
      }
1114

    
1115
      StringReader dtd = null;
1116
      if (params.containsKey("dtdtext")) {
1117
        String[] dtdtext = (String[])params.get("dtdtext");
1118
        try {
1119
          if ( !dtdtext[0].equals("") ) {
1120
            dtd = new StringReader(dtdtext[0]);
1121
          }
1122
        } catch (NullPointerException npe) {}
1123
      }
1124
      
1125
      StringReader xml = null;
1126
      boolean validate = false;
1127
      try {
1128
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1129
        // in order to decide whether to use validation parser
1130
        validate = validateXML(doctext[0]);
1131
        xml = new StringReader(doctext[0]);
1132

    
1133
        String[] action = (String[])params.get("action");
1134
        String[] docid = (String[])params.get("docid");
1135
        String newdocid = null;
1136

    
1137
        String doAction = null;
1138
        if (action[0].equals("insert")) {
1139
          doAction = "INSERT";
1140
        } else if (action[0].equals("update")) {
1141
          doAction = "UPDATE";
1142
        }
1143

    
1144
        try {
1145
          // get a connection from the pool
1146
          conn = util.getConnection();
1147

    
1148
          // write the document to the database
1149
          try {
1150
            String accNumber = docid[0];
1151
            if (accNumber.equals("")) {
1152
              accNumber = null;
1153
            }
1154
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1155
                                          accNumber, user, groups, validate);
1156
          } catch (NullPointerException npe) {
1157
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1158
                                          null, user, groups, validate);
1159
          }
1160
        } finally {
1161
          util.returnConnection(conn);
1162
        }    
1163

    
1164
        // set content type and other response header fields first
1165
        response.setContentType("text/xml");
1166
        out.println("<?xml version=\"1.0\"?>");
1167
        out.println("<success>");
1168
        out.println("<docid>" + newdocid + "</docid>"); 
1169
        out.println("</success>");
1170

    
1171
      } catch (NullPointerException npe) {
1172
        response.setContentType("text/xml");
1173
        out.println("<?xml version=\"1.0\"?>");
1174
        out.println("<error>");
1175
        out.println(npe.getMessage()); 
1176
        out.println("</error>");
1177
      }
1178
    } catch (Exception e) {
1179
      response.setContentType("text/xml");
1180
      out.println("<?xml version=\"1.0\"?>");
1181
      out.println("<error>");
1182
      out.println(e.getMessage()); 
1183
      if (e instanceof SAXException) {
1184
        Exception e2 = ((SAXException)e).getException();
1185
        out.println("<error>");
1186
        try
1187
        {
1188
          out.println(e2.getMessage());
1189
        }
1190
        catch(NullPointerException npe)
1191
        {
1192
          out.println(e.getMessage());
1193
        }
1194
        out.println("</error>");
1195
      }
1196
      //e.printStackTrace(out);
1197
      out.println("</error>");
1198
    }
1199
  }
1200

    
1201
  /** 
1202
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1203
   * in order to decide whether to use validation parser
1204
   */
1205
  private static boolean validateXML(String xmltext) throws IOException {
1206
    
1207
    StringReader xmlreader = new StringReader(xmltext);
1208
    StringBuffer cbuff = new StringBuffer();
1209
    java.util.Stack st = new java.util.Stack();
1210
    boolean validate = false;
1211
    int c;
1212
    int inx;
1213
    
1214
    // read from the stream until find the keywords
1215
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1216
      cbuff.append((char)c);
1217

    
1218
      // "<!DOCTYPE" keyword is found; put it in the stack
1219
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1220
        cbuff = new StringBuffer();
1221
        st.push("<!DOCTYPE");
1222
      }
1223
      // "PUBLIC" keyword is found; put it in the stack
1224
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1225
        cbuff = new StringBuffer();
1226
        st.push("PUBLIC");
1227
      }
1228
      // "SYSTEM" keyword is found; put it in the stack
1229
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1230
        cbuff = new StringBuffer();
1231
        st.push("SYSTEM");
1232
      }
1233
      // ">" character is found; put it in the stack
1234
      // ">" is found twice: fisrt from <?xml ...?> 
1235
      // and second from <!DOCTYPE ... >
1236
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1237
        cbuff = new StringBuffer();
1238
        st.push(">");
1239
      }
1240
    }
1241

    
1242
    // close the stream
1243
    xmlreader.close();
1244

    
1245
    // check the stack whether it contains the keywords:
1246
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1247
    if ( st.size() == 4 ) {
1248
      if ( ((String)st.pop()).equals(">") &&
1249
           ( ((String)st.peek()).equals("PUBLIC") |
1250
             ((String)st.pop()).equals("SYSTEM") ) &&
1251
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1252
        validate = true;
1253
      }
1254
    }
1255

    
1256
System.out.println("Validation is " + validate);
1257
    return validate;
1258
  }
1259
  // END OF INSERT/UPDATE SECTION
1260

    
1261
  // DELETE SECTION
1262
  /** 
1263
   * Handle the database delete request and delete an XML document 
1264
   * from the database connection
1265
   */
1266
  private void handleDeleteAction(PrintWriter out, Hashtable params, 
1267
               HttpServletResponse response, String user, String[] groups) {
1268

    
1269
    String[] docid = (String[])params.get("docid");
1270
    Connection conn = null;
1271

    
1272
    // delete the document from the database
1273
    try {
1274
      // get a connection from the pool
1275
      conn = util.getConnection();
1276
                                      // NOTE -- NEED TO TEST HERE
1277
                                      // FOR EXISTENCE OF DOCID PARAM
1278
                                      // BEFORE ACCESSING ARRAY
1279
      try { 
1280
        DocumentImpl.delete(conn, docid[0], user, groups);
1281
        response.setContentType("text/xml");
1282
        out.println("<?xml version=\"1.0\"?>");
1283
        out.println("<success>");
1284
        out.println("Document deleted."); 
1285
        out.println("</success>");
1286
      } catch (AccessionNumberException ane) {
1287
        response.setContentType("text/xml");
1288
        out.println("<?xml version=\"1.0\"?>");
1289
        out.println("<error>");
1290
        out.println("Error deleting document!!!");
1291
        out.println(ane.getMessage()); 
1292
        out.println("</error>");
1293
      }
1294
    } catch (Exception e) {
1295
      response.setContentType("text/xml");
1296
      out.println("<?xml version=\"1.0\"?>");
1297
      out.println("<error>");
1298
      out.println(e.getMessage()); 
1299
      out.println("</error>");
1300
    } finally {
1301
      util.returnConnection(conn);
1302
    }  
1303
  }
1304
  // END OF DELETE SECTION
1305
  
1306
  // VALIDATE SECTION
1307
  /** 
1308
   * Handle the validation request and return the results to the requestor
1309
   */
1310
  private void handleValidateAction(PrintWriter out, Hashtable params, 
1311
               HttpServletResponse response) {
1312

    
1313
    // Get the document indicated
1314
    String valtext = null;
1315
    
1316
    try {
1317
      valtext = ((String[])params.get("valtext"))[0];
1318
    } catch (Exception nullpe) {
1319

    
1320
      Connection conn = null;
1321
      String docid = null;
1322
      try {
1323
        // Find the document id number
1324
        docid = ((String[])params.get("docid"))[0]; 
1325

    
1326
        // get a connection from the pool
1327
        conn = util.getConnection();
1328

    
1329
        // Get the document indicated from the db
1330
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
1331
        valtext = xmldoc.toString();
1332

    
1333
      } catch (NullPointerException npe) {
1334
        response.setContentType("text/xml");
1335
        out.println("<error>Error getting document ID: " + docid + "</error>");
1336
        if ( conn != null ) { util.returnConnection(conn); }
1337
        return;
1338
      } catch (Exception e) {
1339
        response.setContentType("text/html");
1340
        out.println(e.getMessage()); 
1341
      } finally {
1342
        util.returnConnection(conn);
1343
      }  
1344
    }
1345

    
1346
    Connection conn = null;
1347
    try {
1348
      // get a connection from the pool
1349
      conn = util.getConnection();
1350
      DBValidate valobj = new DBValidate(saxparser,conn);
1351
      boolean valid = valobj.validateString(valtext);
1352

    
1353
      // set content type and other response header fields first
1354
      response.setContentType("text/xml");
1355
      out.println(valobj.returnErrors());
1356

    
1357
    } catch (NullPointerException npe2) {
1358
      // set content type and other response header fields first
1359
      response.setContentType("text/xml");
1360
      out.println("<error>Error validating document.</error>"); 
1361
    } catch (Exception e) {
1362
      response.setContentType("text/html");
1363
      out.println(e.getMessage()); 
1364
    } finally {
1365
      util.returnConnection(conn);
1366
    }  
1367
  }
1368
  // END OF VALIDATE SECTION
1369
 
1370
  // OTHER ACTION HANDLERS
1371
  
1372
  /** 
1373
   * Handle "getaccesscontrol" action.
1374
   * Read Access Control List from db connection in XML format
1375
   */
1376
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params, 
1377
                                       HttpServletResponse response, 
1378
                                       String username, String[] groupnames) {
1379

    
1380
    Connection conn = null;
1381
    String docid = ((String[])params.get("docid"))[0];
1382
    
1383
    try {
1384

    
1385
        // get connection from the pool
1386
        conn = util.getConnection();
1387
        AccessControlList aclobj = new AccessControlList(conn);
1388
        String acltext = aclobj.getACL(docid, username, groupnames);
1389
        out.println(acltext);
1390

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

    
1402
  /** 
1403
   * Handle the "getprincipals" action.
1404
   * Read all principals from authentication scheme in XML format
1405
   */
1406
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1407
                                         String password) {
1408

    
1409
    Connection conn = null;
1410

    
1411
    try {
1412

    
1413
        // get connection from the pool
1414
        AuthSession auth = new AuthSession();
1415
        String principals = auth.getPrincipals(user, password);
1416
        out.println(principals);
1417

    
1418
    } catch (Exception e) {
1419
      out.println("<?xml version=\"1.0\"?>");
1420
      out.println("<error>");
1421
      out.println(e.getMessage());
1422
      out.println("</error>");
1423
    } finally {
1424
      util.returnConnection(conn);
1425
    }  
1426
    
1427
  }
1428

    
1429
  /** 
1430
   * Handle "getdoctypes" action.
1431
   * Read all doctypes from db connection in XML format
1432
   */
1433
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params, 
1434
                                       HttpServletResponse response) {
1435

    
1436
    Connection conn = null;
1437
    
1438
    try {
1439

    
1440
        // get connection from the pool
1441
        conn = util.getConnection();
1442
        DBUtil dbutil = new DBUtil(conn);
1443
        String doctypes = dbutil.readDoctypes();
1444
        out.println(doctypes);
1445

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

    
1457
  /** 
1458
   * Handle the "getdtdschema" action.
1459
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1460
   */
1461
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1462
                                        HttpServletResponse response) {
1463

    
1464
    Connection conn = null;
1465
    String doctype = null;
1466
    String[] doctypeArr = (String[])params.get("doctype");
1467

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

    
1474
    try {
1475

    
1476
        // get connection from the pool
1477
        conn = util.getConnection();
1478
        DBUtil dbutil = new DBUtil(conn);
1479
        String dtdschema = dbutil.readDTDSchema(doctype);
1480
        out.println(dtdschema);
1481

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

    
1493
  /** 
1494
   * Handle the "getdataguide" action.
1495
   * Read Data Guide for a given doctype from db connection in XML format
1496
   */
1497
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params, 
1498
                                        HttpServletResponse response) {
1499

    
1500
    Connection conn = null;
1501
    String doctype = null;
1502
    String[] doctypeArr = (String[])params.get("doctype");
1503

    
1504
    // get only the first doctype specified in the list of doctypes
1505
    // it could be done for all doctypes in that list
1506
    if (doctypeArr != null) {
1507
        doctype = ((String[])params.get("doctype"))[0]; 
1508
    }
1509

    
1510
    try {
1511

    
1512
        // get connection from the pool
1513
        conn = util.getConnection();
1514
        DBUtil dbutil = new DBUtil(conn);
1515
        String dataguide = dbutil.readDataGuide(doctype);
1516
        out.println(dataguide);
1517

    
1518
    } catch (Exception e) {
1519
      out.println("<?xml version=\"1.0\"?>");
1520
      out.println("<error>");
1521
      out.println(e.getMessage());
1522
      out.println("</error>");
1523
    } finally {
1524
      util.returnConnection(conn);
1525
    }  
1526
    
1527
  }
1528

    
1529
  /** 
1530
   * Handle the "getlastdocid" action.
1531
   * Get the latest docid with rev number from db connection in XML format
1532
   */
1533
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params, 
1534
                                        HttpServletResponse response) {
1535

    
1536
    Connection conn = null;
1537
    String scope = ((String[])params.get("scope"))[0];
1538
    if (scope == null) {
1539
        scope = ((String[])params.get("username"))[0];
1540
    }
1541

    
1542
    try {
1543

    
1544
        // get connection from the pool
1545
        conn = util.getConnection();
1546
        DBUtil dbutil = new DBUtil(conn);
1547
        String lastDocid = dbutil.getMaxDocid(scope);
1548
        out.println("<?xml version=\"1.0\"?>");
1549
        out.println("<lastDocid>");
1550
        out.println("  <scope>" + scope + "</scope>");
1551
        out.println("  <docid>" + lastDocid + "</docid>");
1552
        out.println("</lastDocid>");
1553

    
1554
    } catch (Exception e) {
1555
      out.println("<?xml version=\"1.0\"?>");
1556
      out.println("<error>");
1557
      out.println(e.getMessage());
1558
      out.println("</error>");
1559
    } finally {
1560
      util.returnConnection(conn);
1561
    }  
1562
    
1563
  }
1564

    
1565
  /** 
1566
   * Handle documents passed to metacat that are encoded using the 
1567
   * "multipart/form-data" mime type.  This is typically used for uploading
1568
   * data files which may be binary and large.
1569
   */
1570
  private void handleMultipartForm(HttpServletRequest request,
1571
                                   HttpServletResponse response) 
1572
  {
1573
    PrintWriter out = null;
1574
    String action = null;
1575

    
1576
    // Parse the multipart form, and save the parameters in a Hashtable and
1577
    // save the FileParts in a hashtable
1578

    
1579
    Hashtable params = new Hashtable();
1580
    Hashtable fileList = new Hashtable();
1581

    
1582
    try {
1583
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1584
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); //200MB
1585
      Part part;
1586
      while ((part = mp.readNextPart()) != null) {
1587
        String name = part.getName();
1588

    
1589
        if (part.isParam()) {
1590
          // it's a parameter part
1591
          ParamPart paramPart = (ParamPart) part;
1592
          String value = paramPart.getStringValue();
1593
          params.put(name, value);
1594
          if (name.equals("action")) {
1595
            action = value;
1596
          }
1597
        } else if (part.isFile()) {
1598
          // it's a file part
1599
          FilePart filePart = (FilePart) part;
1600
          fileList.put(name, filePart);
1601

    
1602
          // Stop once the first file part is found, otherwise going onto the
1603
          // next part prevents access to the file contents.  So...for upload
1604
          // to work, the datafile must be the last part
1605
          break;
1606
        }
1607
      }
1608
    } catch (IOException ioe) {
1609
      try {
1610
        out = response.getWriter();
1611
      } catch (IOException ioe2) {
1612
        System.err.println("Fatal Error: couldn't get response output stream.");
1613
      }
1614
      out.println("<?xml version=\"1.0\"?>");
1615
      out.println("<error>");
1616
      out.println("Error: problem reading multipart data.");
1617
      out.println("</error>");
1618
    }
1619

    
1620
    // Get the session information
1621
    String username = null;
1622
    String password = null;
1623
    String[] groupnames = null;
1624
    String sess_id = null;
1625

    
1626
    // be aware of session expiration on every request  
1627
    HttpSession sess = request.getSession(true);
1628
    if (sess.isNew()) {
1629
      // session expired or has not been stored b/w user requests
1630
      username = "public";
1631
      sess.setAttribute("username", username);
1632
    } else {
1633
      username = (String)sess.getAttribute("username");
1634
      password = (String)sess.getAttribute("password");
1635
      groupnames = (String[])sess.getAttribute("groupnames");
1636
      try {
1637
        sess_id = (String)sess.getId();
1638
      } catch(IllegalStateException ise) {
1639
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1640
                           "happen: the session should be valid: " + 
1641
                           ise.getMessage());
1642
      }
1643
    }  
1644

    
1645
    if ( action.equals("upload")) {
1646
      if (username != null &&  !username.equals("public")) {
1647
        handleUploadAction(request, response, params, fileList, 
1648
                           username, groupnames);
1649
      } else {
1650
        try {
1651
          out = response.getWriter();
1652
        } catch (IOException ioe2) {
1653
          util.debugMessage("Fatal Error: couldn't get response "+
1654
                                                              "output stream.");
1655
        }
1656
        out.println("<?xml version=\"1.0\"?>");
1657
        out.println("<error>");
1658
        out.println("Permission denied for " + action);
1659
        out.println("</error>");
1660
      }
1661
    } else {
1662
      try {
1663
        out = response.getWriter();
1664
      } catch (IOException ioe2) {
1665
        System.err.println("Fatal Error: couldn't get response output stream.");
1666
      }
1667
      out.println("<?xml version=\"1.0\"?>");
1668
      out.println("<error>");
1669
      out.println("Error: action not registered.  Please report this error.");
1670
      out.println("</error>");
1671
    }
1672
  }
1673

    
1674
  /** 
1675
   * Handle the upload action by saving the attached file to disk and 
1676
   * registering it in the Metacat db
1677
   */
1678
  private void handleUploadAction(HttpServletRequest request,
1679
                                  HttpServletResponse response, 
1680
                                  Hashtable params, Hashtable fileList, 
1681
                                  String username, String[] groupnames)
1682
  {
1683
    PrintWriter out = null;
1684
    Connection conn = null;
1685
    String action = null;
1686
    String docid = null;
1687

    
1688
    response.setContentType("text/xml");
1689
    try {
1690
      out = response.getWriter();
1691
    } catch (IOException ioe2) {
1692
      System.err.println("Fatal Error: couldn't get response output stream.");
1693
    }
1694

    
1695
    if (params.containsKey("docid")) {
1696
      docid = (String)params.get("docid");
1697
    }
1698

    
1699
    // Make sure we have a docid and datafile
1700
    if (docid != null && fileList.containsKey("datafile")) {
1701

    
1702
      // Get a reference to the file part of the form
1703
      FilePart filePart = (FilePart)fileList.get("datafile");
1704
      String fileName = filePart.getFileName();
1705
      MetaCatUtil.debugMessage("Uploading filename: " + fileName);
1706

    
1707
      // Check if the right file existed in the uploaded data
1708
      if (fileName != null) {
1709
  
1710
        try {
1711
          // register the file in the database (which generates an exception if
1712
          // the docid is not acceptable or other untoward things happen
1713
          DocumentImpl.registerDocument(fileName, "BIN", docid, username, 1);
1714
    
1715
          // Save the data file to disk using "docid" as the name
1716
          dataDirectory.mkdirs();
1717
          File newFile = new File(dataDirectory, docid);
1718
          long size = filePart.writeTo(newFile);
1719

    
1720
          // set content type and other response header fields first
1721
          out.println("<?xml version=\"1.0\"?>");
1722
          out.println("<success>");
1723
          out.println("<docid>" + docid + "</docid>"); 
1724
          out.println("<size>" + size + "</size>"); 
1725
          out.println("</success>");
1726
    
1727
        } catch (Exception e) {
1728
          out.println("<?xml version=\"1.0\"?>");
1729
          out.println("<error>");
1730
          out.println(e.getMessage()); 
1731
          out.println("</error>");
1732
        }
1733
      } else {
1734
        // the field did not contain a file
1735
        out.println("<?xml version=\"1.0\"?>");
1736
        out.println("<error>");
1737
        out.println("The uploaded data did not contain a valid file."); 
1738
        out.println("</error>");
1739
      }
1740
    } else {
1741
      // Error bcse docid missing or file missing
1742
      out.println("<?xml version=\"1.0\"?>");
1743
      out.println("<error>");
1744
      out.println("The uploaded data did not contain a valid docid " +
1745
                  "or valid file."); 
1746
      out.println("</error>");
1747
    }
1748
  }
1749
}
(29-29/40)