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-05-07 16:57:12 -0700 (Tue, 07 May 2002) $'
11
 * '$Revision: 1056 $'
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, 1);
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
        
292
        handleExportAction(params, response, username, groupnames);
293
      } else if (action.equals("read")) {
294
        handleReadAction(params, response, username, groupnames);
295
      } else if (action.equals("insert") || action.equals("update")) {
296
        PrintWriter out = response.getWriter();
297
        if ( (username != null) &&  !username.equals("public") ) {
298
          handleInsertOrUpdateAction(out,params,response,username,groupnames);
299
        } else {  
300
          out.println("Permission denied for " + action);
301
        }  
302
      } else if (action.equals("delete")) {
303
        PrintWriter out = response.getWriter();
304
        if ( (username != null) &&  !username.equals("public") ) {
305
          handleDeleteAction(out, params, response, username, groupnames);
306
        } else {  
307
          out.println("Permission denied for " + action);
308
        }  
309
      } else if (action.equals("validate")) {
310
        PrintWriter out = response.getWriter();
311
        handleValidateAction(out, params, response); 
312
      } else if (action.equals("getaccesscontrol")) {
313
        PrintWriter out = response.getWriter();
314
        handleGetAccessControlAction(out,params,response,username,groupnames);
315
      } else if (action.equals("getprincipals")) {
316
        PrintWriter out = response.getWriter();
317
        handleGetPrincipalsAction(out, username, password);  
318
      } else if (action.equals("getdoctypes")) {
319
        PrintWriter out = response.getWriter();
320
        handleGetDoctypesAction(out, params, response);  
321
      } else if (action.equals("getdtdschema")) {
322
        PrintWriter out = response.getWriter();
323
        handleGetDTDSchemaAction(out, params, response);  
324
      } else if (action.equals("getdataguide")) {
325
        PrintWriter out = response.getWriter();
326
        handleGetDataGuideAction(out, params, response);  
327
      } else if (action.equals("getlastdocid")) {
328
        PrintWriter out = response.getWriter();
329
        handleGetMaxDocidAction(out, params, response);  
330
      } else if (action.equals("login") || action.equals("logout")) {
331
      } else if (action.equals("protocoltest")) {
332
        String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
333
        try {
334
          testURL = ((String[])params.get("url"))[0];
335
        } catch (Throwable t) {
336
        }
337
        String phandler = System.getProperty("java.protocol.handler.pkgs");
338
        response.setContentType("text/html");
339
        PrintWriter out = response.getWriter();
340
        out.println("<body bgcolor=\"white\">");
341
        out.println("<p>Handler property: <code>" + phandler + "</code></p>");
342
        out.println("<p>Starting test for:<br>");
343
        out.println("    " + testURL + "</p>");
344
        try {
345
          URL u = new URL(testURL);
346
          out.println("<pre>");
347
          out.println("Protocol: " + u.getProtocol());
348
          out.println("    Host: " + u.getHost());
349
          out.println("    Port: " + u.getPort());
350
          out.println("    Path: " + u.getPath());
351
          out.println("     Ref: " + u.getRef());
352
          String pquery = u.getQuery();
353
          out.println("   Query: " + pquery);
354
          out.println("  Params: ");
355
          if (pquery != null) {
356
            Hashtable qparams = util.parseQuery(u.getQuery());
357
            for (Enumeration en = qparams.keys(); en.hasMoreElements(); ) {
358
              String pname = (String)en.nextElement();
359
              String pvalue = (String)qparams.get(pname);
360
              out.println("    " + pname + ": " + pvalue);
361
            }
362
          }
363
          out.println("</pre>");
364
          out.println("</body>");
365
          out.close();
366
        } catch (MalformedURLException mue) {
367
          System.out.println("bad url from MetacatServlet.handleGetOrPost");
368
          out.println(mue.getMessage());
369
          mue.printStackTrace(out);
370
          out.close();
371
        }
372
      } else {
373
        PrintWriter out = response.getWriter();
374
        out.println("<?xml version=\"1.0\"?>");
375
        out.println("<error>");
376
        out.println("Error: action not registered.  Please report this error.");
377
        out.println("</error>");
378
      }
379
      
380
      util.closeConnections();
381
      // Close the stream to the client
382
      // out.close();
383
    }
384
  }
385
  
386
  // LOGIN & LOGOUT SECTION
387
  /** 
388
   * Handle the login request. Create a new session object.
389
   * Do user authentication through the session.
390
   */
