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

    
436
    AuthSession sess = null;
437
    String un = ((String[])params.get("username"))[0];
438
    String pw = ((String[])params.get("password"))[0];
439
    String action = ((String[])params.get("action"))[0];
440
    String qformat = ((String[])params.get("qformat"))[0];
441
    
442
    try {
443
      sess = new AuthSession();
444
    } catch (Exception e) {
445
      System.out.println("error in MetacatServlet.handleLoginAction: " +
446
                          e.getMessage());
447
      out.println(e.getMessage());
448
      return;
449
    }
450
    boolean isValid = sess.authenticate(request, un, pw);
451
    // format and transform the output
452
    if (qformat.equals("xml")) {
453
      response.setContentType("text/xml");
454
      out.println(sess.getMessage()); 
455
    } else {
456
     
457
      try {
458
        
459
        DBTransform trans = new DBTransform();
460
        response.setContentType("text/html");
461
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
462
                                   "-//W3C//HTML//EN", qformat, out);
463
         
464
      } catch(Exception e) {
465
        
466
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
467
                                +e.getMessage(), 30);
468
      } 
469
      
470
    // any output is returned  
471
    }
472
  }    
473

    
474
  /** 
475
   * Handle the logout request. Close the connection.
476
   */
477
  private void handleLogoutAction(PrintWriter out, Hashtable params, 
478
               HttpServletRequest request, HttpServletResponse response) {
479

    
480
    String qformat = ((String[])params.get("qformat"))[0];
481

    
482
    // close the connection
483
    HttpSession sess = request.getSession(false);
484
    if (sess != null) { sess.invalidate();  }    
485

    
486
    // produce output
487
    StringBuffer output = new StringBuffer();
488
    output.append("<?xml version=\"1.0\"?>");
489
    output.append("<logout>");
490
    output.append("User logged out");
491
    output.append("</logout>");
492

    
493
    //format and transform the output
494
    if (qformat.equals("xml")) {
495
      response.setContentType("text/xml");
496
      out.println(output.toString()); 
497
    } else {
498
      
499
      try {
500
       
501
        DBTransform trans = new DBTransform();
502
        response.setContentType("text/html");
503
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN", 
504
                                   "-//W3C//HTML//EN", qformat, out);
505
         
506
      } catch(Exception e) {
507
        
508
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
509
                                  +e.getMessage(), 30);
510
      } 
511
    }
512
  }
513
  // END OF LOGIN & LOGOUT SECTION
514
  
515
  // SQUERY & QUERY SECTION
516
  /**      
517
   * Retreive the squery xml, execute it and display it
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
   * @param conn the database connection 
524
   */
525
  protected void handleSQuery(PrintWriter out, Hashtable params, 
526
                 HttpServletResponse response, String user, String[] groups)
527
  { 
528
    String xmlquery = ((String[])params.get("query"))[0];
529
    String qformat = ((String[])params.get("qformat"))[0];
530
    String resultdoc = null;
531
    
532
    Hashtable doclist = runQuery(xmlquery, user, groups);
533

    
534
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
535
    
536
    //format and transform the results                                        
537
    if(qformat.equals("xml")) {
538
      response.setContentType("text/xml");
539
      out.println(resultdoc);
540
    } else {
541
      transformResultset(resultdoc, response, out, qformat);
542
    }
543
  }
544
  
545
   /**
546
    * Create the xml query, execute it and display the results.
547
    *
548
    * @param out the output stream to the client
549
    * @param params the Hashtable of parameters that should be included
550
    * in the squery.
551
    * @param response the response object linked to the client
552
    */ 
553
  protected void handleQuery(PrintWriter out, Hashtable params, 
554
                 HttpServletResponse response, String user, String[] groups)
555
  {
556
    //create the query and run it
557
    String xmlquery = DBQuery.createSQuery(params);
558
    Hashtable doclist = runQuery(xmlquery, user, groups);
559
    String qformat = ((String[])params.get("qformat"))[0];
560
    String resultdoc = null;
561
    
562
    resultdoc = createResultDocument(doclist, transformQuery(params));
563

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

    
682
    if(doclist != null)
683
    {
684
      Enumeration doclistkeys = doclist.keys(); 
685
      while (doclistkeys.hasMoreElements()) 
686
      {
687
        docid = (String)doclistkeys.nextElement();
688
        document = (String)doclist.get(docid);
689
        resultset.append("  <document>" + document + "</document>");
690
      }
691
    }
692

    
693
    resultset.append("</resultset>");
694
    return resultset.toString();
695
  }
696
  // END OF SQUERY & QUERY SECTION
697
  
698
 //Exoport section
699
 /**
700
   * Handle the "export" request of data package from Metacat in zip format
701
   * @param params the Hashtable of HTTP request parameters
702
   * @param response the HTTP response object linked to the client
703
   * @param user the username sent the request
704
   * @param groups the user's groupnames
705
   */
706
  private void handleExportAction(Hashtable params, 
707
    HttpServletResponse response, String user, String[] groups, String passWord)
