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-06-13 11:54:51 -0700 (Thu, 13 Jun 2002) $'
11
 * '$Revision: 1217 $'
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 String resultStyleURL = null;
109
  private String xmlcatalogfile = null;
110
  private String saxparser = null;
111
  private String datafilepath = null; 
112
  private File dataDirectory = null;
113
  private String servletpath = null; 
114
  private String htmlpath = null; 
115
  private PropertyResourceBundle options = null;
116
  private MetaCatUtil util = null;
117
  private DBConnectionPool connPool = 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
      //initial DBConnection pool
132
      connPool = DBConnectionPool.getInstance();
133

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

    
143

    
144
    } catch ( ServletException ex ) {
145
      throw ex;
146
    } catch (SQLException e) {
147
      MetaCatUtil.debugMessage("Error in MetacatServlet.init: "
148
                                          +e.getMessage(), 20);
149
    }
150
  }
151

    
152
  /**
153
   * Close all db connections from the pool
154
   */
155
  public void destroy() {
156
      // Close all db connection  
157
      connPool.release();
158
  }
159

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

    
164
    // Process the data and send back the response
165
    handleGetOrPost(request, response);
166
  }
167

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

    
172
    // Process the data and send back the response
173
    handleGetOrPost(request, response);
174
  }
175

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

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

    
407
    AuthSession sess = null;
408
    String un = ((String[])params.get("username"))[0];
409
    String pw = ((String[])params.get("password"))[0];
410
    String action = ((String[])params.get("action"))[0];
411
    String qformat = ((String[])params.get("qformat"))[0];
412
    
413
    try {
414
      sess = new AuthSession();
415
    } catch (Exception e) {
416
      System.out.println("error in MetacatServlet.handleLoginAction: " +
417
                          e.getMessage());
418
      out.println(e.getMessage());
419
      return;
420
    }
421
    boolean isValid = sess.authenticate(request, un, pw);
422
    // format and transform the output
423
    if (qformat.equals("xml")) {
424
      response.setContentType("text/xml");
425
      out.println(sess.getMessage()); 
426
    } else {
427
     
428
      try {
429
        
430
        DBTransform trans = new DBTransform();
431
        response.setContentType("text/html");
432
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
433
                                   "-//W3C//HTML//EN", qformat, out);
434
         
435
      } catch(Exception e) {
436
        
437
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
438
                                +e.getMessage(), 30);
439
      } 
440
      
441
    // any output is returned  
442
    }
443
  }    
444

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

    
451
    String qformat = ((String[])params.get("qformat"))[0];
452

    
453
    // close the connection
454
    HttpSession sess = request.getSession(false);
455
    if (sess != null) { sess.invalidate();  }    
456

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

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

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

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

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

    
664
    resultset.append("</resultset>");
665
    return resultset.toString();
666
  }
667
  // END OF SQUERY & QUERY SECTION
668
  
669
 //Exoport section
670
 /**
671
   * Handle the "export" request of data package from Metacat in zip format
672
   * @param params the Hashtable of HTTP request parameters
673
   * @param response the HTTP response object linked to the client
674
   * @param user the username sent the request
675
   * @param groups the user's groupnames
676
   */
677
  private void handleExportAction(Hashtable params,
678
                    HttpServletResponse response, String user, String[] groups)
679
  {
680
    ServletOutputStream out = null;
681
    ZipOutputStream zOut = null;
682
    DocumentImpl docImpls=null;
683
    DBQuery queryObj=null;
684
  
685
    String[] docs = new String[10];
686
    String docId = "";
687

    
688
    try
689
    {
690
      // read the params
691
      if (params.containsKey("docid")) {
692
        docs = (String[])params.get("docid");
693
      }
694

    
695
   
696
      queryObj = new DBQuery(saxparser);//"saxparser" have to use though
697
                                              //it is not standard
698
      docId=docs[0];
699
      out = response.getOutputStream();
700
      response.setContentType("application/zip"); //MIME type
701
      zOut = new ZipOutputStream(out);
702
      zOut =queryObj.getZippedPackage(docId, out, user, groups);
703
      zOut.finish(); //terminate the zip file
704
      zOut.close();  //close the zip stream
705
      
706
    } 
707
    catch (Exception e)
708
    {
709
      try
710
      {
711
        response.setContentType("text/xml"); //MIME type
712
        if (out != null)
713
        {
714
            PrintWriter pw = new PrintWriter(out);
715
            pw.println("<?xml version=\"1.0\"?>");
716
            pw.println("<error>");
717
            pw.println(e.getMessage());
718
            pw.println("</error>");
719
            pw.close();
720
        }
721

    
722
        if ( zOut != null )
723
        {
724
          zOut.close();
725
        }
726
      }
727
      catch (IOException ioe)
728
      {
729
        MetaCatUtil.debugMessage("Problem with the servlet output " +
730
                           "in MetacatServlet.handleReadAction: " +
731
                           ioe.getMessage(), 30);
732
        
733

    
734
      }
735

    
736
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
737
                         e.getMessage(), 30);
738
      
739
    }//catch