391
  private void handleLoginAction(PrintWriter out, Hashtable params, 
392
               HttpServletRequest request, HttpServletResponse response) {
393

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

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

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

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

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

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

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

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

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

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

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

    
675
      //get the connection to database
676
      conn = util.getConnection();
677
      queryObj = new DBQuery(conn, saxparser);//"saxparser" have to use though
678
                                              //it is not standard
679
      docId=docs[0];
680
      out = response.getOutputStream();
681
      response.setContentType("application/zip"); //MIME type
682
      zOut = new ZipOutputStream(out);
683
      zOut =queryObj.getZippedPackage(docId, out, user, groups);
684
      zOut.finish(); //terminate the zip file
685
      zOut.close();  //close the zip stream
686
      
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
    finally 
722
    {
723
      util.returnConnection(conn);
724
    }
725

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

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

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

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

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

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

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

    
996
    try {
997
      URL url = new URL(docid);
998

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

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

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

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

    
1108
    Connection conn = null;
1109

    
1110
    try {
1111
      // Get the document indicated
1112
      String[] doctext = (String[])params.get("doctext");
1113

    
1114
      String pub = null;
1115
      if (params.containsKey("public")) {
1116
        pub = ((String[])params.get("public"))[0];
1117
      }
1118

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

    
1137
        String[] action = (String[])params.get("action");
1138
        String[] docid = (String[])params.get("docid");
1139
        String newdocid = null;
1140

    
1141
        String doAction = null;
1142
        if (action[0].equals("insert")) {
1143
          doAction = "INSERT";
1144
        } else if (action[0].equals("update")) {
1145
          doAction = "UPDATE";
1146
        }
1147

    
1148
        try {
1149
          // get a connection from the pool
1150
          conn = util.getConnection();
1151

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

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

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

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

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

    
1246
    // close the stream
1247
    xmlreader.close();
1248

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

    
1260
System.out.println("Validation is " + validate);
1261
    return validate;
1262
  }
1263
  // END OF INSERT/UPDATE SECTION
1264

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

    
1273
    String[] docid = (String[])params.get("docid");
1274
    Connection conn = null;
1275

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

    
1317
    // Get the document indicated
1318
    String valtext = null;
1319
    
1320
    try {
1321
      valtext = ((String[])params.get("valtext"))[0];
1322
    } catch (Exception nullpe) {
1323

    
1324
      Connection conn = null;
1325
      String docid = null;
1326
      try {
1327
        // Find the document id number
1328
        docid = ((String[])params.get("docid"))[0]; 
1329

    
1330
        // get a connection from the pool
1331
        conn = util.getConnection();
1332

    
1333
        // Get the document indicated from the db
1334
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
1335
        valtext = xmldoc.toString();
1336

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

    
1350
    Connection conn = null;
1351
    try {
1352
      // get a connection from the pool
1353
      conn = util.getConnection();
1354
      DBValidate valobj = new DBValidate(saxparser,conn);
1355
      boolean valid = valobj.validateString(valtext);
1356

    
1357
      // set content type and other response header fields first
1358
      response.setContentType("text/xml");
1359
      out.println(valobj.returnErrors());
1360

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

    
1384
    Connection conn = null;
1385
    String docid = ((String[])params.get("docid"))[0];
1386
    
1387
    try {
1388

    
1389
        // get connection from the pool
1390
        conn = util.getConnection();
1391
        AccessControlList aclobj = new AccessControlList(conn);
1392
        String acltext = aclobj.getACL(docid, username, groupnames);
1393
        out.println(acltext);
1394

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

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

    
1413
    Connection conn = null;
1414

    
1415
    try {
1416

    
1417
        // get connection from the pool
1418
        AuthSession auth = new AuthSession();
1419
        String principals = auth.getPrincipals(user, password);
1420
        out.println(principals);
1421

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

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

    
1440
    Connection conn = null;
1441
    
1442
    try {
1443

    
1444
        // get connection from the pool
1445
        conn = util.getConnection();
1446
        DBUtil dbutil = new DBUtil(conn);
1447
        String doctypes = dbutil.readDoctypes();
1448
        out.println(doctypes);
1449

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

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

    
1468
    Connection conn = null;
1469
    String doctype = null;
1470
    String[] doctypeArr = (String[])params.get("doctype");
1471

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

    
1478
    try {
1479

    
1480
        // get connection from the pool
1481
        conn = util.getConnection();
1482
        DBUtil dbutil = new DBUtil(conn);
1483
        String dtdschema = dbutil.readDTDSchema(doctype);
1484
        out.println(dtdschema);
1485

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

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

    
1504
    Connection conn = null;
1505
    String doctype = null;
1506
    String[] doctypeArr = (String[])params.get("doctype");
1507

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

    
1514
    try {
1515

    
1516
        // get connection from the pool
1517
        conn = util.getConnection();
1518
        DBUtil dbutil = new DBUtil(conn);
1519
        String dataguide = dbutil.readDataGuide(doctype);
1520
        out.println(dataguide);
1521

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

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

    
1540
    Connection conn = null;
1541
    String scope = ((String[])params.get("scope"))[0];
1542
    if (scope == null) {
1543
        scope = ((String[])params.get("username"))[0];
1544
    }
1545

    
1546
    try {
1547

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

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

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

    
1580
    // Parse the multipart form, and save the parameters in a Hashtable and
1581
    // save the FileParts in a hashtable
1582

    
1583
    Hashtable params = new Hashtable();
1584
    Hashtable fileList = new Hashtable();
1585

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

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

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

    
1624
    // Get the session information
1625
    String username = null;
1626
    String password = null;
1627
    String[] groupnames = null;
1628
    String sess_id = null;
1629

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

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

    
1678
  /** 
1679
   * Handle the upload action by saving the attached file to disk and 
1680
   * registering it in the Metacat db
1681
   */
1682
  private void handleUploadAction(HttpServletRequest request,
1683
                                  HttpServletResponse response, 
1684
                                  Hashtable params, Hashtable fileList, 
1685
                                  String username, String[] groupnames)
1686
  {
1687
    PrintWriter out = null;
1688
    Connection conn = null;
1689
    String action = null;
1690
    String docid = null;
1691
  
1692
    response.setContentType("text/xml");
1693
    try 
1694
    {
1695
      out = response.getWriter();
1696
    } 
1697
    catch (IOException ioe2) 
1698
    {
1699
      System.err.println("Fatal Error: couldn't get response output stream.");
1700
    }
1701

    
1702
    if (params.containsKey("docid")) 
1703
    {
1704
      docid = (String)params.get("docid");
1705
    }
1706

    
1707
    // Make sure we have a docid and datafile
1708
    if (docid != null && fileList.containsKey("datafile")) {
1709

    
1710
      // Get a reference to the file part of the form
1711
      FilePart filePart = (FilePart)fileList.get("datafile");
1712
      String fileName = filePart.getFileName();
1713
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
1714

    
1715
      // Check if the right file existed in the uploaded data
1716
      if (fileName != null) {
1717
  
1718
        try 
1719
        {
1720
           //If document get lock data file grant
1721
           if (DocumentImpl.getDataFileLockGrant(docid))
1722
           {
1723
               // register the file in the database (which generates an exception
1724
              //if the docid is not acceptable or other untoward things happen
1725
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
1726
    
1727
              // Save the data file to disk using "docid" as the name
1728
              dataDirectory.mkdirs();
1729
              File newFile = new File(dataDirectory, docid);
1730
              long size = filePart.writeTo(newFile);
1731
              if ((util.getOption("replicationdata")).equals("on"))
1732
              {
1733
                // force replcation data file if metacat was configured
1734
                if (ReplicationHandler.getServerLocation(docid)==1)
1735
                {//local host document
1736
                  conn=util.getConnection();
1737
                  ForceReplicationHandler frh = new ForceReplicationHandler
1738
             (docid, "insert", false, ReplicationHandler.buildServerList(conn));
1739
                  util.returnConnection(conn);
1740
                }//if
1741
                else
1742
                {
1743
                  //if it is super hub, replication to server list
1744
                  if ((util.getOption("hub")).equals("super"))
1745
                  {
1746
                    ForceReplicationHandler frh = new ForceReplicationHandler
1747
                    (docid,true, ReplicationHandler.buildServerList(conn));
1748
                    util.returnConnection(conn);
1749
                  }//if
1750
                  else
1751
                  {
1752
                    //only replicate to home host of the document
1753
                    String id=util.getDocIdFromString(docid);
1754
                    ForceReplicationHandler frh = new ForceReplicationHandler
1755
                    (docid, true, ReplicationHandler.getHomeServer(id));
1756
                  }//else
1757
                }//else
1758
              }//if
1759
              // set content type and other response header fields first
1760
              out.println("<?xml version=\"1.0\"?>");
1761
              out.println("<success>");
1762
              out.println("<docid>" + docid + "</docid>"); 
1763
              out.println("<size>" + size + "</size>"); 
1764
              out.println("</success>");
1765
           }//if
1766
    
1767
        } //try
1768
        catch (Exception e) 
1769
        {
1770
          out.println("<?xml version=\"1.0\"?>");
1771
          out.println("<error>");
1772
          out.println(e.getMessage()); 
1773
          out.println("</error>");
1774
        }
1775
        finally
1776
        {
1777
          util.returnConnection(conn);
1778
         }
1779
      }
1780
      else 
1781
      {
1782
        // the field did not contain a file
1783
        out.println("<?xml version=\"1.0\"?>");
1784
        out.println("<error>");
1785
        out.println("The uploaded data did not contain a valid file."); 
1786
        out.println("</error>");
1787
      }
1788
    } 
1789
    else 
1790
    {
1791
      // Error bcse docid missing or file missing
1792
      out.println("<?xml version=\"1.0\"?>");
1793
      out.println("<error>");
1794
      out.println("The uploaded data did not contain a valid docid " +
1795
                  "or valid file."); 
1796
      out.println("</error>");
1797
    }
1798
  }
1799
}
(30-30/41)