708
  {
709
    // Output stream
710
    ServletOutputStream out = null;
711
    // Zip output stream
712
    ZipOutputStream zOut = null;
713
    DocumentImpl docImpls=null;
714
    DBQuery queryObj=null;
715
  
716
    String[] docs = new String[10];
717
    String docId = "";
718

    
719
    try
720
    {
721
      // read the params
722
      if (params.containsKey("docid")) 
723
      {
724
        docs = (String[])params.get("docid");
725
      }//if
726
      // Create a DBuery to handle export
727
      queryObj = new DBQuery(saxparser);
728
      // Get the docid
729
      docId=docs[0];
730
      // Make sure the client specify docid
731
      if (docId == null || docId.equals(""))
732
      {
733
        response.setContentType("text/xml"); //MIME type
734
        // Get a printwriter
735
        PrintWriter pw = response.getWriter();
736
        // Send back message
737
        pw.println("<?xml version=\"1.0\"?>");
738
        pw.println("<error>");
739
        pw.println("You didn't specify requested docid");
740
        pw.println("</error>");
741
        // Close printwriter 
742
        pw.close();
743
        return;
744
      }//if
745
      // Get output stream
746
      out = response.getOutputStream();
747
      response.setContentType("application/zip"); //MIME type
748
      zOut = new ZipOutputStream(out);
749
      zOut =queryObj.getZippedPackage(docId, out, user, groups, passWord);
750
      zOut.finish(); //terminate the zip file
751
      zOut.close();  //close the zip stream
752
      
753
    }//try 
754
    catch (Exception e)
755
    {
756
      try
757
      {
758
        response.setContentType("text/xml"); //MIME type
759
        // Send error message back
760
        if (out != null)
761
        {
762
            PrintWriter pw = new PrintWriter(out);
763
            pw.println("<?xml version=\"1.0\"?>");
764
            pw.println("<error>");
765
            pw.println(e.getMessage());
766
            pw.println("</error>");
767
            // Close printwriter
768
            pw.close();
769
            // Close output stream
770
            out.close();
771
        }//if
772
        // Close zip output stream 
773
        if ( zOut != null )
774
        {
775
          zOut.close();
776
        }//if
777
      }//try
778
      catch (IOException ioe)
779
      {
780
        MetaCatUtil.debugMessage("Problem with the servlet output " +
781
                           "in MetacatServlet.handleExportAction: " +
782
                           ioe.getMessage(), 30);
783
      }//catch
784

    
785
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
786
                         e.getMessage(), 30);
787
      e.printStackTrace(System.out);
788
      
789
    }//catch
790
 
791
  }//handleExportAction
792
  
793
  // READ SECTION
794
  /** 
795
   * Handle the "read" request of metadata/data files from Metacat
796
   * or any files from Internet;
797
   * transformed metadata XML document into HTML presentation if requested;
798
   * zip files when more than one were requested.
799
   *
800
   * @param params the Hashtable of HTTP request parameters
801
   * @param response the HTTP response object linked to the client
802
   * @param user the username sent the request
803
   * @param groups the user's groupnames
804
   */
805
  private void handleReadAction(Hashtable params, HttpServletResponse response,
806
                                String user, String passWord, String[] groups) 
807
  {
808
    ServletOutputStream out = null;
809
    ZipOutputStream zout = null;
810
    PrintWriter pw = null;
811
    boolean zip = false;
812
    
813
    try {
814
      String[] docs = new String[0];
815
      String docid = "";
816
      String qformat = "";
817
      String abstrpath = null;
818
      
819
      // read the params
820
      if (params.containsKey("docid")) {
821
        docs = (String[])params.get("docid");
822
      }
823
      if (params.containsKey("qformat")) {
824
        qformat = ((String[])params.get("qformat"))[0];
825
      }
826
      if (params.containsKey("abstractpath")) {
827
        abstrpath = ((String[])params.get("abstractpath"))[0];
828
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
829
          viewAbstract(response, abstrpath, docs[0]);
830
          return;
831
        }
832
      }
833
      if ( (docs.length > 1) || qformat.equals("zip") ) {
834
        zip = true;
835
        out = response.getOutputStream();
836
        response.setContentType("application/zip"); //MIME type
837
        zout = new ZipOutputStream(out);
838
      }
839
      // go through the list of docs to read
840
      for (int i=0; i < docs.length; i++ ) {
841
        try {
842

    
843
          URL murl = new URL(docs[i]);
844
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
845
          // case docid="http://.../?docid=aaa" 
846
          // or docid="metacat://.../?docid=bbb"
847
          if (murlQueryStr.containsKey("docid")) {
848
            // get only docid, eliminate the rest
849
            docid = (String)murlQueryStr.get("docid");
850
            if ( zip ) {
851
              addDocToZip(docid, zout, user, groups);
852
            } else {
853
              readFromMetacat(response, docid, qformat, abstrpath,
854
                              user, groups, zip, zout);
855
            }
856

    
857
          // case docid="http://.../filename"
858
          } else {
859
            docid = docs[i];
860
            if ( zip ) {
861
              addDocToZip(docid, zout, user, groups);
862
            } else {
863
              readFromURLConnection(response, docid);
864
            }
865
          }
866

    
867
        // case docid="ccc"
868
        } catch (MalformedURLException mue) {
869
          docid = docs[i];
870
          if ( zip ) {
871
            addDocToZip(docid, zout, user, groups);
872
          } else {
873
            readFromMetacat(response, docid, qformat, abstrpath,
874
                            user, groups, zip, zout);
875
          }
876
        }
877
        
878
      } /* end for */
879
      
880
      if ( zip ) {
881
        zout.finish(); //terminate the zip file
882
        zout.close();  //close the zip stream
883
      }
884
      
885
  
886
    }
887
    // To handle doc not found exception
888
    catch (McdbDocNotFoundException notFoundE)
889
    {
890
      // the docid which didn't be found
891
      String notFoundDocId = notFoundE.getUnfoundDocId();
892
      String notFoundRevision = notFoundE.getUnfoundRevision();
893
      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
894
      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
895
      try
896
      {
897
        // read docid from remote server
898
        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
899
                                              user, passWord, out, zip, zout);
900
        // Close zout outputstream
901
        if ( zout != null)
902
        {
903
          zout.close();
904
        }
905
        // close output stream
906
        if (out != null)
907
        {
908
          out.close();
909
        }
910
        
911
      }//try
912
      catch ( Exception exc)
913
      {
914
        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
915
                                      exc.getMessage(), 30);
916
        try
917
        {
918
          if (out != null) 
919
          {
920
            response.setContentType("text/xml");
921
            // Send back error message by printWriter
922
            pw = new PrintWriter(out);
923
            pw.println("<?xml version=\"1.0\"?>");
924
            pw.println("<error>");
925
            pw.println(notFoundE.getMessage());
926
            pw.println("</error>");
927
            pw.close();
928
            out.close();
929
            
930
          }
931
          else
932
          {
933
           response.setContentType("text/xml"); //MIME type
934
           // Send back error message if out = null
935
           if (pw == null)
936
           {
937
             // If pw is null, open the respnose
938
            pw = response.getWriter();
939
           }
940
           pw.println("<?xml version=\"1.0\"?>");
941
           pw.println("<error>");
942
           pw.println(notFoundE.getMessage());
943
           pw.println("</error>");
944
           pw.close();
945
        }
946
        // close zout
947
        if ( zout != null ) 
948
        { 
949
          zout.close(); 
950
        }
951
        }//try