740
   
741

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

    
792
          URL murl = new URL(docs[i]);
793
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
794
          // case docid="http://.../?docid=aaa" 
795
          // or docid="metacat://.../?docid=bbb"
796
          if (murlQueryStr.containsKey("docid")) {
797
            // get only docid, eliminate the rest
798
            docid = (String)murlQueryStr.get("docid");
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
          // case docid="http://.../filename"
807
          } else {
808
            docid = docs[i];
809
            if ( zip ) {
810
              addDocToZip(docid, zout, user, groups);
811
            } else {
812
              readFromURLConnection(response, docid);
813
            }
814
          }
815

    
816
        // case docid="ccc"
817
        } catch (MalformedURLException mue) {
818
          docid = docs[i];
819
          if ( zip ) {
820
            addDocToZip(docid, zout, user, groups);
821
          } else {
822
            readFromMetacat(response, docid, qformat, abstrpath,
823
                            user, groups, zip, zout);
824
          }
825
        }
826
        
827
      } /* end for */
828
      
829
      if ( zip ) {
830
        zout.finish(); //terminate the zip file
831
        zout.close();  //close the zip stream
832
      }
833
      
834
  
835
    } catch (Exception e) {
836
      try {
837
        response.setContentType("text/xml"); //MIME type
838
        //PrintWriter pw = response.getWriter();
839
        if (out != null) {
840
            PrintWriter pw = new PrintWriter(out);
841
            pw.println("<?xml version=\"1.0\"?>");
842
            pw.println("<error>");
843
            pw.println(e.getMessage());
844
            pw.println("</error>");
845
            pw.close();
846
        }
847
        //if ( out != null ) { out.close(); }
848
        if ( zout != null ) { zout.close(); }
849
      } catch (IOException ioe) {
850
        System.out.println("Problem with the servlet output " +
851
                           "in MetacatServlet.handleReadAction: " +
852
                           ioe.getMessage());
853
        ioe.printStackTrace(System.out);
854
        
855
      }
856

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

    
931
      } else {
932
        // this is metadata doc
933
        if ( qformat.equals("xml") ) { 
934
          
935
          // set content type first
936
          response.setContentType("text/xml");   //MIME type
937
          PrintWriter out = response.getWriter();
938
          doc.toXml(out);
939
        } else {
940
          response.setContentType("text/html");  //MIME type
941
          PrintWriter out = response.getWriter();
942
    
943
          // Look up the document type
944
          String doctype = doc.getDoctype();
945
          // Transform the document to the new doctype
946
          DBTransform dbt = new DBTransform();
947
          dbt.transformXMLDocument(doc.toString(),
948
                                   doctype,"-//W3C//HTML//EN", qformat, out);
949
        }
950
      
951
      }
952
    } catch (Exception except) {
953
      throw except;
954
    
955
    }
956
    
957
  }
958
  
959
  // read data from URLConnection
960
  private void readFromURLConnection(HttpServletResponse response, String docid)
961
               throws IOException, MalformedURLException
962
  {
963
    ServletOutputStream out = response.getOutputStream(); 
964
    String contentType = getServletContext().getMimeType(docid); //MIME type
965
    if (contentType == null) {
966
      if (docid.endsWith(".xml")) {
967
        contentType="text/xml";
968
      } else if (docid.endsWith(".css")) {
969
        contentType="text/css";
970
      } else if (docid.endsWith(".dtd")) {
971
        contentType="text/plain";
972
      } else if (docid.endsWith(".xsd")) {
973
        contentType="text/xml";
974
      } else if (docid.endsWith("/")) {
975
        contentType="text/html";
976
      } else {
977
        File f = new File(docid);
978
        if ( f.isDirectory() ) {
979
          contentType="text/html";
980
        } else {
981
          contentType="application/octet-stream";
982
        }
983
      }
984
    }
985
    response.setContentType(contentType);
986
    // if we decide to use "application/octet-stream" for all data returns
987
    // response.setContentType("application/octet-stream");
988

    
989
    // this is http url
990
    URL url = new URL(docid);
991
    BufferedInputStream bis = null;
992
    try {
993
      bis = new BufferedInputStream(url.openStream());
994
      byte[] buf = new byte[4 * 1024]; // 4K buffer
995
      int b = bis.read(buf);
996
      while (b != -1) {
997
        out.write(buf, 0, b);
998
        b = bis.read(buf);
999
      }
1000
    } finally {
1001
      if (bis != null) bis.close();
1002
    }
1003
    
1004
  }