952
        catch (IOException ie)
953
        {
954
          MetaCatUtil.debugMessage("Problem with the servlet output " +
955
                           "in MetacatServlet.handleReadAction: " +
956
                           ie.getMessage(), 30);
957
        }//cathch
958
      }//catch
959
    }// catch McdbDocNotFoundException
960
    catch (Exception e) 
961
    {
962
      try {
963
       
964
        if (out != null) {
965
            response.setContentType("text/xml"); //MIME type
966
            pw = new PrintWriter(out);
967
            pw.println("<?xml version=\"1.0\"?>");
968
            pw.println("<error>");
969
            pw.println(e.getMessage());
970
            pw.println("</error>");
971
            pw.close();
972
            out.close();
973
        }
974
        else
975
        {
976
           response.setContentType("text/xml"); //MIME type
977
           // Send back error message if out = null
978
           if ( pw == null)
979
           {
980
            pw = response.getWriter();
981
           }
982
           pw.println("<?xml version=\"1.0\"?>");
983
           pw.println("<error>");
984
           pw.println(e.getMessage());
985
           pw.println("</error>");
986
           pw.close();
987
          
988
        }
989
        // Close zip output stream
990
        if ( zout != null ) { zout.close(); }
991
        
992
      } catch (IOException ioe) {
993
        MetaCatUtil.debugMessage("Problem with the servlet output " +
994
                           "in MetacatServlet.handleReadAction: " +
995
                           ioe.getMessage(), 30);
996
        ioe.printStackTrace(System.out);
997
        
998
      }
999

    
1000
      System.out.println("Error in MetacatServlet.handleReadAction: " +
1001
                         e.getMessage());
1002
      e.printStackTrace(System.out);
1003
    }
1004
    
1005
  }
1006
  
1007
  // read metadata or data from Metacat
1008
  private void readFromMetacat(HttpServletResponse response, String docid,
1009
                               String qformat, String abstrpath, String user,
1010
                             String[] groups, boolean zip, ZipOutputStream zout)
1011
               throws ClassNotFoundException, IOException, SQLException, 
1012
                      McdbException, Exception
1013
  {
1014
   
1015
    try {
1016
     
1017
      
1018
      DocumentImpl doc = new DocumentImpl(docid);
1019
    
1020
      //check the permission for read
1021
      if (!doc.hasReadPermission(user, groups, docid))
1022
      {
1023
        Exception e = new Exception("User " + user + " does not have permission"
1024
                       +" to read the document with the docid " + docid);
1025
    
1026
        throw e;
1027
      }
1028
     
1029
      if ( doc.getRootNodeID() == 0 ) {
1030
        // this is data file
1031
        String filepath = util.getOption("datafilepath");
1032
        if(!filepath.endsWith("/")) {
1033
          filepath += "/";
1034
        }
1035
        String filename = filepath + docid;
1036
        FileInputStream fin = null;
1037
        fin = new FileInputStream(filename);
1038
        
1039
        //MIME type
1040
        String contentType = getServletContext().getMimeType(filename);
1041
        if (contentType == null) {
1042
          if (filename.endsWith(".xml")) {
1043
            contentType="text/xml";
1044
          } else if (filename.endsWith(".css")) {
1045
            contentType="text/css";
1046
          } else if (filename.endsWith(".dtd")) {
1047
            contentType="text/plain";
1048
          } else if (filename.endsWith(".xsd")) {
1049
            contentType="text/xml";
1050
          } else if (filename.endsWith("/")) {
1051
            contentType="text/html";
1052
          } else {
1053
            File f = new File(filename);
1054
            if ( f.isDirectory() ) {
1055
              contentType="text/html";
1056
            } else {
1057
              contentType="application/octet-stream";
1058
            }
1059
          }
1060
        }
1061
        response.setContentType(contentType);
1062
        // if we decide to use "application/octet-stream" for all data returns
1063
        // response.setContentType("application/octet-stream");
1064
       
1065
        try {
1066
          
1067
          ServletOutputStream out = response.getOutputStream(); 
1068
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1069
          int b = fin.read(buf);
1070
          while (b != -1) {
1071
            out.write(buf, 0, b);
1072
            b = fin.read(buf);
1073
          }
1074
        } finally {
1075
          if (fin != null) fin.close();
1076
        }
1077

    
1078
      } else {
1079
        // this is metadata doc
1080
        if ( qformat.equals("xml") ) { 
1081
          
1082
          // set content type first
1083
          response.setContentType("text/xml");   //MIME type
1084
          PrintWriter out = response.getWriter();
1085
          doc.toXml(out);
1086
        } else {
1087
          response.setContentType("text/html");  //MIME type
1088
          PrintWriter out = response.getWriter();
1089
    
1090
          // Look up the document type
1091
          String doctype = doc.getDoctype();
1092
          // Transform the document to the new doctype
1093
          DBTransform dbt = new DBTransform();
1094
          dbt.transformXMLDocument(doc.toString(),
1095
                                   doctype,"-//W3C//HTML//EN", qformat, out);
1096
        }
1097
      
1098
      }
1099
    }
1100
    catch (Exception except) 
1101
    {
1102
      throw except;
1103
    
1104
    }
1105
    
1106
  }
1107
  
1108
  // read data from URLConnection
1109
  private void readFromURLConnection(HttpServletResponse response, String docid)
1110
               throws IOException, MalformedURLException
1111
  {
1112
    ServletOutputStream out = response.getOutputStream(); 
1113
    String contentType = getServletContext().getMimeType(docid); //MIME type
1114
    if (contentType == null) {
1115
      if (docid.endsWith(".xml")) {
1116
        contentType="text/xml";
1117
      } else if (docid.endsWith(".css")) {
1118
        contentType="text/css";
1119
      } else if (docid.endsWith(".dtd")) {
1120
        contentType="text/plain";
1121
      } else if (docid.endsWith(".xsd")) {
1122
        contentType="text/xml";
1123
      } else if (docid.endsWith("/")) {
1124
        contentType="text/html";
1125
      } else {
1126
        File f = new File(docid);
1127
        if ( f.isDirectory() ) {
1128
          contentType="text/html";
1129
        } else {
1130
          contentType="application/octet-stream";
1131
        }
1132
      }
1133
    }
1134
    response.setContentType(contentType);
1135
    // if we decide to use "application/octet-stream" for all data returns
1136
    // response.setContentType("application/octet-stream");
1137

    
1138
    // this is http url
1139
    URL url = new URL(docid);
1140
    BufferedInputStream bis = null;
1141
    try {
1142
      bis = new BufferedInputStream(url.openStream());
1143
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1144
      int b = bis.read(buf);
1145
      while (b != -1) {
1146
        out.write(buf, 0, b);
1147
        b = bis.read(buf);
1148
      }
1149
    } finally {
1150
      if (bis != null) bis.close();
1151
    }
1152
    
1153
  }
1154
  
1155
  // read file/doc and write to ZipOutputStream
1156
  private void addDocToZip(String docid, ZipOutputStream zout, 
1157
                              String user, String[] groups)
1158
               throws ClassNotFoundException, IOException, SQLException, 
1159
                      McdbException, Exception
1160
  {
1161
    byte[] bytestring = null;
1162
    ZipEntry zentry = null;
1163

    
1164
    try {
1165
      URL url = new URL(docid);
1166

    
1167
      // this http url; read from URLConnection; add to zip
1168
      zentry = new ZipEntry(docid);
1169
      zout.putNextEntry(zentry);
1170
      BufferedInputStream bis = null;
1171
      try {
1172
        bis = new BufferedInputStream(url.openStream());
1173
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1174
        int b = bis.read(buf);
1175
        while(b != -1) {
1176
          zout.write(buf, 0, b);
1177
          b = bis.read(buf);
1178
        }
1179
      } finally {
1180
        if (bis != null) bis.close();
1181
      }
1182
      zout.closeEntry();
1183

    
1184
    } catch (MalformedURLException mue) {
1185
      
1186
      // this is metacat doc (data file or metadata doc)
1187
  
1188
      try {
1189
       
1190
        DocumentImpl doc = new DocumentImpl(docid);
1191
        
1192
        //check the permission for read
1193
        if (!doc.hasReadPermission(user, groups, docid))
1194
        {
1195
          Exception e = new Exception("User " + user + " does not have "
1196
                    +"permission to read the document with the docid " + docid);
1197
        
1198
          throw e;
1199
        } 
1200
        
1201
        if ( doc.getRootNodeID() == 0 ) {
1202
          // this is data file; add file to zip
1203
          String filepath = util.getOption("datafilepath");
1204
          if(!filepath.endsWith("/")) {
1205
            filepath += "/";
1206
          }
1207
          String filename = filepath + docid;
1208
          FileInputStream fin = null;
1209
          fin = new FileInputStream(filename);
1210
          try {
1211
            
1212
            zentry = new ZipEntry(docid);
1213
            zout.putNextEntry(zentry);
1214
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1215
            int b = fin.read(buf);
1216
            while (b != -1) {
1217
              zout.write(buf, 0, b);
1218
              b = fin.read(buf);
1219
            }
1220
          } finally {
1221
            if (fin != null) fin.close();
1222
          }
1223
          zout.closeEntry();
1224

    
1225
        } else {
1226
          // this is metadata doc; add doc to zip
1227
          bytestring = doc.toString().getBytes();
1228
          zentry = new ZipEntry(docid + ".xml");
1229
          zentry.setSize(bytestring.length);
1230
          zout.putNextEntry(zentry);
1231
          zout.write(bytestring, 0, bytestring.length);
1232
          zout.closeEntry();
1233
        }
1234
      } catch (Exception except) {
1235
        throw except;
1236
       
1237
      }
1238
      
1239
    }
1240
      
1241
  }
1242
  
1243
  // view abstract within document
1244
  private void viewAbstract(HttpServletResponse response,
1245
                            String abstractpath, String docid)
1246
               throws ClassNotFoundException, IOException, SQLException,
1247
                      McdbException, Exception
1248
  {
1249
  
1250
    PrintWriter out =null;
1251
    try {
1252
   
1253
      response.setContentType("text/html");  //MIME type
1254
      out = response.getWriter();
1255
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1256
      out.println("<html><head><title>Abstract</title></head>");
1257
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1258
      for (int i=0; i<abstracts.length; i++) {
1259
        out.println("<p>" + (String)abstracts[i] + "</p>");
1260
      }
1261
      out.println("</body></html>");
1262

    
1263
    } catch (Exception e) {
1264
       out.println("<?xml version=\"1.0\"?>");
1265
       out.println("<error>");
1266
       out.println(e.getMessage());
1267
       out.println("</error>");
1268
    
1269
   
1270
    }
1271
  }
1272
  /**
1273
   * If metacat couldn't find a data file or document locally, it will read this
1274
   * docid from its home server. This is for the replication feature
1275
   */
1276
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid, 
1277
                     String rev, String user, String password, 
1278
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1279
                        throws Exception
1280
 {
1281
   // Create a object of RemoteDocument, "" is for zipEntryPath
1282
   RemoteDocument remoteDoc = 
1283
                        new RemoteDocument (docid, rev,user, password, "");
1284
   // If it is zip format
1285
   if (zip)
1286
   {
1287
     remoteDoc.readDocumentFromRemoteServerByZip(zout);
1288
   }//if 
1289
   else
1290
   {
1291
     if (out == null)
1292
     {
1293
       out = response.getOutputStream();
1294
     }//if
1295
     response.setContentType("application/octet-stream");
1296
     remoteDoc.readDocumentFromRemoteServer(out);
1297
   }//else (not zip)                   
1298
 }//readFromRemoteMetaCat
1299
  
1300
  // END OF READ SECTION
1301
    
1302
  // INSERT/UPDATE SECTION
1303
  /** 
1304
   * Handle the database putdocument request and write an XML document 
1305
   * to the database connection
1306
   */