1005
  
1006
  // read file/doc and write to ZipOutputStream
1007
  private void addDocToZip(String docid, ZipOutputStream zout, 
1008
                              String user, String[] groups)
1009
               throws ClassNotFoundException, IOException, SQLException, 
1010
                      McdbException, Exception
1011
  {
1012
    byte[] bytestring = null;
1013
    ZipEntry zentry = null;
1014

    
1015
    try {
1016
      URL url = new URL(docid);
1017

    
1018
      // this http url; read from URLConnection; add to zip
1019
      zentry = new ZipEntry(docid);
1020
      zout.putNextEntry(zentry);
1021
      BufferedInputStream bis = null;
1022
      try {
1023
        bis = new BufferedInputStream(url.openStream());
1024
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1025
        int b = bis.read(buf);
1026
        while(b != -1) {
1027
          zout.write(buf, 0, b);
1028
          b = bis.read(buf);
1029
        }
1030
      } finally {
1031
        if (bis != null) bis.close();
1032
      }
1033
      zout.closeEntry();
1034

    
1035
    } catch (MalformedURLException mue) {
1036
      
1037
      // this is metacat doc (data file or metadata doc)
1038
  
1039
      try {
1040
       
1041
        DocumentImpl doc = new DocumentImpl(docid);
1042
        
1043
        //check the permission for read
1044
        if (!doc.hasReadPermission(user, groups, docid))
1045
        {
1046
          Exception e = new Exception("User " + user + " does not have "
1047
                    +"permission to read the document with the docid " + docid);
1048
        
1049
          throw e;
1050
        } 
1051
        
1052
        if ( doc.getRootNodeID() == 0 ) {
1053
          // this is data file; add file to zip
1054
          String filepath = util.getOption("datafilepath");
1055
          if(!filepath.endsWith("/")) {
1056
            filepath += "/";
1057
          }
1058
          String filename = filepath + doc.getDocname();
1059
          zentry = new ZipEntry(filename);
1060
          zout.putNextEntry(zentry);
1061
          FileInputStream fin = null;
1062
          try {
1063
            fin = new FileInputStream(filename);
1064
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1065
            int b = fin.read(buf);
1066
            while (b != -1) {
1067
              zout.write(buf, 0, b);
1068
              b = fin.read(buf);
1069
            }
1070
          } finally {
1071
            if (fin != null) fin.close();
1072
          }
1073
          zout.closeEntry();
1074

    
1075
        } else {
1076
          // this is metadata doc; add doc to zip
1077
          bytestring = doc.toString().getBytes();
1078
          zentry = new ZipEntry(docid + ".xml");
1079
          zentry.setSize(bytestring.length);
1080
          zout.putNextEntry(zentry);
1081
          zout.write(bytestring, 0, bytestring.length);
1082
          zout.closeEntry();
1083
        }
1084
      } catch (Exception except) {
1085
        throw except;
1086
       
1087
      }
1088
      
1089
    }
1090
      
1091
  }
1092
  
1093
  // view abstract within document
1094
  private void viewAbstract(HttpServletResponse response,
1095
                            String abstractpath, String docid)
1096
               throws ClassNotFoundException, IOException, SQLException,
1097
                      McdbException, Exception
1098
  {
1099
  
1100
    PrintWriter out =null;
1101
    try {
1102
   
1103
      response.setContentType("text/html");  //MIME type
1104
      out = response.getWriter();
1105
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1106
      out.println("<html><head><title>Abstract</title></head>");
1107
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1108
      for (int i=0; i<abstracts.length; i++) {
1109
        out.println("<p>" + (String)abstracts[i] + "</p>");
1110
      }
1111
      out.println("</body></html>");
1112

    
1113
    } catch (Exception e) {
1114
       out.println("<?xml version=\"1.0\"?>");
1115
       out.println("<error>");
1116
       out.println(e.getMessage());
1117
       out.println("</error>");
1118
    
1119
   
1120
    }
1121
  }
1122
  // END OF READ SECTION
1123
    
1124
  // INSERT/UPDATE SECTION
1125
  /** 
1126
   * Handle the database putdocument request and write an XML document 
1127
   * to the database connection
1128
   */
1129
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params, 
1130
               HttpServletResponse response, String user, String[] groups) {
1131

    
1132
    DBConnection dbConn = null;
1133
    int serialNumber = -1;
1134

    
1135
    try {
1136
      // Get the document indicated
1137
      String[] doctext = (String[])params.get("doctext");
1138

    
1139
      String pub = null;
1140
      if (params.containsKey("public")) {
1141
        pub = ((String[])params.get("public"))[0];
1142
      }
1143

    
1144
      StringReader dtd = null;
1145
      if (params.containsKey("dtdtext")) {
1146
        String[] dtdtext = (String[])params.get("dtdtext");
1147
        try {
1148
          if ( !dtdtext[0].equals("") ) {
1149
            dtd = new StringReader(dtdtext[0]);
1150
          }
1151
        } catch (NullPointerException npe) {}
1152
      }
1153
      
1154
      StringReader xml = null;
1155
      boolean validate = false;
1156
      try {
1157
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1158
        // in order to decide whether to use validation parser
1159
        validate = validateXML(doctext[0]);
1160
        xml = new StringReader(doctext[0]);
1161

    
1162
        String[] action = (String[])params.get("action");
1163
        String[] docid = (String[])params.get("docid");
1164
        String newdocid = null;
1165

    
1166
        String doAction = null;
1167
        if (action[0].equals("insert")) {
1168
          doAction = "INSERT";
1169
        } else if (action[0].equals("update")) {
1170
          doAction = "UPDATE";
1171
        }
1172
        
1173
        try 
1174
        {
1175
          // get a connection from the pool
1176
          dbConn=DBConnectionPool.
1177
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1178
          serialNumber=dbConn.getCheckOutSerialNumber();
1179
          
1180
          // write the document to the database
1181
          try 
1182
          {
1183
            String accNumber = docid[0];
1184
            if (accNumber.equals("")) 
1185
            {
1186
              accNumber = null;
1187
            }//if
1188
            newdocid = DocumentImpl.write(dbConn, xml, pub, dtd, doAction,
1189
                                          accNumber, user, groups, validate);
1190
            
1191
          }//try 
1192
          catch (NullPointerException npe) 
1193
          {
1194
            newdocid = DocumentImpl.write(dbConn, xml, pub, dtd, doAction,
1195
                                          null, user, groups, validate);
1196
          }//catch
1197
        }//try 
1198
        finally 
1199
        {
1200
          // Return db connection
1201
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1202
        }    
1203

    
1204
        // set content type and other response header fields first
1205
        response.setContentType("text/xml");
1206
        out.println("<?xml version=\"1.0\"?>");
1207
        out.println("<success>");
1208
        out.println("<docid>" + newdocid + "</docid>"); 
1209
        out.println("</success>");
1210

    
1211
      } catch (NullPointerException npe) {
1212
        response.setContentType("text/xml");
1213
        out.println("<?xml version=\"1.0\"?>");
1214
        out.println("<error>");
1215
        out.println(npe.getMessage()); 
1216
        out.println("</error>");
1217
      }
1218
    } catch (Exception e) {
1219
      response.setContentType("text/xml");
1220
      out.println("<?xml version=\"1.0\"?>");
1221
      out.println("<error>");
1222
      out.println(e.getMessage()); 
1223
      if (e instanceof SAXException) {
1224
        Exception e2 = ((SAXException)e).getException();
1225
        out.println("<error>");
1226
        try
1227
        {
1228
          out.println(e2.getMessage());
1229
        }
1230
        catch(NullPointerException npe)
1231
        {
1232
          out.println(e.getMessage());
1233
        }
1234
        out.println("</error>");
1235
      }
1236
      //e.printStackTrace(out);
1237
      out.println("</error>");
1238
    }
1239
  }
1240

    
1241
  /** 
1242
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1243
   * in order to decide whether to use validation parser
1244
   */
1245
  private static boolean validateXML(String xmltext) throws IOException {
1246
    
1247
    StringReader xmlreader = new StringReader(xmltext);
1248
    StringBuffer cbuff = new StringBuffer();
1249
    java.util.Stack st = new java.util.Stack();
1250
    boolean validate = false;
1251
    int c;
1252
    int inx;
1253
    
1254
    // read from the stream until find the keywords
1255
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1256
      cbuff.append((char)c);
1257

    
1258
      // "<!DOCTYPE" keyword is found; put it in the stack
1259
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1260
        cbuff = new StringBuffer();
1261
        st.push("<!DOCTYPE");
1262
      }
1263
      // "PUBLIC" keyword is found; put it in the stack
1264
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1265
        cbuff = new StringBuffer();
1266
        st.push("PUBLIC");
1267
      }
1268
      // "SYSTEM" keyword is found; put it in the stack