1307
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params, 
1308
               HttpServletResponse response, String user, String[] groups) {
1309

    
1310
    DBConnection dbConn = null;
1311
    int serialNumber = -1;
1312

    
1313
    try {
1314
      // Get the document indicated
1315
      String[] doctext = (String[])params.get("doctext");
1316

    
1317
      String pub = null;
1318
      if (params.containsKey("public")) {
1319
        pub = ((String[])params.get("public"))[0];
1320
      }
1321

    
1322
      StringReader dtd = null;
1323
      if (params.containsKey("dtdtext")) {
1324
        String[] dtdtext = (String[])params.get("dtdtext");
1325
        try {
1326
          if ( !dtdtext[0].equals("") ) {
1327
            dtd = new StringReader(dtdtext[0]);
1328
          }
1329
        } catch (NullPointerException npe) {}
1330
      }
1331
      
1332
      StringReader xml = null;
1333
      boolean validate = false;
1334
      try {
1335
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1336
        // in order to decide whether to use validation parser
1337
        validate = validateXML(doctext[0]);
1338
        xml = new StringReader(doctext[0]);
1339

    
1340
        String[] action = (String[])params.get("action");
1341
        String[] docid = (String[])params.get("docid");
1342
        String newdocid = null;
1343

    
1344
        String doAction = null;
1345
        if (action[0].equals("insert")) {
1346
          doAction = "INSERT";
1347
        } else if (action[0].equals("update")) {
1348
          doAction = "UPDATE";
1349
        }
1350
        
1351
        try 
1352
        {
1353
          // get a connection from the pool
1354
          dbConn=DBConnectionPool.
1355
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1356
          serialNumber=dbConn.getCheckOutSerialNumber();
1357
          
1358
          
1359
          // write the document to the database
1360
          try 
1361
          {
1362
            String accNumber = docid[0];
1363
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1364
            if (accNumber.equals("")) 
1365
            {
1366
              accNumber = null;
1367
            }//if
1368
            newdocid = DocumentImpl.write(dbConn, xml, pub, dtd, doAction,
1369
                                          accNumber, user, groups, validate);
1370
            
1371
          }//try 
1372
          catch (NullPointerException npe) 
1373
          {
1374
            newdocid = DocumentImpl.write(dbConn, xml, pub, dtd, doAction,
1375
                                          null, user, groups, validate);
1376
          }//catch
1377
        }//try 
1378
        finally 
1379
        {
1380
          // Return db connection
1381
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1382
        }    
1383

    
1384
        // set content type and other response header fields first
1385
        response.setContentType("text/xml");
1386
        out.println("<?xml version=\"1.0\"?>");
1387
        out.println("<success>");
1388
        out.println("<docid>" + newdocid + "</docid>"); 
1389
        out.println("</success>");
1390

    
1391
      } catch (NullPointerException npe) {
1392
        response.setContentType("text/xml");
1393
        out.println("<?xml version=\"1.0\"?>");
1394
        out.println("<error>");
1395
        out.println(npe.getMessage()); 
1396
        out.println("</error>");
1397
      }
1398
    } catch (Exception e) {
1399
      response.setContentType("text/xml");
1400
      out.println("<?xml version=\"1.0\"?>");
1401
      out.println("<error>");
1402
      out.println(e.getMessage()); 
1403
      if (e instanceof SAXException) {
1404
        Exception e2 = ((SAXException)e).getException();
1405
        out.println("<error>");
1406
        try
1407
        {
1408
          out.println(e2.getMessage());
1409
        }
1410
        catch(NullPointerException npe)
1411
        {
1412
          out.println(e.getMessage());
1413
        }
1414
        out.println("</error>");
1415
      }
1416
      //e.printStackTrace(out);
1417
      out.println("</error>");
1418
    }
1419
  }
1420

    
1421
  /** 
1422
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > 
1423
   * in order to decide whether to use validation parser
1424
   */
1425
  private static boolean validateXML(String xmltext) throws IOException {
1426
    
1427
    StringReader xmlreader = new StringReader(xmltext);
1428
    StringBuffer cbuff = new StringBuffer();
1429
    java.util.Stack st = new java.util.Stack();
1430
    boolean validate = false;
1431
    int c;
1432
    int inx;
1433
    
1434
    // read from the stream until find the keywords
1435
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1436
      cbuff.append((char)c);
1437

    
1438
      // "<!DOCTYPE" keyword is found; put it in the stack
1439
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1440
        cbuff = new StringBuffer();
1441
        st.push("<!DOCTYPE");
1442
      }
1443
      // "PUBLIC" keyword is found; put it in the stack
1444
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1445
        cbuff = new StringBuffer();
1446
        st.push("PUBLIC");
1447
      }
1448
      // "SYSTEM" keyword is found; put it in the stack
1449
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1450
        cbuff = new StringBuffer();
1451
        st.push("SYSTEM");
1452
      }
1453
      // ">" character is found; put it in the stack
1454
      // ">" is found twice: fisrt from <?xml ...?> 
1455
      // and second from <!DOCTYPE ... >
1456
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1457
        cbuff = new StringBuffer();
1458
        st.push(">");
1459
      }
1460
    }
1461

    
1462
    // close the stream
1463
    xmlreader.close();
1464

    
1465
    // check the stack whether it contains the keywords:
1466
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1467
    if ( st.size() == 4 ) {
1468
      if ( ((String)st.pop()).equals(">") &&
1469
           ( ((String)st.peek()).equals("PUBLIC") |
1470
             ((String)st.pop()).equals("SYSTEM") ) &&
1471
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1472
        validate = true;
1473
      }
1474
    }
1475

    
1476
System.out.println("Validation is " + validate);
1477
    return validate;
1478
  }
1479
  // END OF INSERT/UPDATE SECTION
1480

    
1481
  // DELETE SECTION
1482
  /** 
1483
   * Handle the database delete request and delete an XML document 
1484
   * from the database connection
1485
   */