1269
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1270
        cbuff = new StringBuffer();
1271
        st.push("SYSTEM");
1272
      }
1273
      // ">" character is found; put it in the stack
1274
      // ">" is found twice: fisrt from <?xml ...?> 
1275
      // and second from <!DOCTYPE ... >
1276
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1277
        cbuff = new StringBuffer();
1278
        st.push(">");
1279
      }
1280
    }
1281

    
1282
    // close the stream
1283
    xmlreader.close();
1284

    
1285
    // check the stack whether it contains the keywords:
1286
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1287
    if ( st.size() == 4 ) {
1288
      if ( ((String)st.pop()).equals(">") &&
1289
           ( ((String)st.peek()).equals("PUBLIC") |
1290
             ((String)st.pop()).equals("SYSTEM") ) &&
1291
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1292
        validate = true;
1293
      }
1294
    }
1295

    
1296
System.out.println("Validation is " + validate);
1297
    return validate;
1298
  }
1299
  // END OF INSERT/UPDATE SECTION
1300

    
1301
  // DELETE SECTION
1302
  /** 
1303
   * Handle the database delete request and delete an XML document 
1304
   * from the database connection
1305
   */
1306
  private void handleDeleteAction(PrintWriter out, Hashtable params, 
1307
               HttpServletResponse response, String user, String[] groups) {
1308

    
1309
    String[] docid = (String[])params.get("docid");
1310
  
1311
    // delete the document from the database
1312
    try {
1313
 
1314
                                      // NOTE -- NEED TO TEST HERE
1315
                                      // FOR EXISTENCE OF DOCID PARAM
1316
                                      // BEFORE ACCESSING ARRAY
1317
      try { 
1318
        DocumentImpl.delete(docid[0], user, groups);
1319
        response.setContentType("text/xml");
1320
        out.println("<?xml version=\"1.0\"?>");
1321
        out.println("<success>");
1322
        out.println("Document deleted."); 
1323
        out.println("</success>");
1324
      } catch (AccessionNumberException ane) {
1325
        response.setContentType("text/xml");
1326
        out.println("<?xml version=\"1.0\"?>");
1327
        out.println("<error>");
1328
        out.println("Error deleting document!!!");
1329
        out.println(ane.getMessage()); 
1330
        out.println("</error>");
1331
      }
1332
    } catch (Exception e) {
1333
      response.setContentType("text/xml");
1334
      out.println("<?xml version=\"1.0\"?>");
1335
      out.println("<error>");
1336
      out.println(e.getMessage()); 
1337
      out.println("</error>");
1338
    } 
1339
  }
1340
  // END OF DELETE SECTION
1341
  
1342
  // VALIDATE SECTION
1343
  /** 
1344
   * Handle the validation request and return the results to the requestor
1345
   */
1346
  private void handleValidateAction(PrintWriter out, Hashtable params, 
1347
               HttpServletResponse response) {
1348

    
1349
    // Get the document indicated
1350
    String valtext = null;
1351
    DBConnection dbConn = null;
1352
    int serialNumber = -1;
1353
    
1354
    try {
1355
      valtext = ((String[])params.get("valtext"))[0];
1356
    } catch (Exception nullpe) {
1357

    
1358
     
1359
      String docid = null;
1360
      try {
1361
        // Find the document id number
1362
        docid = ((String[])params.get("docid"))[0]; 
1363

    
1364
      
1365
        // Get the document indicated from the db
1366
        DocumentImpl xmldoc = new DocumentImpl(docid);
1367
        valtext = xmldoc.toString();
1368

    
1369
      } catch (NullPointerException npe) {
1370
        response.setContentType("text/xml");
1371
        out.println("<error>Error getting document ID: " + docid + "</error>");
1372
        //if ( conn != null ) { util.returnConnection(conn); }
1373
        return;
1374
      } catch (Exception e) {
1375
        response.setContentType("text/html");
1376
        out.println(e.getMessage()); 
1377
      } 
1378
    }
1379

    
1380
  
1381
    try {
1382
      // get a connection from the pool
1383
      dbConn=DBConnectionPool.
1384
                  getDBConnection("MetaCatServlet.handleValidateAction");
1385
      serialNumber=dbConn.getCheckOutSerialNumber();
1386
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1387
      boolean valid = valobj.validateString(valtext);
1388

    
1389
      // set content type and other response header fields first
1390
      response.setContentType("text/xml");
1391
      out.println(valobj.returnErrors());
1392

    
1393
    } catch (NullPointerException npe2) {
1394
      // set content type and other response header fields first
1395
      response.setContentType("text/xml");
1396
      out.println("<error>Error validating document.</error>"); 
1397
    } catch (Exception e) {
1398
      response.setContentType("text/html");
1399
      out.println(e.getMessage()); 
1400
    } finally {
1401
      // Return db connection
1402
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1403
    }  
1404
  }
1405
  // END OF VALIDATE SECTION
1406
 
1407
  // OTHER ACTION HANDLERS
1408
  
1409
  /** 
1410
   * Handle "getaccesscontrol" action.
1411
   * Read Access Control List from db connection in XML format
1412
   */
1413
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params, 
1414
                                       HttpServletResponse response, 
1415
                                       String username, String[] groupnames) {
1416

    
1417
    DBConnection dbConn = null;
1418
    int serialNumber = -1;
1419
    String docid = ((String[])params.get("docid"))[0];
1420
    
1421
    try {
1422

    
1423
        // get connection from the pool
1424
        dbConn=DBConnectionPool.
1425
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1426
        serialNumber=dbConn.getCheckOutSerialNumber();
1427
        AccessControlList aclobj = new AccessControlList(dbConn);
1428
        String acltext = aclobj.getACL(docid, username, groupnames);
1429
        out.println(acltext);
1430

    
1431
    } catch (Exception e) {
1432
      out.println("<?xml version=\"1.0\"?>");
1433
      out.println("<error>");
1434
      out.println(e.getMessage());
1435
      out.println("</error>");
1436
    } finally {
1437
      // Retrun db connection to pool
1438
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1439
    }  
1440
    
1441
  }
1442

    
1443
  /** 
1444
   * Handle the "getprincipals" action.
1445
   * Read all principals from authentication scheme in XML format
1446
   */
1447
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1448
                                         String password) {
1449

    
1450
   
1451
    try {
1452

    
1453
        
1454
        AuthSession auth = new AuthSession();
1455
        String principals = auth.getPrincipals(user, password);
1456
        out.println(principals);
1457

    
1458
    } catch (Exception e) {
1459
      out.println("<?xml version=\"1.0\"?>");
1460
      out.println("<error>");
1461
      out.println(e.getMessage());
1462
      out.println("</error>");
1463
    } 
1464
    
1465
  }
1466

    
1467
  /** 
1468
   * Handle "getdoctypes" action.
1469
   * Read all doctypes from db connection in XML format
1470
   */
1471
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params, 
1472
                                       HttpServletResponse response) {
1473

    
1474
   
1475
    try {
1476

    
1477
     
1478
        DBUtil dbutil = new DBUtil();
1479
        String doctypes = dbutil.readDoctypes();
1480
        out.println(doctypes);
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
    } 
1488
    
1489
  }
1490

    
1491
  /** 
1492
   * Handle the "getdtdschema" action.
1493
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1494
   */
1495
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1496
                                        HttpServletResponse response) {
1497

    
1498
   
1499
    String doctype = null;
1500
    String[] doctypeArr = (String[])params.get("doctype");
1501

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

    
1508
    try {
1509

    
1510
       
1511
        DBUtil dbutil = new DBUtil();
1512
        String dtdschema = dbutil.readDTDSchema(doctype);
1513
        out.println(dtdschema);
1514

    
1515
    } catch (Exception e) {
1516
      out.println("<?xml version=\"1.0\"?>");
1517
      out.println("<error>");
1518
      out.println(e.getMessage());
1519
      out.println("</error>");
1520
    } 
1521
    
1522
  }
1523

    
1524
  /** 
1525
   * Handle the "getdataguide" action.
1526
   * Read Data Guide for a given doctype from db connection in XML format
1527
   */
1528
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params, 
1529
                                        HttpServletResponse response) {
1530

    
1531
  
1532
    String doctype = null;
1533
    String[] doctypeArr = (String[])params.get("doctype");
1534

    
1535
    // get only the first doctype specified in the list of doctypes
1536
    // it could be done for all doctypes in that list
1537
    if (doctypeArr != null) {
1538
        doctype = ((String[])params.get("doctype"))[0]; 
1539
    }
1540

    
1541
    try {
1542

    
1543
  
1544
        DBUtil dbutil = new DBUtil();
1545
        String dataguide = dbutil.readDataGuide(doctype);
1546
        out.println(dataguide);
1547

    
1548
    } catch (Exception e) {
1549
      out.println("<?xml version=\"1.0\"?>");
1550
      out.println("<error>");
1551
      out.println(e.getMessage());
1552
      out.println("</error>");
1553
    }
1554
    
1555
  }
1556

    
1557
  /** 
1558
   * Handle the "getlastdocid" action.
1559
   * Get the latest docid with rev number from db connection in XML format
1560
   */