1486
  private void handleDeleteAction(PrintWriter out, Hashtable params, 
1487
               HttpServletResponse response, String user, String[] groups) {
1488

    
1489
    String[] docid = (String[])params.get("docid");
1490
  
1491
    // delete the document from the database
1492
    try {
1493
 
1494
                                      // NOTE -- NEED TO TEST HERE
1495
                                      // FOR EXISTENCE OF DOCID PARAM
1496
                                      // BEFORE ACCESSING ARRAY
1497
      try { 
1498
        DocumentImpl.delete(docid[0], user, groups);
1499
        response.setContentType("text/xml");
1500
        out.println("<?xml version=\"1.0\"?>");
1501
        out.println("<success>");
1502
        out.println("Document deleted."); 
1503
        out.println("</success>");
1504
      } catch (AccessionNumberException ane) {
1505
        response.setContentType("text/xml");
1506
        out.println("<?xml version=\"1.0\"?>");
1507
        out.println("<error>");
1508
        out.println("Error deleting document!!!");
1509
        out.println(ane.getMessage()); 
1510
        out.println("</error>");
1511
      }
1512
    } catch (Exception e) {
1513
      response.setContentType("text/xml");
1514
      out.println("<?xml version=\"1.0\"?>");
1515
      out.println("<error>");
1516
      out.println(e.getMessage()); 
1517
      out.println("</error>");
1518
    } 
1519
  }
1520
  // END OF DELETE SECTION
1521
  
1522
  // VALIDATE SECTION
1523
  /** 
1524
   * Handle the validation request and return the results to the requestor
1525
   */
1526
  private void handleValidateAction(PrintWriter out, Hashtable params, 
1527
               HttpServletResponse response) {
1528

    
1529
    // Get the document indicated
1530
    String valtext = null;
1531
    DBConnection dbConn = null;
1532
    int serialNumber = -1;
1533
    
1534
    try {
1535
      valtext = ((String[])params.get("valtext"))[0];
1536
    } catch (Exception nullpe) {
1537

    
1538
     
1539
      String docid = null;
1540
      try {
1541
        // Find the document id number
1542
        docid = ((String[])params.get("docid"))[0]; 
1543

    
1544
      
1545
        // Get the document indicated from the db
1546
        DocumentImpl xmldoc = new DocumentImpl(docid);
1547
        valtext = xmldoc.toString();
1548

    
1549
      } catch (NullPointerException npe) {
1550
        response.setContentType("text/xml");
1551
        out.println("<error>Error getting document ID: " + docid + "</error>");
1552
        //if ( conn != null ) { util.returnConnection(conn); }
1553
        return;
1554
      } catch (Exception e) {
1555
        response.setContentType("text/html");
1556
        out.println(e.getMessage()); 
1557
      } 
1558
    }
1559

    
1560
  
1561
    try {
1562
      // get a connection from the pool
1563
      dbConn=DBConnectionPool.
1564
                  getDBConnection("MetaCatServlet.handleValidateAction");
1565
      serialNumber=dbConn.getCheckOutSerialNumber();
1566
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1567
      boolean valid = valobj.validateString(valtext);
1568

    
1569
      // set content type and other response header fields first
1570
      response.setContentType("text/xml");
1571
      out.println(valobj.returnErrors());
1572

    
1573
    } catch (NullPointerException npe2) {
1574
      // set content type and other response header fields first
1575
      response.setContentType("text/xml");
1576
      out.println("<error>Error validating document.</error>"); 
1577
    } catch (Exception e) {
1578
      response.setContentType("text/html");
1579
      out.println(e.getMessage()); 
1580
    } finally {
1581
      // Return db connection
1582
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1583
    }  
1584
  }
1585
  // END OF VALIDATE SECTION
1586
 
1587
  // OTHER ACTION HANDLERS
1588
  
1589
  /**
1590
   * Handle "getrevsionanddoctype" action
1591
   * Given a docid, return it's current revision and doctype from data base
1592
   * The output is String look like "rev;doctype"
1593
   */
1594
  private void handleGetRevisionAndDocTypeAction(PrintWriter out, 
1595
                                                              Hashtable params)
1596
  {
1597
    // To store doc parameter
1598
    String [] docs = new String[10];
1599
    // Store a single doc id
1600
    String givenDocId = null;
1601
    // Get docid from parameters
1602
    if (params.containsKey("docid")) 
1603
    {
1604
      docs = (String[])params.get("docid");
1605
    }
1606
    // Get first docid form string array
1607
    givenDocId = docs[0];
1608
   
1609
    try 
1610
    {
1611
      // Make sure there is a docid
1612
      if (givenDocId == null || givenDocId.equals(""))
1613
      {
1614
        throw new Exception("User didn't specify docid!");
1615
      }//if
1616
      
1617
      // Create a DBUtil object
1618
      DBUtil dbutil = new DBUtil();
1619
      // Get a rev and doctype
1620
      String revAndDocType = 
1621
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1622
      out.println(revAndDocType);
1623

    
1624
    }//try 
1625
    catch (Exception e) 
1626
    {
1627
      // Handle exception
1628
      out.println("<?xml version=\"1.0\"?>");
1629
      out.println("<error>");
1630
      out.println(e.getMessage());
1631
      out.println("</error>");
1632
    }//catch 
1633
    
1634
  }//handleGetRevisionAndDocTypeAction
1635
  
1636
  /** 
1637
   * Handle "getaccesscontrol" action.
1638
   * Read Access Control List from db connection in XML format
1639
   */
1640
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params, 
1641
                                       HttpServletResponse response, 
1642
                                       String username, String[] groupnames) {
1643

    
1644
    DBConnection dbConn = null;
1645
    int serialNumber = -1;
1646
    String docid = ((String[])params.get("docid"))[0];
1647
    
1648
    try {
1649

    
1650
        // get connection from the pool
1651
        dbConn=DBConnectionPool.
1652
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1653
        serialNumber=dbConn.getCheckOutSerialNumber();
1654
        AccessControlList aclobj = new AccessControlList(dbConn);
1655
        String acltext = aclobj.getACL(docid, username, groupnames);
1656
        out.println(acltext);
1657

    
1658
    } catch (Exception e) {
1659
      out.println("<?xml version=\"1.0\"?>");
1660
      out.println("<error>");
1661
      out.println(e.getMessage());
1662
      out.println("</error>");
1663
    } finally {
1664
      // Retrun db connection to pool
1665
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1666
    }  
1667
    
1668
  }