1561
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params, 
1562
                                        HttpServletResponse response) {
1563

    
1564

    
1565
    String scope = ((String[])params.get("scope"))[0];
1566
    if (scope == null) {
1567
        scope = ((String[])params.get("username"))[0];
1568
    }
1569

    
1570
    try {
1571

    
1572
       
1573
        DBUtil dbutil = new DBUtil();
1574
        String lastDocid = dbutil.getMaxDocid(scope);
1575
        out.println("<?xml version=\"1.0\"?>");
1576
        out.println("<lastDocid>");
1577
        out.println("  <scope>" + scope + "</scope>");
1578
        out.println("  <docid>" + lastDocid + "</docid>");
1579
        out.println("</lastDocid>");
1580

    
1581
    } catch (Exception e) {
1582
      out.println("<?xml version=\"1.0\"?>");
1583
      out.println("<error>");
1584
      out.println(e.getMessage());
1585
      out.println("</error>");
1586
    }
1587
    
1588
  }
1589

    
1590
  /** 
1591
   * Handle documents passed to metacat that are encoded using the 
1592
   * "multipart/form-data" mime type.  This is typically used for uploading
1593
   * data files which may be binary and large.
1594
   */
1595
  private void handleMultipartForm(HttpServletRequest request,
1596
                                   HttpServletResponse response) 
1597
  {
1598
    PrintWriter out = null;
1599
    String action = null;
1600

    
1601
    // Parse the multipart form, and save the parameters in a Hashtable and
1602
    // save the FileParts in a hashtable
1603

    
1604
    Hashtable params = new Hashtable();
1605
    Hashtable fileList = new Hashtable();
1606

    
1607
    try {
1608
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1609
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); //200MB
1610
      Part part;
1611
      while ((part = mp.readNextPart()) != null) {
1612
        String name = part.getName();
1613

    
1614
        if (part.isParam()) {
1615
          // it's a parameter part
1616
          ParamPart paramPart = (ParamPart) part;
1617
          String value = paramPart.getStringValue();
1618
          params.put(name, value);
1619
          if (name.equals("action")) {
1620
            action = value;
1621
          }
1622
        } else if (part.isFile()) {
1623
          // it's a file part
1624
          FilePart filePart = (FilePart) part;
1625
          fileList.put(name, filePart);
1626

    
1627
          // Stop once the first file part is found, otherwise going onto the
1628
          // next part prevents access to the file contents.  So...for upload
1629
          // to work, the datafile must be the last part
1630
          break;
1631
        }
1632
      }
1633
    } catch (IOException ioe) {
1634
      try {
1635
        out = response.getWriter();
1636
      } catch (IOException ioe2) {
1637
        System.err.println("Fatal Error: couldn't get response output stream.");
1638
      }
1639
      out.println("<?xml version=\"1.0\"?>");
1640
      out.println("<error>");
1641
      out.println("Error: problem reading multipart data.");
1642
      out.println("</error>");
1643
    }
1644

    
1645
    // Get the session information
1646
    String username = null;
1647
    String password = null;
1648
    String[] groupnames = null;
1649
    String sess_id = null;
1650

    
1651
    // be aware of session expiration on every request  
1652
    HttpSession sess = request.getSession(true);
1653
    if (sess.isNew()) {
1654
      // session expired or has not been stored b/w user requests
1655
      username = "public";
1656
      sess.setAttribute("username", username);
1657
    } else {
1658
      username = (String)sess.getAttribute("username");
1659
      password = (String)sess.getAttribute("password");
1660
      groupnames = (String[])sess.getAttribute("groupnames");
1661
      try {
1662
        sess_id = (String)sess.getId();
1663
      } catch(IllegalStateException ise) {
1664
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1665
                           "happen: the session should be valid: " + 
1666
                           ise.getMessage());
1667
      }
1668
    }  
1669

    
1670
    if ( action.equals("upload")) {
1671
      if (username != null &&  !username.equals("public")) {
1672
        handleUploadAction(request, response, params, fileList, 
1673
                           username, groupnames);
1674
      } else {
1675
        try {
1676
          out = response.getWriter();
1677
        } catch (IOException ioe2) {
1678
          util.debugMessage("Fatal Error: couldn't get response "+
1679
                                                              "output stream.");
1680
        }
1681
        out.println("<?xml version=\"1.0\"?>");
1682
        out.println("<error>");
1683
        out.println("Permission denied for " + action);
1684
        out.println("</error>");
1685
      }
1686
    } else {
1687
      try {
1688
        out = response.getWriter();
1689
      } catch (IOException ioe2) {
1690
        System.err.println("Fatal Error: couldn't get response output stream.");
1691
      }
1692
      out.println("<?xml version=\"1.0\"?>");
1693
      out.println("<error>");
1694
      out.println("Error: action not registered.  Please report this error.");
1695
      out.println("</error>");
1696
    }