1669

    
1670
  /** 
1671
   * Handle the "getprincipals" action.
1672
   * Read all principals from authentication scheme in XML format
1673
   */
1674
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1675
                                         String password) {
1676

    
1677
   
1678
    try {
1679

    
1680
        
1681
        AuthSession auth = new AuthSession();
1682
        String principals = auth.getPrincipals(user, password);
1683
        out.println(principals);
1684

    
1685
    } catch (Exception e) {
1686
      out.println("<?xml version=\"1.0\"?>");
1687
      out.println("<error>");
1688
      out.println(e.getMessage());
1689
      out.println("</error>");
1690
    } 
1691
    
1692
  }
1693

    
1694
  /** 
1695
   * Handle "getdoctypes" action.
1696
   * Read all doctypes from db connection in XML format
1697
   */
1698
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params, 
1699
                                       HttpServletResponse response) {
1700

    
1701
   
1702
    try {
1703

    
1704
     
1705
        DBUtil dbutil = new DBUtil();
1706
        String doctypes = dbutil.readDoctypes();
1707
        out.println(doctypes);
1708

    
1709
    } catch (Exception e) {
1710
      out.println("<?xml version=\"1.0\"?>");
1711
      out.println("<error>");
1712
      out.println(e.getMessage());
1713
      out.println("</error>");
1714
    } 
1715
    
1716
  }
1717

    
1718
  /** 
1719
   * Handle the "getdtdschema" action.
1720
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1721
   */
1722
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1723
                                        HttpServletResponse response) {
1724

    
1725
   
1726
    String doctype = null;
1727
    String[] doctypeArr = (String[])params.get("doctype");
1728

    
1729
    // get only the first doctype specified in the list of doctypes
1730
    // it could be done for all doctypes in that list
1731
    if (doctypeArr != null) {
1732
        doctype = ((String[])params.get("doctype"))[0]; 
1733
    }
1734

    
1735
    try {
1736

    
1737
       
1738
        DBUtil dbutil = new DBUtil();
1739
        String dtdschema = dbutil.readDTDSchema(doctype);
1740
        out.println(dtdschema);
1741

    
1742
    } catch (Exception e) {
1743
      out.println("<?xml version=\"1.0\"?>");
1744
      out.println("<error>");
1745
      out.println(e.getMessage());
1746
      out.println("</error>");
1747
    } 
1748
    
1749
  }
1750

    
1751
  /** 
1752
   * Handle the "getdataguide" action.
1753
   * Read Data Guide for a given doctype from db connection in XML format
1754
   */
1755
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params, 
1756
                                        HttpServletResponse response) {
1757

    
1758
  
1759
    String doctype = null;
1760
    String[] doctypeArr = (String[])params.get("doctype");
1761

    
1762
    // get only the first doctype specified in the list of doctypes
1763
    // it could be done for all doctypes in that list
1764
    if (doctypeArr != null) {
1765
        doctype = ((String[])params.get("doctype"))[0]; 
1766
    }
1767

    
1768
    try {
1769

    
1770
  
1771
        DBUtil dbutil = new DBUtil();
1772
        String dataguide = dbutil.readDataGuide(doctype);
1773
        out.println(dataguide);
1774

    
1775
    } catch (Exception e) {
1776
      out.println("<?xml version=\"1.0\"?>");
1777
      out.println("<error>");
1778
      out.println(e.getMessage());
1779
      out.println("</error>");
1780
    }
1781
    
1782
  }
1783

    
1784
  /** 
1785
   * Handle the "getlastdocid" action.
1786
   * Get the latest docid with rev number from db connection in XML format
1787
   */
1788
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params, 
1789
                                        HttpServletResponse response) {
1790

    
1791

    
1792
    String scope = ((String[])params.get("scope"))[0];
1793
    if (scope == null) {
1794
        scope = ((String[])params.get("username"))[0];
1795
    }
1796

    
1797
    try {
1798

    
1799
       
1800
        DBUtil dbutil = new DBUtil();
1801
        String lastDocid = dbutil.getMaxDocid(scope);
1802
        out.println("<?xml version=\"1.0\"?>");
1803
        out.println("<lastDocid>");
1804
        out.println("  <scope>" + scope + "</scope>");
1805
        out.println("  <docid>" + lastDocid + "</docid>");
1806
        out.println("</lastDocid>");
1807

    
1808
    } catch (Exception e) {
1809
      out.println("<?xml version=\"1.0\"?>");
1810
      out.println("<error>");
1811
      out.println(e.getMessage());
1812
      out.println("</error>");
1813
    }
1814
    
1815
  }
1816

    
1817
  /** 
1818
   * Handle documents passed to metacat that are encoded using the 
1819
   * "multipart/form-data" mime type.  This is typically used for uploading
1820
   * data files which may be binary and large.
1821
   */
1822
  private void handleMultipartForm(HttpServletRequest request,
1823
                                   HttpServletResponse response) 
1824
  {
1825
    PrintWriter out = null;
1826
    String action = null;
1827

    
1828
    // Parse the multipart form, and save the parameters in a Hashtable and
1829
    // save the FileParts in a hashtable
1830

    
1831
    Hashtable params = new Hashtable();
1832
    Hashtable fileList = new Hashtable();
1833

    
1834
    try {
1835
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1836
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); //200MB
1837
      Part part;
1838
      while ((part = mp.readNextPart()) != null) {
1839
        String name = part.getName();
1840

    
1841
        if (part.isParam()) {
1842
          // it's a parameter part
1843
          ParamPart paramPart = (ParamPart) part;
1844
          String value = paramPart.getStringValue();
1845
          params.put(name, value);
1846
          if (name.equals("action")) {
1847
            action = value;
1848
          }
1849
        } else if (part.isFile()) {
1850
          // it's a file part
1851
          FilePart filePart = (FilePart) part;
1852
          fileList.put(name, filePart);
1853

    
1854
          // Stop once the first file part is found, otherwise going onto the
1855
          // next part prevents access to the file contents.  So...for upload
1856
          // to work, the datafile must be the last part
1857
          break;
1858
        }
1859
      }
1860
    } catch (IOException ioe) {
1861
      try {
1862
        out = response.getWriter();
1863
      } catch (IOException ioe2) {
1864
        System.err.println("Fatal Error: couldn't get response output stream.");
1865
      }
1866
      out.println("<?xml version=\"1.0\"?>");
1867
      out.println("<error>");
1868
      out.println("Error: problem reading multipart data.");
1869
      out.println("</error>");
1870
    }
1871

    
1872
    // Get the session information
1873
    String username = null;
1874
    String password = null;
1875
    String[] groupnames = null;
1876
    String sess_id = null;
1877

    
1878
    // be aware of session expiration on every request  
1879
    HttpSession sess = request.getSession(true);
1880
    if (sess.isNew()) {
1881
      // session expired or has not been stored b/w user requests
1882
      username = "public";
1883
      sess.setAttribute("username", username);
1884
    } else {
1885
      username = (String)sess.getAttribute("username");
1886
      password = (String)sess.getAttribute("password");
1887
      groupnames = (String[])sess.getAttribute("groupnames");
1888
      try {
1889
        sess_id = (String)sess.getId();
1890
      } catch(IllegalStateException ise) {
1891
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1892
                           "happen: the session should be valid: " + 
1893
                           ise.getMessage());
1894
      }
1895
    }  
1896
    
1897
    // Get the out stream
1898
    try {
1899
          out = response.getWriter();
1900
        } catch (IOException ioe2) {
1901
          util.debugMessage("Fatal Error: couldn't get response "+
1902
                                                              "output stream.");
1903
        }
1904
    
1905
    if ( action.equals("upload")) {
1906
      if (username != null &&  !username.equals("public")) {
1907
        handleUploadAction(request, out, params, fileList, 
1908
                           username, groupnames);
1909
      } else {
1910
       
1911
        out.println("<?xml version=\"1.0\"?>");
1912
        out.println("<error>");
1913
        out.println("Permission denied for " + action);
1914
        out.println("</error>");
1915
      }
1916
    } else {
1917
      /*try {
1918
        out = response.getWriter();
1919
      } catch (IOException ioe2) {
1920
        System.err.println("Fatal Error: couldn't get response output stream.");
1921
      }*/
1922
      out.println("<?xml version=\"1.0\"?>");
1923
      out.println("<error>");
1924
      out.println("Error: action not registered.  Please report this error.");
1925
      out.println("</error>");
1926
    }
1927
    out.close();
1928
  }
1929

    
1930
  /** 
1931
   * Handle the upload action by saving the attached file to disk and 
1932
   * registering it in the Metacat db
1933
   */
1934
  private void handleUploadAction(HttpServletRequest request,
1935
                                  PrintWriter out, 
1936
                                  Hashtable params, Hashtable fileList, 
1937
                                  String username, String[] groupnames)
1938
  {
1939
    //PrintWriter out = null;
1940
    //Connection conn = null;
1941
    String action = null;
1942
    String docid = null;
1943
  
1944
    /*response.setContentType("text/xml");
1945
    try 
1946
    {
1947
      out = response.getWriter();
1948
    } 
1949
    catch (IOException ioe2) 
1950
    {
1951
      System.err.println("Fatal Error: couldn't get response output stream.");
1952
    }*/
1953

    
1954
    if (params.containsKey("docid")) 
1955
    {
1956
      docid = (String)params.get("docid");
1957
    }
1958

    
1959
    // Make sure we have a docid and datafile
1960
    if (docid != null && fileList.containsKey("datafile")) {
1961

    
1962
      // Get a reference to the file part of the form
1963
      FilePart filePart = (FilePart)fileList.get("datafile");
1964
      String fileName = filePart.getFileName();
1965
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
1966

    
1967
      // Check if the right file existed in the uploaded data
1968
      if (fileName != null) {
1969
  
1970
        try 
1971
        {
1972
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
1973
           //If document get lock data file grant
1974
           if (DocumentImpl.getDataFileLockGrant(docid))
1975
           {
1976
              // register the file in the database (which generates an exception
1977
              //if the docid is not acceptable or other untoward things happen
1978
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
1979
    
1980
              // Save the data file to disk using "docid" as the name
1981
              dataDirectory.mkdirs();
1982
              File newFile = new File(dataDirectory, docid);
1983
              long size = filePart.writeTo(newFile);
1984
              
1985
              // Force replication this data file
1986
              // To data file, "insert" and update is same
1987
              // The fourth parameter is null. Because it is notification server 
1988
              // and this method is in MetaCatServerlet. It is original command, 
1989
              // not get force replication info from another metacat
1990
              ForceReplicationHandler frh = new ForceReplicationHandler
1991
                                                (docid, "insert", false, null);
1992
             
1993
              // set content type and other response header fields first
1994
              out.println("<?xml version=\"1.0\"?>");
1995
              out.println("<success>");
1996
              out.println("<docid>" + docid + "</docid>"); 
1997
              out.println("<size>" + size + "</size>"); 
1998
              out.println("</success>");
1999
          }//if
2000
    
2001
        } //try
2002
        catch (Exception e) 
2003
        {
2004
          out.println("<?xml version=\"1.0\"?>");
2005
          out.println("<error>");
2006
          out.println(e.getMessage()); 
2007
          out.println("</error>");
2008
        }
2009
       
2010
      }
2011
      else 
2012
      {
2013
        // the field did not contain a file
2014
        out.println("<?xml version=\"1.0\"?>");
2015
        out.println("<error>");
2016
        out.println("The uploaded data did not contain a valid file."); 
2017
        out.println("</error>");
2018
      }
2019
    } 
2020
    else 
2021
    {
2022
      // Error bcse docid missing or file missing
2023
      out.println("<?xml version=\"1.0\"?>");
2024
      out.println("<error>");
2025
      out.println("The uploaded data did not contain a valid docid " +
2026
                  "or valid file."); 
2027
      out.println("</error>");
2028
    }
2029
  }
2030
}
(32-32/46)