1697
    out.close();
1698
  }
1699

    
1700
  /** 
1701
   * Handle the upload action by saving the attached file to disk and 
1702
   * registering it in the Metacat db
1703
   */
1704
  private void handleUploadAction(HttpServletRequest request,
1705
                                  HttpServletResponse response, 
1706
                                  Hashtable params, Hashtable fileList, 
1707
                                  String username, String[] groupnames)
1708
  {
1709
    PrintWriter out = null;
1710
    //Connection conn = null;
1711
    String action = null;
1712
    String docid = null;
1713
  
1714
    response.setContentType("text/xml");
1715
    try 
1716
    {
1717
      out = response.getWriter();
1718
    } 
1719
    catch (IOException ioe2) 
1720
    {
1721
      System.err.println("Fatal Error: couldn't get response output stream.");
1722
    }
1723

    
1724
    if (params.containsKey("docid")) 
1725
    {
1726
      docid = (String)params.get("docid");
1727
    }
1728

    
1729
    // Make sure we have a docid and datafile
1730
    if (docid != null && fileList.containsKey("datafile")) {
1731

    
1732
      // Get a reference to the file part of the form
1733
      FilePart filePart = (FilePart)fileList.get("datafile");
1734
      String fileName = filePart.getFileName();
1735
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
1736

    
1737
      // Check if the right file existed in the uploaded data
1738
      if (fileName != null) {
1739
  
1740
        try 
1741
        {
1742
           //If document get lock data file grant
1743
           if (DocumentImpl.getDataFileLockGrant(docid))
1744
           {
1745
              // register the file in the database (which generates an exception
1746
              //if the docid is not acceptable or other untoward things happen
1747
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
1748
    
1749
              // Save the data file to disk using "docid" as the name
1750
              dataDirectory.mkdirs();
1751
              File newFile = new File(dataDirectory, docid);
1752
              long size = filePart.writeTo(newFile);
1753
              if ((util.getOption("replicationsenddata")).equals("on"))
1754
              {
1755
                // force replcation data file if metacat was configured
1756
                if (ReplicationHandler.getServerLocation(docid)==1)
1757
                {//local host document
1758
                  //conn=util.getConnection();
1759
                  ForceReplicationHandler frh = new ForceReplicationHandler
1760
             (docid, "insert", false, ReplicationHandler.buildServerList());
1761
                  //conn.close();
1762
                }//if
1763
                else
1764
                {
1765
                  //if it is super hub, replication to server list
1766
                  if ((util.getOption("hub")).equals("super"))
1767
                  {
1768
                    ForceReplicationHandler frh = new ForceReplicationHandler
1769
                    (docid,true, ReplicationHandler.buildServerList());
1770
                    //conn.close();
1771
                  }//if
1772
                  else
1773
                  {
1774
                    //only replicate to home host of the document
1775
                    String id=util.getDocIdFromString(docid);
1776
                    ForceReplicationHandler frh = new ForceReplicationHandler
1777
                    (docid, true, ReplicationHandler.getHomeServer(id));
1778
                  }//else
1779
                }//else
1780
              }//if
1781
              // set content type and other response header fields first
1782
              out.println("<?xml version=\"1.0\"?>");
1783
              out.println("<success>");
1784
              out.println("<docid>" + docid + "</docid>"); 
1785
              out.println("<size>" + size + "</size>"); 
1786
              out.println("</success>");
1787
          }//if
1788
    
1789
        } //try
1790
        catch (Exception e) 
1791
        {
1792
          out.println("<?xml version=\"1.0\"?>");
1793
          out.println("<error>");
1794
          out.println(e.getMessage()); 
1795
          out.println("</error>");
1796
        }
1797
       
1798
      }
1799
      else 
1800
      {
1801
        // the field did not contain a file
1802
        out.println("<?xml version=\"1.0\"?>");
1803
        out.println("<error>");
1804
        out.println("The uploaded data did not contain a valid file."); 
1805
        out.println("</error>");
1806
      }
1807
    } 
1808
    else 
1809
    {
1810
      // Error bcse docid missing or file missing
1811
      out.println("<?xml version=\"1.0\"?>");
1812
      out.println("<error>");
1813
      out.println("The uploaded data did not contain a valid docid " +
1814
                  "or valid file."); 
1815
      out.println("</error>");
1816
    }
1817
  }
1818
}
(32-32/43)