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: 2003-01-08 17:29:33 -0800 (Wed, 08 Jan 2003) $'
11
 * '$Revision: 1360 $'
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
      System.out.println("Destroying MetacatServlet");
158
      connPool.release();
159
  }
160

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

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

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

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

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

    
185
    if ( util == null ) {
186
        util = new MetaCatUtil();
187
    }
188
    /*MetaCatUtil.debugMessage("Connection pool size: "
189
                                     +connPool.getSizeOfDBConnectionPool(),10);
190
    MetaCatUtil.debugMessage("Free DBConnection number: "
191
                                  +connPool.getFreeDBConnectionNumber(), 10);*/
192
    //If all DBConnection in the pool are free and DBConnection pool
193
    //size is greater than initial value, shrink the connection pool
194
    //size to initial value
195
    DBConnectionPool.shrinkDBConnectionPoolSize();
196

    
197
    //Debug message to print out the method which have a busy DBConnection
198
    connPool.printMethodNameHavingBusyDBConnection();
199

    
200
    String ctype = request.getContentType();
201
    if (ctype != null && ctype.startsWith("multipart/form-data")) {
202
      handleMultipartForm(request, response);
203
    } else {
204

    
205

    
206
      String name = null;
207
      String[] value = null;
208
      String[] docid = new String[3];
209
      Hashtable params = new Hashtable();
210
      Enumeration paramlist = request.getParameterNames();
211

    
212

    
213
      while (paramlist.hasMoreElements()) {
214

    
215
        name = (String)paramlist.nextElement();
216
        value = request.getParameterValues(name);
217

    
218
        // Decode the docid and mouse click information
219
        if (name.endsWith(".y")) {
220
          docid[0] = name.substring(0,name.length()-2);
221
          params.put("docid", docid);
222
          name = "ypos";
223
        }
224
        if (name.endsWith(".x")) {
225
          name = "xpos";
226
        }
227

    
228
        params.put(name,value);
229
      }
230

    
231

    
232
      //handle param is emptpy
233
      if (params.isEmpty() || params == null)
234
      {
235
        return;
236
      }
237
      //if the user clicked on the input images, decode which image
238
      //was clicked then set the action.
239
      String action = ((String[])params.get("action"))[0];
240
      util.debugMessage("Line 230: Action is: " + action, 1);
241

    
242
      // This block handles session management for the servlet
243
      // by looking up the current session information for all actions
244
      // other than "login" and "logout"
245
      String username = null;
246
      String password = null;
247
      String[] groupnames = null;
248
      String sess_id = null;
249

    
250
      // handle login action
251
      if (action.equals("login")) {
252
        PrintWriter out = response.getWriter();
253
        handleLoginAction(out, params, request, response);
254
        out.close();
255

    
256
      // handle logout action
257
      } else if (action.equals("logout")) {
258
        PrintWriter out = response.getWriter();
259
        handleLogoutAction(out, params, request, response);
260
        out.close();
261

    
262
      // handle shrink DBConnection request
263
      } else if (action.equals("shrink")) {
264
        PrintWriter out = response.getWriter();
265
        boolean success = false;
266
        //If all DBConnection in the pool are free and DBConnection pool
267
        //size is greater than initial value, shrink the connection pool
268
        //size to initial value
269
        success = DBConnectionPool.shrinkConnectionPoolSize();
270
        if (success)
271
        {
272
          //if successfully shrink the pool size to initial value
273
          out.println("DBConnection Pool shrink successfully");
274
        }//if
275
        else
276
        {
277
          out.println("DBConnection pool couldn't shrink successfully");
278
        }
279
       //close out put
280
        out.close();
281

    
282
      // aware of session expiration on every request
283
      } else {
284

    
285
        HttpSession sess = request.getSession(true);
286
        if (sess.isNew()) {
287
          // session expired or has not been stored b/w user requests
288
          username = "public";
289
          sess.setAttribute("username", username);
290
        } else {
291
          username = (String)sess.getAttribute("username");
292
          password = (String)sess.getAttribute("password");
293
          groupnames = (String[])sess.getAttribute("groupnames");
294
          try {
295
            sess_id = (String)sess.getId();
296
          } catch(IllegalStateException ise) {
297
            System.out.println("error in handleGetOrPost: this shouldn't " +
298
                               "happen: the session should be valid: " +
299
                               ise.getMessage());
300
          }
301
        }
302
      }
303

    
304
       // Now that we know the session is valid, we can delegate the request
305
      // to a particular action handler
306
      if(action.equals("query")) {
307
        PrintWriter out = response.getWriter();
308
        handleQuery(out,params,response,username,groupnames);
309
        out.close();
310
      } else if(action.equals("squery")) {
311
        PrintWriter out = response.getWriter();
312
        if(params.containsKey("query")) {
313
         handleSQuery(out, params,response,username,groupnames);
314
         out.close();
315
        } else {
316
          out.println("Illegal action squery without \"query\" parameter");
317
          out.close();
318
        }
319
      } else if (action.equals("export")) {
320

    
321
        handleExportAction(params, response, username, groupnames, password);
322
      } else if (action.equals("read")) {
323
        handleReadAction(params, response, username,password, groupnames);
324
      } else if (action.equals("insert") || action.equals("update")) {
325
        PrintWriter out = response.getWriter();
326
        if ( (username != null) &&  !username.equals("public") ) {
327
          handleInsertOrUpdateAction(out,params,response,username,groupnames);
328
        } else {
329
          out.println("Permission denied for " + action);
330
        }
331
        out.close();
332
      } else if (action.equals("delete")) {
333
        PrintWriter out = response.getWriter();
334
        if ( (username != null) &&  !username.equals("public") ) {
335
          handleDeleteAction(out, params, response, username, groupnames);
336
        } else {
337
          out.println("Permission denied for " + action);
338
        }
339
        out.close();
340
      } else if (action.equals("validate")) {
341
        PrintWriter out = response.getWriter();
342
        handleValidateAction(out, params);
343
        out.close();
344
      } else if (action.equals("getaccesscontrol")) {
345
        PrintWriter out = response.getWriter();
346
        handleGetAccessControlAction(out,params,response,username,groupnames);
347
        out.close();
348
      } else if (action.equals("getprincipals")) {
349
        PrintWriter out = response.getWriter();
350
        handleGetPrincipalsAction(out, username, password);
351
        out.close();
352
      } else if (action.equals("getdoctypes")) {
353
        PrintWriter out = response.getWriter();
354
        handleGetDoctypesAction(out, params, response);
355
        out.close();
356
      } else if (action.equals("getdtdschema")) {
357
        PrintWriter out = response.getWriter();
358
        handleGetDTDSchemaAction(out, params, response);
359
        out.close();
360
      } else if (action.equals("getdataguide")) {
361
        PrintWriter out = response.getWriter();
362
        handleGetDataGuideAction(out, params, response);
363
        out.close();
364
      } else if (action.equals("getlastdocid")) {
365
        PrintWriter out = response.getWriter();
366
        handleGetMaxDocidAction(out, params, response);
367
        out.close();
368
      } else if (action.equals("getrevisionanddoctype")) {
369
        PrintWriter out = response.getWriter();
370
        handleGetRevisionAndDocTypeAction(out, params);
371
        out.close();
372
      } else if (action.equals("login") || action.equals("logout")) {
373
      } else if (action.equals("protocoltest")) {
374
        String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
375
        try {
376
          testURL = ((String[])params.get("url"))[0];
377
        } catch (Throwable t) {
378
        }
379
        String phandler = System.getProperty("java.protocol.handler.pkgs");
380
        response.setContentType("text/html");
381
        PrintWriter out = response.getWriter();
382
        out.println("<body bgcolor=\"white\">");
383
        out.println("<p>Handler property: <code>" + phandler + "</code></p>");
384
        out.println("<p>Starting test for:<br>");
385
        out.println("    " + testURL + "</p>");
386
        try {
387
          URL u = new URL(testURL);
388
          out.println("<pre>");
389
          out.println("Protocol: " + u.getProtocol());
390
          out.println("    Host: " + u.getHost());
391
          out.println("    Port: " + u.getPort());
392
          out.println("    Path: " + u.getPath());
393
          out.println("     Ref: " + u.getRef());
394
          String pquery = u.getQuery();
395
          out.println("   Query: " + pquery);
396
          out.println("  Params: ");
397
          if (pquery != null) {
398
            Hashtable qparams = util.parseQuery(u.getQuery());
399
            for (Enumeration en = qparams.keys(); en.hasMoreElements(); ) {
400
              String pname = (String)en.nextElement();
401
              String pvalue = (String)qparams.get(pname);
402
              out.println("    " + pname + ": " + pvalue);
403
            }
404
          }
405
          out.println("</pre>");
406
          out.println("</body>");
407
          out.close();
408
        } catch (MalformedURLException mue) {
409
          System.out.println("bad url from MetacatServlet.handleGetOrPost");
410
          out.println(mue.getMessage());
411
          mue.printStackTrace(out);
412
          out.close();
413
        }
414
      } else {
415
        PrintWriter out = response.getWriter();
416
        out.println("<?xml version=\"1.0\"?>");
417
        out.println("<error>");
418
        out.println("Error: action not registered.  Please report this error.");
419
        out.println("</error>");
420
        out.close();
421
      }
422

    
423
      //util.closeConnections();
424
      // Close the stream to the client
425
      //out.close();
426
    }
427
  }
428

    
429
  // LOGIN & LOGOUT SECTION
430
  /**
431
   * Handle the login request. Create a new session object.
432
   * Do user authentication through the session.
433
   */
434
  private void handleLoginAction(PrintWriter out, Hashtable params,
435
               HttpServletRequest request, HttpServletResponse response) {
436

    
437
    AuthSession sess = null;
438
    String un = ((String[])params.get("username"))[0];
439
    String pw = ((String[])params.get("password"))[0];
440
    String action = ((String[])params.get("action"))[0];
441
    String qformat = ((String[])params.get("qformat"))[0];
442

    
443
    try {
444
      sess = new AuthSession();
445
    } catch (Exception e) {
446
      System.out.println("error in MetacatServlet.handleLoginAction: " +
447
                          e.getMessage());
448
      out.println(e.getMessage());
449
      return;
450
    }
451
    boolean isValid = sess.authenticate(request, un, pw);
452
    // format and transform the output
453
    if (qformat.equals("xml")) {
454
      response.setContentType("text/xml");
455
      out.println(sess.getMessage());
456
    } else {
457

    
458
      try {
459

    
460
        DBTransform trans = new DBTransform();
461
        response.setContentType("text/html");
462
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
463
                                   "-//W3C//HTML//EN", qformat, out);
464

    
465
      } catch(Exception e) {
466

    
467
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
468
                                +e.getMessage(), 30);
469
      }
470

    
471
    // any output is returned
472
    }
473
  }
474

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

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

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

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

    
494
    //format and transform the output
495
    if (qformat.equals("xml")) {
496
      response.setContentType("text/xml");
497
      out.println(output.toString());
498
    } else {
499

    
500
      try {
501

    
502
        DBTransform trans = new DBTransform();
503
        response.setContentType("text/html");
504
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
505
                                   "-//W3C//HTML//EN", qformat, out);
506

    
507
      } catch(Exception e) {
508

    
509
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
510
                                  +e.getMessage(), 30);
511
      }
512
    }
513
  }
514
  // END OF LOGIN & LOGOUT SECTION
515

    
516
  // SQUERY & QUERY SECTION
517
  /**
518
   * Retreive the squery xml, execute it and display it
519
   *
520
   * @param out the output stream to the client
521
   * @param params the Hashtable of parameters that should be included
522
   * in the squery.
523
   * @param response the response object linked to the client
524
   * @param conn the database connection
525
   */
526
  protected void handleSQuery(PrintWriter out, Hashtable params,
527
                 HttpServletResponse response, String user, String[] groups)
528
  {
529
    String xmlquery = ((String[])params.get("query"))[0];
530
    String qformat = ((String[])params.get("qformat"))[0];
531
    String resultdoc = null;
532
    MetaCatUtil.debugMessage("xmlquery: "+xmlquery, 30);
533
    double startTime = System.currentTimeMillis()/1000;
534
    Hashtable doclist = runQuery(xmlquery, user, groups);
535
    double docListTime = System.currentTimeMillis()/1000;
536
    MetaCatUtil.debugMessage("Time for getting doc list: "
537
                                            +(docListTime-startTime), 30);
538

    
539
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
540
    double toStringTime = System.currentTimeMillis()/1000;
541
    MetaCatUtil.debugMessage("Time to create xml string: "
542
                              +(toStringTime-docListTime), 30);
543
    //format and transform the results
544
    double outPutTime = 0;
545
    if(qformat.equals("xml")) {
546
      response.setContentType("text/xml");
547
      out.println(resultdoc);
548
      outPutTime = System.currentTimeMillis()/1000;
549
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
550
    } else {
551
      transformResultset(resultdoc, response, out, qformat);
552
      outPutTime = System.currentTimeMillis()/1000;
553
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
554
    }
555
  }
556

    
557
   /**
558
    * Create the xml query, execute it and display the results.
559
    *
560
    * @param out the output stream to the client
561
    * @param params the Hashtable of parameters that should be included
562
    * in the squery.
563
    * @param response the response object linked to the client
564
    */
565
  protected void handleQuery(PrintWriter out, Hashtable params,
566
                 HttpServletResponse response, String user, String[] groups)
567
  {
568
    //create the query and run it
569
    String xmlquery = DBQuery.createSQuery(params);
570
    Hashtable doclist = runQuery(xmlquery, user, groups);
571
    String qformat = ((String[])params.get("qformat"))[0];
572
    String resultdoc = null;
573

    
574
    resultdoc = createResultDocument(doclist, transformQuery(params));
575

    
576
    //format and transform the results
577
    if(qformat.equals("xml")) {
578
      response.setContentType("text/xml");
579
      out.println(resultdoc);
580
    } else {
581
      transformResultset(resultdoc, response, out, qformat);
582
    }
583
  }
584

    
585
  /**
586
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
587
   * so it can properly be placed in the <query> tag of the resultset.
588
   * This method is overwritable so that other applications can customize
589
   * the structure of what is in the <query> tag.
590
   *
591
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
592
   */
593
  protected String transformQuery(Hashtable params)
594
  {
595
    //DBQuery.createSQuery is a re-calling of a previously called
596
    //function but it is necessary
597
    //so that overriding methods have access to the params hashtable
598
    String xmlquery = DBQuery.createSQuery(params);
599
    //the <?xml version="1.0"?> tag is the first 22 characters of the
600
    xmlquery = xmlquery.trim();
601
    int index = xmlquery.indexOf("?>");
602
    return xmlquery.substring(index + 2, xmlquery.length());
603
  }
604

    
605
  /**
606
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
607
   * string as a param instead of a hashtable.
608
   *
609
   * @param xmlquery a string representing a query.
610
   */
611
  protected String transformQuery(String xmlquery)
612
  {
613
    xmlquery = xmlquery.trim();
614
    int index = xmlquery.indexOf("?>");
615
    return xmlquery.substring(index + 2, xmlquery.length());
616
  }
617

    
618
  /**
619
   * Run the query and return a hashtable of results.
620
   *
621
   * @param xmlquery the query to run
622
   */
623
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
624
  {
625
    Hashtable doclist=null;
626

    
627
    try
628
    {
629

    
630
      DBQuery queryobj = new DBQuery(saxparser);
631
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
632

    
633
      return doclist;
634
    }
635
    catch (Exception e)
636
    {
637

    
638
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
639
                                                      + e.getMessage(), 30);
640
      doclist = null;
641
      return doclist;
642
    }
643
  }
644

    
645
  /**
646
   * Transorms an xml resultset document to html and sends it to the browser
647
   *
648
   * @param resultdoc the string representation of the document that needs
649
   * to be transformed.
650
   * @param response the HttpServletResponse object bound to the client.
651
   * @param out the output stream to the client
652
   * @param qformat the name of the style-set to use for transformations
653
   */
654
  protected void transformResultset(String resultdoc,
655
                                    HttpServletResponse response,
656
                                    PrintWriter out, String qformat)
657
  {
658

    
659
    try {
660

    
661
      DBTransform trans = new DBTransform();
662
      response.setContentType("text/html");
663
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
664
                                 "-//W3C//HTML//EN", qformat, out);
665

    
666
    }
667
    catch(Exception e)
668
    {
669

    
670
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
671
                                +e.getMessage(), 30);
672
    }
673
  }
674

    
675
  /**
676
   * Transforms a hashtable of documents to an xml or html result.
677
   *
678
   * @param doclist- the hashtable to transform
679
   * @param xmlquery- the query that returned the doclist result
680
   */
681
  protected String createResultDocument(Hashtable doclist, String xmlquery)
682
  {
683
    // Create a buffer to hold the xml result
684
    StringBuffer resultset = new StringBuffer();
685

    
686
    // Print the resulting root nodes
687
    String docid = null;
688
    String document = null;
689
    resultset.append("<?xml version=\"1.0\"?>\n");
690
    resultset.append("<resultset>\n");
691

    
692
    resultset.append("  <query>" + xmlquery + "</query>");
693

    
694
    if(doclist != null)
695
    {
696
      Enumeration doclistkeys = doclist.keys();
697
      while (doclistkeys.hasMoreElements())
698
      {
699
        docid = (String)doclistkeys.nextElement();
700
        document = (String)doclist.get(docid);
701
        resultset.append("  <document>" + document + "</document>");
702
      }
703
    }
704

    
705
    resultset.append("</resultset>");
706
    return resultset.toString();
707
  }
708
  // END OF SQUERY & QUERY SECTION
709

    
710
 //Exoport section
711
 /**
712
   * Handle the "export" request of data package from Metacat in zip format
713
   * @param params the Hashtable of HTTP request parameters
714
   * @param response the HTTP response object linked to the client
715
   * @param user the username sent the request
716
   * @param groups the user's groupnames
717
   */
718
  private void handleExportAction(Hashtable params,
719
    HttpServletResponse response, String user, String[] groups, String passWord)
720
  {
721
    // Output stream
722
    ServletOutputStream out = null;
723
    // Zip output stream
724
    ZipOutputStream zOut = null;
725
    DocumentImpl docImpls=null;
726
    DBQuery queryObj=null;
727

    
728
    String[] docs = new String[10];
729
    String docId = "";
730

    
731
    try
732
    {
733
      // read the params
734
      if (params.containsKey("docid"))
735
      {
736
        docs = (String[])params.get("docid");
737
      }//if
738
      // Create a DBuery to handle export
739
      queryObj = new DBQuery(saxparser);
740
      // Get the docid
741
      docId=docs[0];
742
      // Make sure the client specify docid
743
      if (docId == null || docId.equals(""))
744
      {
745
        response.setContentType("text/xml"); //MIME type
746
        // Get a printwriter
747
        PrintWriter pw = response.getWriter();
748
        // Send back message
749
        pw.println("<?xml version=\"1.0\"?>");
750
        pw.println("<error>");
751
        pw.println("You didn't specify requested docid");
752
        pw.println("</error>");
753
        // Close printwriter
754
        pw.close();
755
        return;
756
      }//if
757
      // Get output stream
758
      out = response.getOutputStream();
759
      response.setContentType("application/zip"); //MIME type
760
      zOut = new ZipOutputStream(out);
761
      zOut =queryObj.getZippedPackage(docId, out, user, groups, passWord);
762
      zOut.finish(); //terminate the zip file
763
      zOut.close();  //close the zip stream
764

    
765
    }//try
766
    catch (Exception e)
767
    {
768
      try
769
      {
770
        response.setContentType("text/xml"); //MIME type
771
        // Send error message back
772
        if (out != null)
773
        {
774
            PrintWriter pw = new PrintWriter(out);
775
            pw.println("<?xml version=\"1.0\"?>");
776
            pw.println("<error>");
777
            pw.println(e.getMessage());
778
            pw.println("</error>");
779
            // Close printwriter
780
            pw.close();
781
            // Close output stream
782
            out.close();
783
        }//if
784
        // Close zip output stream
785
        if ( zOut != null )
786
        {
787
          zOut.close();
788
        }//if
789
      }//try
790
      catch (IOException ioe)
791
      {
792
        MetaCatUtil.debugMessage("Problem with the servlet output " +
793
                           "in MetacatServlet.handleExportAction: " +
794
                           ioe.getMessage(), 30);
795
      }//catch
796

    
797
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
798
                         e.getMessage(), 30);
799
      e.printStackTrace(System.out);
800

    
801
    }//catch
802

    
803
  }//handleExportAction
804

    
805
  // READ SECTION
806
  /**
807
   * Handle the "read" request of metadata/data files from Metacat
808
   * or any files from Internet;
809
   * transformed metadata XML document into HTML presentation if requested;
810
   * zip files when more than one were requested.
811
   *
812
   * @param params the Hashtable of HTTP request parameters
813
   * @param response the HTTP response object linked to the client
814
   * @param user the username sent the request
815
   * @param groups the user's groupnames
816
   */
817
  private void handleReadAction(Hashtable params, HttpServletResponse response,
818
                                String user, String passWord, String[] groups)
819
  {
820
    ServletOutputStream out = null;
821
    ZipOutputStream zout = null;
822
    PrintWriter pw = null;
823
    boolean zip = false;
824

    
825
    try {
826
      String[] docs = new String[0];
827
      String docid = "";
828
      String qformat = "";
829
      String abstrpath = null;
830

    
831
      // read the params
832
      if (params.containsKey("docid")) {
833
        docs = (String[])params.get("docid");
834
      }
835
      if (params.containsKey("qformat")) {
836
        qformat = ((String[])params.get("qformat"))[0];
837
      }
838
      if (params.containsKey("abstractpath")) {
839
        abstrpath = ((String[])params.get("abstractpath"))[0];
840
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
841
          viewAbstract(response, abstrpath, docs[0]);
842
          return;
843
        }
844
      }
845
      if ( (docs.length > 1) || qformat.equals("zip") ) {
846
        zip = true;
847
        out = response.getOutputStream();
848
        response.setContentType("application/zip"); //MIME type
849
        zout = new ZipOutputStream(out);
850
      }
851
      // go through the list of docs to read
852
      for (int i=0; i < docs.length; i++ ) {
853
        try {
854

    
855
          URL murl = new URL(docs[i]);
856
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
857
          // case docid="http://.../?docid=aaa"
858
          // or docid="metacat://.../?docid=bbb"
859
          if (murlQueryStr.containsKey("docid")) {
860
            // get only docid, eliminate the rest
861
            docid = (String)murlQueryStr.get("docid");
862
            if ( zip ) {
863
              addDocToZip(docid, zout, user, groups);
864
            } else {
865
              readFromMetacat(response, docid, qformat, abstrpath,
866
                              user, groups, zip, zout);
867
            }
868

    
869
          // case docid="http://.../filename"
870
          } else {
871
            docid = docs[i];
872
            if ( zip ) {
873
              addDocToZip(docid, zout, user, groups);
874
            } else {
875
              readFromURLConnection(response, docid);
876
            }
877
          }
878

    
879
        // case docid="ccc"
880
        } catch (MalformedURLException mue) {
881
          docid = docs[i];
882
          if ( zip ) {
883
            addDocToZip(docid, zout, user, groups);
884
          } else {
885
            readFromMetacat(response, docid, qformat, abstrpath,
886
                            user, groups, zip, zout);
887
          }
888
        }
889

    
890
      } /* end for */
891

    
892
      if ( zip ) {
893
        zout.finish(); //terminate the zip file
894
        zout.close();  //close the zip stream
895
      }
896

    
897

    
898
    }
899
    // To handle doc not found exception
900
    catch (McdbDocNotFoundException notFoundE)
901
    {
902
      // the docid which didn't be found
903
      String notFoundDocId = notFoundE.getUnfoundDocId();
904
      String notFoundRevision = notFoundE.getUnfoundRevision();
905
      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
906
      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
907
      try
908
      {
909
        // read docid from remote server
910
        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
911
                                              user, passWord, out, zip, zout);
912
        // Close zout outputstream
913
        if ( zout != null)
914
        {
915
          zout.close();
916
        }
917
        // close output stream
918
        if (out != null)
919
        {
920
          out.close();
921
        }
922

    
923
      }//try
924
      catch ( Exception exc)
925
      {
926
        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
927
                                      exc.getMessage(), 30);
928
        try
929
        {
930
          if (out != null)
931
          {
932
            response.setContentType("text/xml");
933
            // Send back error message by printWriter
934
            pw = new PrintWriter(out);
935
            pw.println("<?xml version=\"1.0\"?>");
936
            pw.println("<error>");
937
            pw.println(notFoundE.getMessage());
938
            pw.println("</error>");
939
            pw.close();
940
            out.close();
941

    
942
          }
943
          else
944
          {
945
           response.setContentType("text/xml"); //MIME type
946
           // Send back error message if out = null
947
           if (pw == null)
948
           {
949
             // If pw is null, open the respnose
950
            pw = response.getWriter();
951
           }
952
           pw.println("<?xml version=\"1.0\"?>");
953
           pw.println("<error>");
954
           pw.println(notFoundE.getMessage());
955
           pw.println("</error>");
956
           pw.close();
957
        }
958
        // close zout
959
        if ( zout != null )
960
        {
961
          zout.close();
962
        }
963
        }//try
964
        catch (IOException ie)
965
        {
966
          MetaCatUtil.debugMessage("Problem with the servlet output " +
967
                           "in MetacatServlet.handleReadAction: " +
968
                           ie.getMessage(), 30);
969
        }//cathch
970
      }//catch
971
    }// catch McdbDocNotFoundException
972
    catch (Exception e)
973
    {
974
      try {
975

    
976
        if (out != null) {
977
            response.setContentType("text/xml"); //MIME type
978
            pw = new PrintWriter(out);
979
            pw.println("<?xml version=\"1.0\"?>");
980
            pw.println("<error>");
981
            pw.println(e.getMessage());
982
            pw.println("</error>");
983
            pw.close();
984
            out.close();
985
        }
986
        else
987
        {
988
           response.setContentType("text/xml"); //MIME type
989
           // Send back error message if out = null
990
           if ( pw == null)
991
           {
992
            pw = response.getWriter();
993
           }
994
           pw.println("<?xml version=\"1.0\"?>");
995
           pw.println("<error>");
996
           pw.println(e.getMessage());
997
           pw.println("</error>");
998
           pw.close();
999

    
1000
        }
1001
        // Close zip output stream
1002
        if ( zout != null ) { zout.close(); }
1003

    
1004
      } catch (IOException ioe) {
1005
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1006
                           "in MetacatServlet.handleReadAction: " +
1007
                           ioe.getMessage(), 30);
1008
        ioe.printStackTrace(System.out);
1009

    
1010
      }
1011

    
1012
      System.out.println("Error in MetacatServlet.handleReadAction: " +
1013
                         e.getMessage());
1014
      e.printStackTrace(System.out);
1015
    }
1016

    
1017
  }
1018

    
1019
  // read metadata or data from Metacat
1020
  private void readFromMetacat(HttpServletResponse response, String docid,
1021
                               String qformat, String abstrpath, String user,
1022
                             String[] groups, boolean zip, ZipOutputStream zout)
1023
               throws ClassNotFoundException, IOException, SQLException,
1024
                      McdbException, Exception
1025
  {
1026

    
1027
    try {
1028

    
1029

    
1030
      DocumentImpl doc = new DocumentImpl(docid);
1031

    
1032
      //check the permission for read
1033
      if (!doc.hasReadPermission(user, groups, docid))
1034
      {
1035
        Exception e = new Exception("User " + user + " does not have permission"
1036
                       +" to read the document with the docid " + docid);
1037

    
1038
        throw e;
1039
      }
1040

    
1041
      if ( doc.getRootNodeID() == 0 ) {
1042
        // this is data file
1043
        String filepath = util.getOption("datafilepath");
1044
        if(!filepath.endsWith("/")) {
1045
          filepath += "/";
1046
        }
1047
        String filename = filepath + docid;
1048
        FileInputStream fin = null;
1049
        fin = new FileInputStream(filename);
1050

    
1051
        //MIME type
1052
        String contentType = getServletContext().getMimeType(filename);
1053
        if (contentType == null) {
1054
          if (filename.endsWith(".xml")) {
1055
            contentType="text/xml";
1056
          } else if (filename.endsWith(".css")) {
1057
            contentType="text/css";
1058
          } else if (filename.endsWith(".dtd")) {
1059
            contentType="text/plain";
1060
          } else if (filename.endsWith(".xsd")) {
1061
            contentType="text/xml";
1062
          } else if (filename.endsWith("/")) {
1063
            contentType="text/html";
1064
          } else {
1065
            File f = new File(filename);
1066
            if ( f.isDirectory() ) {
1067
              contentType="text/html";
1068
            } else {
1069
              contentType="application/octet-stream";
1070
            }
1071
          }
1072
        }
1073
        response.setContentType(contentType);
1074
        // if we decide to use "application/octet-stream" for all data returns
1075
        // response.setContentType("application/octet-stream");
1076

    
1077
        try {
1078

    
1079
          ServletOutputStream out = response.getOutputStream();
1080
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1081
          int b = fin.read(buf);
1082
          while (b != -1) {
1083
            out.write(buf, 0, b);
1084
            b = fin.read(buf);
1085
          }
1086
        } finally {
1087
          if (fin != null) fin.close();
1088
        }
1089

    
1090
      } else {
1091
        // this is metadata doc
1092
        if ( qformat.equals("xml") ) {
1093

    
1094
          // set content type first
1095
          response.setContentType("text/xml");   //MIME type
1096
          PrintWriter out = response.getWriter();
1097
          doc.toXml(out);
1098
        } else {
1099
          response.setContentType("text/html");  //MIME type
1100
          PrintWriter out = response.getWriter();
1101

    
1102
          // Look up the document type
1103
          String doctype = doc.getDoctype();
1104
          // Transform the document to the new doctype
1105
          DBTransform dbt = new DBTransform();
1106
          dbt.transformXMLDocument(doc.toString(),
1107
                                   doctype,"-//W3C//HTML//EN", qformat, out);
1108
        }
1109

    
1110
      }
1111
    }
1112
    catch (Exception except)
1113
    {
1114
      throw except;
1115

    
1116
    }
1117

    
1118
  }
1119

    
1120
  // read data from URLConnection
1121
  private void readFromURLConnection(HttpServletResponse response, String docid)
1122
               throws IOException, MalformedURLException
1123
  {
1124
    ServletOutputStream out = response.getOutputStream();
1125
    String contentType = getServletContext().getMimeType(docid); //MIME type
1126
    if (contentType == null) {
1127
      if (docid.endsWith(".xml")) {
1128
        contentType="text/xml";
1129
      } else if (docid.endsWith(".css")) {
1130
        contentType="text/css";
1131
      } else if (docid.endsWith(".dtd")) {
1132
        contentType="text/plain";
1133
      } else if (docid.endsWith(".xsd")) {
1134
        contentType="text/xml";
1135
      } else if (docid.endsWith("/")) {
1136
        contentType="text/html";
1137
      } else {
1138
        File f = new File(docid);
1139
        if ( f.isDirectory() ) {
1140
          contentType="text/html";
1141
        } else {
1142
          contentType="application/octet-stream";
1143
        }
1144
      }
1145
    }
1146
    response.setContentType(contentType);
1147
    // if we decide to use "application/octet-stream" for all data returns
1148
    // response.setContentType("application/octet-stream");
1149

    
1150
    // this is http url
1151
    URL url = new URL(docid);
1152
    BufferedInputStream bis = null;
1153
    try {
1154
      bis = new BufferedInputStream(url.openStream());
1155
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1156
      int b = bis.read(buf);
1157
      while (b != -1) {
1158
        out.write(buf, 0, b);
1159
        b = bis.read(buf);
1160
      }
1161
    } finally {
1162
      if (bis != null) bis.close();
1163
    }
1164

    
1165
  }
1166

    
1167
  // read file/doc and write to ZipOutputStream
1168
  private void addDocToZip(String docid, ZipOutputStream zout,
1169
                              String user, String[] groups)
1170
               throws ClassNotFoundException, IOException, SQLException,
1171
                      McdbException, Exception
1172
  {
1173
    byte[] bytestring = null;
1174
    ZipEntry zentry = null;
1175

    
1176
    try {
1177
      URL url = new URL(docid);
1178

    
1179
      // this http url; read from URLConnection; add to zip
1180
      zentry = new ZipEntry(docid);
1181
      zout.putNextEntry(zentry);
1182
      BufferedInputStream bis = null;
1183
      try {
1184
        bis = new BufferedInputStream(url.openStream());
1185
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1186
        int b = bis.read(buf);
1187
        while(b != -1) {
1188
          zout.write(buf, 0, b);
1189
          b = bis.read(buf);
1190
        }
1191
      } finally {
1192
        if (bis != null) bis.close();
1193
      }
1194
      zout.closeEntry();
1195

    
1196
    } catch (MalformedURLException mue) {
1197

    
1198
      // this is metacat doc (data file or metadata doc)
1199

    
1200
      try {
1201

    
1202
        DocumentImpl doc = new DocumentImpl(docid);
1203

    
1204
        //check the permission for read
1205
        if (!doc.hasReadPermission(user, groups, docid))
1206
        {
1207
          Exception e = new Exception("User " + user + " does not have "
1208
                    +"permission to read the document with the docid " + docid);
1209

    
1210
          throw e;
1211
        }
1212

    
1213
        if ( doc.getRootNodeID() == 0 ) {
1214
          // this is data file; add file to zip
1215
          String filepath = util.getOption("datafilepath");
1216
          if(!filepath.endsWith("/")) {
1217
            filepath += "/";
1218
          }
1219
          String filename = filepath + docid;
1220
          FileInputStream fin = null;
1221
          fin = new FileInputStream(filename);
1222
          try {
1223

    
1224
            zentry = new ZipEntry(docid);
1225
            zout.putNextEntry(zentry);
1226
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1227
            int b = fin.read(buf);
1228
            while (b != -1) {
1229
              zout.write(buf, 0, b);
1230
              b = fin.read(buf);
1231
            }
1232
          } finally {
1233
            if (fin != null) fin.close();
1234
          }
1235
          zout.closeEntry();
1236

    
1237
        } else {
1238
          // this is metadata doc; add doc to zip
1239
          bytestring = doc.toString().getBytes();
1240
          zentry = new ZipEntry(docid + ".xml");
1241
          zentry.setSize(bytestring.length);
1242
          zout.putNextEntry(zentry);
1243
          zout.write(bytestring, 0, bytestring.length);
1244
          zout.closeEntry();
1245
        }
1246
      } catch (Exception except) {
1247
        throw except;
1248

    
1249
      }
1250

    
1251
    }
1252

    
1253
  }
1254

    
1255
  // view abstract within document
1256
  private void viewAbstract(HttpServletResponse response,
1257
                            String abstractpath, String docid)
1258
               throws ClassNotFoundException, IOException, SQLException,
1259
                      McdbException, Exception
1260
  {
1261

    
1262
    PrintWriter out =null;
1263
    try {
1264

    
1265
      response.setContentType("text/html");  //MIME type
1266
      out = response.getWriter();
1267
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1268
      out.println("<html><head><title>Abstract</title></head>");
1269
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1270
      for (int i=0; i<abstracts.length; i++) {
1271
        out.println("<p>" + (String)abstracts[i] + "</p>");
1272
      }
1273
      out.println("</body></html>");
1274

    
1275
    } catch (Exception e) {
1276
       out.println("<?xml version=\"1.0\"?>");
1277
       out.println("<error>");
1278
       out.println(e.getMessage());
1279
       out.println("</error>");
1280

    
1281

    
1282
    }
1283
  }
1284
  /**
1285
   * If metacat couldn't find a data file or document locally, it will read this
1286
   * docid from its home server. This is for the replication feature
1287
   */
1288
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid,
1289
                     String rev, String user, String password,
1290
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1291
                        throws Exception
1292
 {
1293
   // Create a object of RemoteDocument, "" is for zipEntryPath
1294
   RemoteDocument remoteDoc =
1295
                        new RemoteDocument (docid, rev,user, password, "");
1296
   String docType = remoteDoc.getDocType();
1297
   // Only read data file
1298
   if (docType.equals("BIN"))
1299
   {
1300
    // If it is zip format
1301
    if (zip)
1302
    {
1303
      remoteDoc.readDocumentFromRemoteServerByZip(zout);
1304
    }//if
1305
    else
1306
    {
1307
      if (out == null)
1308
      {
1309
        out = response.getOutputStream();
1310
      }//if
1311
      response.setContentType("application/octet-stream");
1312
      remoteDoc.readDocumentFromRemoteServer(out);
1313
    }//else (not zip)
1314
   }//if doctype=bin
1315
   else
1316
   {
1317
     throw new Exception("Docid: "+docid+"."+rev+" couldn't find");
1318
   }//else
1319
 }//readFromRemoteMetaCat
1320

    
1321
  // END OF READ SECTION
1322

    
1323
  // INSERT/UPDATE SECTION
1324
  /**
1325
   * Handle the database putdocument request and write an XML document
1326
   * to the database connection
1327
   */
1328
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1329
               HttpServletResponse response, String user, String[] groups) {
1330

    
1331
    DBConnection dbConn = null;
1332
    int serialNumber = -1;
1333

    
1334
    try {
1335
      // Get the document indicated
1336
      String[] doctext = (String[])params.get("doctext");
1337

    
1338
      String pub = null;
1339
      if (params.containsKey("public")) {
1340
        pub = ((String[])params.get("public"))[0];
1341
      }
1342

    
1343
      StringReader dtd = null;
1344
      if (params.containsKey("dtdtext")) {
1345
        String[] dtdtext = (String[])params.get("dtdtext");
1346
        try {
1347
          if ( !dtdtext[0].equals("") ) {
1348
            dtd = new StringReader(dtdtext[0]);
1349
          }
1350
        } catch (NullPointerException npe) {}
1351
      }
1352

    
1353
      StringReader xml = null;
1354
      boolean validate = false;
1355
      try {
1356
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1357
        // in order to decide whether to use validation parser
1358
        validate = validateXML(doctext[0]);
1359
        xml = new StringReader(doctext[0]);
1360

    
1361
        String[] action = (String[])params.get("action");
1362
        String[] docid = (String[])params.get("docid");
1363
        String newdocid = null;
1364

    
1365
        String doAction = null;
1366
        if (action[0].equals("insert")) {
1367
          doAction = "INSERT";
1368
        } else if (action[0].equals("update")) {
1369
          doAction = "UPDATE";
1370
        }
1371

    
1372
        try
1373
        {
1374
          // get a connection from the pool
1375
          dbConn=DBConnectionPool.
1376
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1377
          serialNumber=dbConn.getCheckOutSerialNumber();
1378

    
1379

    
1380
          // write the document to the database
1381
          try
1382
          {
1383
            String accNumber = docid[0];
1384
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1385
            if (accNumber.equals(""))
1386
            {
1387
              accNumber = null;
1388
            }//if
1389
            newdocid = DocumentImpl.write(dbConn, xml, pub, dtd, doAction,
1390
                                          accNumber, user, groups, validate);
1391

    
1392
          }//try
1393
          catch (NullPointerException npe)
1394
          {
1395
            newdocid = DocumentImpl.write(dbConn, xml, pub, dtd, doAction,
1396
                                          null, user, groups, validate);
1397
          }//catch
1398
        }//try
1399
        finally
1400
        {
1401
          // Return db connection
1402
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1403
        }
1404

    
1405
        // set content type and other response header fields first
1406
        response.setContentType("text/xml");
1407
        out.println("<?xml version=\"1.0\"?>");
1408
        out.println("<success>");
1409
        out.println("<docid>" + newdocid + "</docid>");
1410
        out.println("</success>");
1411

    
1412
      } catch (NullPointerException npe) {
1413
        response.setContentType("text/xml");
1414
        out.println("<?xml version=\"1.0\"?>");
1415
        out.println("<error>");
1416
        out.println(npe.getMessage());
1417
        out.println("</error>");
1418
      }
1419
    } catch (Exception e) {
1420
      response.setContentType("text/xml");
1421
      out.println("<?xml version=\"1.0\"?>");
1422
      out.println("<error>");
1423
      out.println(e.getMessage());
1424
      if (e instanceof SAXException) {
1425
        Exception e2 = ((SAXException)e).getException();
1426
        out.println("<error>");
1427
        try
1428
        {
1429
          out.println(e2.getMessage());
1430
        }
1431
        catch(NullPointerException npe)
1432
        {
1433
          out.println(e.getMessage());
1434
        }
1435
        out.println("</error>");
1436
      }
1437
      //e.printStackTrace(out);
1438
      out.println("</error>");
1439
    }
1440
  }
1441

    
1442
  /**
1443
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1444
   * in order to decide whether to use validation parser
1445
   */
1446
  private static boolean validateXML(String xmltext) throws IOException {
1447

    
1448
    StringReader xmlreader = new StringReader(xmltext);
1449
    StringBuffer cbuff = new StringBuffer();
1450
    java.util.Stack st = new java.util.Stack();
1451
    boolean validate = false;
1452
    int c;
1453
    int inx;
1454

    
1455
    // read from the stream until find the keywords
1456
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1457
      cbuff.append((char)c);
1458

    
1459
      // "<!DOCTYPE" keyword is found; put it in the stack
1460
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1461
        cbuff = new StringBuffer();
1462
        st.push("<!DOCTYPE");
1463
      }
1464
      // "PUBLIC" keyword is found; put it in the stack
1465
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1466
        cbuff = new StringBuffer();
1467
        st.push("PUBLIC");
1468
      }
1469
      // "SYSTEM" keyword is found; put it in the stack
1470
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1471
        cbuff = new StringBuffer();
1472
        st.push("SYSTEM");
1473
      }
1474
      // ">" character is found; put it in the stack
1475
      // ">" is found twice: fisrt from <?xml ...?>
1476
      // and second from <!DOCTYPE ... >
1477
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1478
        cbuff = new StringBuffer();
1479
        st.push(">");
1480
      }
1481
    }
1482

    
1483
    // close the stream
1484
    xmlreader.close();
1485

    
1486
    // check the stack whether it contains the keywords:
1487
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1488
    if ( st.size() == 4 ) {
1489
      if ( ((String)st.pop()).equals(">") &&
1490
           ( ((String)st.peek()).equals("PUBLIC") |
1491
             ((String)st.pop()).equals("SYSTEM") ) &&
1492
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1493
        validate = true;
1494
      }
1495
    }
1496

    
1497
System.out.println("Validation is " + validate);
1498
    return validate;
1499
  }
1500
  // END OF INSERT/UPDATE SECTION
1501

    
1502
  // DELETE SECTION
1503
  /**
1504
   * Handle the database delete request and delete an XML document
1505
   * from the database connection
1506
   */
1507
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1508
               HttpServletResponse response, String user, String[] groups) {
1509

    
1510
    String[] docid = (String[])params.get("docid");
1511

    
1512
    // delete the document from the database
1513
    try {
1514

    
1515
                                      // NOTE -- NEED TO TEST HERE
1516
                                      // FOR EXISTENCE OF DOCID PARAM
1517
                                      // BEFORE ACCESSING ARRAY
1518
      try {
1519
        DocumentImpl.delete(docid[0], user, groups);
1520
        response.setContentType("text/xml");
1521
        out.println("<?xml version=\"1.0\"?>");
1522
        out.println("<success>");
1523
        out.println("Document deleted.");
1524
        out.println("</success>");
1525
      } catch (AccessionNumberException ane) {
1526
        response.setContentType("text/xml");
1527
        out.println("<?xml version=\"1.0\"?>");
1528
        out.println("<error>");
1529
        out.println("Error deleting document!!!");
1530
        out.println(ane.getMessage());
1531
        out.println("</error>");
1532
      }
1533
    } catch (Exception e) {
1534
      response.setContentType("text/xml");
1535
      out.println("<?xml version=\"1.0\"?>");
1536
      out.println("<error>");
1537
      out.println(e.getMessage());
1538
      out.println("</error>");
1539
    }
1540
  }
1541
  // END OF DELETE SECTION
1542

    
1543
  // VALIDATE SECTION
1544
  /**
1545
   * Handle the validation request and return the results to the requestor
1546
   */
1547
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1548

    
1549
    // Get the document indicated
1550
    String valtext = null;
1551
    DBConnection dbConn = null;
1552
    int serialNumber = -1;
1553

    
1554
    try {
1555
      valtext = ((String[])params.get("valtext"))[0];
1556
    } catch (Exception nullpe) {
1557

    
1558

    
1559
      String docid = null;
1560
      try {
1561
        // Find the document id number
1562
        docid = ((String[])params.get("docid"))[0];
1563

    
1564

    
1565
        // Get the document indicated from the db
1566
        DocumentImpl xmldoc = new DocumentImpl(docid);
1567
        valtext = xmldoc.toString();
1568

    
1569
      } catch (NullPointerException npe) {
1570

    
1571
        out.println("<error>Error getting document ID: " + docid + "</error>");
1572
        //if ( conn != null ) { util.returnConnection(conn); }
1573
        return;
1574
      } catch (Exception e) {
1575

    
1576
        out.println(e.getMessage());
1577
      }
1578
    }
1579

    
1580

    
1581
    try {
1582
      // get a connection from the pool
1583
      dbConn=DBConnectionPool.
1584
                  getDBConnection("MetaCatServlet.handleValidateAction");
1585
      serialNumber=dbConn.getCheckOutSerialNumber();
1586
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1587
      boolean valid = valobj.validateString(valtext);
1588

    
1589
      // set content type and other response header fields first
1590

    
1591
      out.println(valobj.returnErrors());
1592

    
1593
    } catch (NullPointerException npe2) {
1594
      // set content type and other response header fields first
1595

    
1596
      out.println("<error>Error validating document.</error>");
1597
    } catch (Exception e) {
1598

    
1599
      out.println(e.getMessage());
1600
    } finally {
1601
      // Return db connection
1602
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1603
    }
1604
  }
1605
  // END OF VALIDATE SECTION
1606

    
1607
  // OTHER ACTION HANDLERS
1608

    
1609
  /**
1610
   * Handle "getrevsionanddoctype" action
1611
   * Given a docid, return it's current revision and doctype from data base
1612
   * The output is String look like "rev;doctype"
1613
   */
1614
  private void handleGetRevisionAndDocTypeAction(PrintWriter out,
1615
                                                              Hashtable params)
1616
  {
1617
    // To store doc parameter
1618
    String [] docs = new String[10];
1619
    // Store a single doc id
1620
    String givenDocId = null;
1621
    // Get docid from parameters
1622
    if (params.containsKey("docid"))
1623
    {
1624
      docs = (String[])params.get("docid");
1625
    }
1626
    // Get first docid form string array
1627
    givenDocId = docs[0];
1628

    
1629
    try
1630
    {
1631
      // Make sure there is a docid
1632
      if (givenDocId == null || givenDocId.equals(""))
1633
      {
1634
        throw new Exception("User didn't specify docid!");
1635
      }//if
1636

    
1637
      // Create a DBUtil object
1638
      DBUtil dbutil = new DBUtil();
1639
      // Get a rev and doctype
1640
      String revAndDocType =
1641
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1642
      out.println(revAndDocType);
1643

    
1644
    }//try
1645
    catch (Exception e)
1646
    {
1647
      // Handle exception
1648
      out.println("<?xml version=\"1.0\"?>");
1649
      out.println("<error>");
1650
      out.println(e.getMessage());
1651
      out.println("</error>");
1652
    }//catch
1653

    
1654
  }//handleGetRevisionAndDocTypeAction
1655

    
1656
  /**
1657
   * Handle "getaccesscontrol" action.
1658
   * Read Access Control List from db connection in XML format
1659
   */
1660
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
1661
                                       HttpServletResponse response,
1662
                                       String username, String[] groupnames) {
1663

    
1664
    DBConnection dbConn = null;
1665
    int serialNumber = -1;
1666
    String docid = ((String[])params.get("docid"))[0];
1667

    
1668
    try {
1669

    
1670
        // get connection from the pool
1671
        dbConn=DBConnectionPool.
1672
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1673
        serialNumber=dbConn.getCheckOutSerialNumber();
1674
        AccessControlList aclobj = new AccessControlList(dbConn);
1675
        String acltext = aclobj.getACL(docid, username, groupnames);
1676
        out.println(acltext);
1677

    
1678
    } catch (Exception e) {
1679
      out.println("<?xml version=\"1.0\"?>");
1680
      out.println("<error>");
1681
      out.println(e.getMessage());
1682
      out.println("</error>");
1683
    } finally {
1684
      // Retrun db connection to pool
1685
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1686
    }
1687

    
1688
  }
1689

    
1690
  /**
1691
   * Handle the "getprincipals" action.
1692
   * Read all principals from authentication scheme in XML format
1693
   */
1694
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1695
                                         String password) {
1696

    
1697

    
1698
    try {
1699

    
1700

    
1701
        AuthSession auth = new AuthSession();
1702
        String principals = auth.getPrincipals(user, password);
1703
        out.println(principals);
1704

    
1705
    } catch (Exception e) {
1706
      out.println("<?xml version=\"1.0\"?>");
1707
      out.println("<error>");
1708
      out.println(e.getMessage());
1709
      out.println("</error>");
1710
    }
1711

    
1712
  }
1713

    
1714
  /**
1715
   * Handle "getdoctypes" action.
1716
   * Read all doctypes from db connection in XML format
1717
   */
1718
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1719
                                       HttpServletResponse response) {
1720

    
1721

    
1722
    try {
1723

    
1724

    
1725
        DBUtil dbutil = new DBUtil();
1726
        String doctypes = dbutil.readDoctypes();
1727
        out.println(doctypes);
1728

    
1729
    } catch (Exception e) {
1730
      out.println("<?xml version=\"1.0\"?>");
1731
      out.println("<error>");
1732
      out.println(e.getMessage());
1733
      out.println("</error>");
1734
    }
1735

    
1736
  }
1737

    
1738
  /**
1739
   * Handle the "getdtdschema" action.
1740
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1741
   */
1742
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1743
                                        HttpServletResponse response) {
1744

    
1745

    
1746
    String doctype = null;
1747
    String[] doctypeArr = (String[])params.get("doctype");
1748

    
1749
    // get only the first doctype specified in the list of doctypes
1750
    // it could be done for all doctypes in that list
1751
    if (doctypeArr != null) {
1752
        doctype = ((String[])params.get("doctype"))[0];
1753
    }
1754

    
1755
    try {
1756

    
1757

    
1758
        DBUtil dbutil = new DBUtil();
1759
        String dtdschema = dbutil.readDTDSchema(doctype);
1760
        out.println(dtdschema);
1761

    
1762
    } catch (Exception e) {
1763
      out.println("<?xml version=\"1.0\"?>");
1764
      out.println("<error>");
1765
      out.println(e.getMessage());
1766
      out.println("</error>");
1767
    }
1768

    
1769
  }
1770

    
1771
  /**
1772
   * Handle the "getdataguide" action.
1773
   * Read Data Guide for a given doctype from db connection in XML format
1774
   */
1775
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
1776
                                        HttpServletResponse response) {
1777

    
1778

    
1779
    String doctype = null;
1780
    String[] doctypeArr = (String[])params.get("doctype");
1781

    
1782
    // get only the first doctype specified in the list of doctypes
1783
    // it could be done for all doctypes in that list
1784
    if (doctypeArr != null) {
1785
        doctype = ((String[])params.get("doctype"))[0];
1786
    }
1787

    
1788
    try {
1789

    
1790

    
1791
        DBUtil dbutil = new DBUtil();
1792
        String dataguide = dbutil.readDataGuide(doctype);
1793
        out.println(dataguide);
1794

    
1795
    } catch (Exception e) {
1796
      out.println("<?xml version=\"1.0\"?>");
1797
      out.println("<error>");
1798
      out.println(e.getMessage());
1799
      out.println("</error>");
1800
    }
1801

    
1802
  }
1803

    
1804
  /**
1805
   * Handle the "getlastdocid" action.
1806
   * Get the latest docid with rev number from db connection in XML format
1807
   */
1808
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
1809
                                        HttpServletResponse response) {
1810

    
1811

    
1812
    String scope = ((String[])params.get("scope"))[0];
1813
    if (scope == null) {
1814
        scope = ((String[])params.get("username"))[0];
1815
    }
1816

    
1817
    try {
1818

    
1819

    
1820
        DBUtil dbutil = new DBUtil();
1821
        String lastDocid = dbutil.getMaxDocid(scope);
1822
        out.println("<?xml version=\"1.0\"?>");
1823
        out.println("<lastDocid>");
1824
        out.println("  <scope>" + scope + "</scope>");
1825
        out.println("  <docid>" + lastDocid + "</docid>");
1826
        out.println("</lastDocid>");
1827

    
1828
    } catch (Exception e) {
1829
      out.println("<?xml version=\"1.0\"?>");
1830
      out.println("<error>");
1831
      out.println(e.getMessage());
1832
      out.println("</error>");
1833
    }
1834

    
1835
  }
1836

    
1837
  /**
1838
   * Handle documents passed to metacat that are encoded using the
1839
   * "multipart/form-data" mime type.  This is typically used for uploading
1840
   * data files which may be binary and large.
1841
   */
1842
  private void handleMultipartForm(HttpServletRequest request,
1843
                                   HttpServletResponse response)
1844
  {
1845
    PrintWriter out = null;
1846
    String action = null;
1847

    
1848
    // Parse the multipart form, and save the parameters in a Hashtable and
1849
    // save the FileParts in a hashtable
1850

    
1851
    Hashtable params = new Hashtable();
1852
    Hashtable fileList = new Hashtable();
1853

    
1854
    try {
1855
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1856
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); //200MB
1857
      Part part;
1858
      while ((part = mp.readNextPart()) != null) {
1859
        String name = part.getName();
1860

    
1861
        if (part.isParam()) {
1862
          // it's a parameter part
1863
          ParamPart paramPart = (ParamPart) part;
1864
          String value = paramPart.getStringValue();
1865
          params.put(name, value);
1866
          if (name.equals("action")) {
1867
            action = value;
1868
          }
1869
        } else if (part.isFile()) {
1870
          // it's a file part
1871
          FilePart filePart = (FilePart) part;
1872
          fileList.put(name, filePart);
1873

    
1874
          // Stop once the first file part is found, otherwise going onto the
1875
          // next part prevents access to the file contents.  So...for upload
1876
          // to work, the datafile must be the last part
1877
          break;
1878
        }
1879
      }
1880
    } catch (IOException ioe) {
1881
      try {
1882
        out = response.getWriter();
1883
      } catch (IOException ioe2) {
1884
        System.err.println("Fatal Error: couldn't get response output stream.");
1885
      }
1886
      out.println("<?xml version=\"1.0\"?>");
1887
      out.println("<error>");
1888
      out.println("Error: problem reading multipart data.");
1889
      out.println("</error>");
1890
    }
1891

    
1892
    // Get the session information
1893
    String username = null;
1894
    String password = null;
1895
    String[] groupnames = null;
1896
    String sess_id = null;
1897

    
1898
    // be aware of session expiration on every request
1899
    HttpSession sess = request.getSession(true);
1900
    if (sess.isNew()) {
1901
      // session expired or has not been stored b/w user requests
1902
      username = "public";
1903
      sess.setAttribute("username", username);
1904
    } else {
1905
      username = (String)sess.getAttribute("username");
1906
      password = (String)sess.getAttribute("password");
1907
      groupnames = (String[])sess.getAttribute("groupnames");
1908
      try {
1909
        sess_id = (String)sess.getId();
1910
      } catch(IllegalStateException ise) {
1911
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1912
                           "happen: the session should be valid: " +
1913
                           ise.getMessage());
1914
      }
1915
    }
1916

    
1917
    // Get the out stream
1918
    try {
1919
          out = response.getWriter();
1920
        } catch (IOException ioe2) {
1921
          util.debugMessage("Fatal Error: couldn't get response "+
1922
                                                              "output stream.");
1923
        }
1924

    
1925
    if ( action.equals("upload")) {
1926
      if (username != null &&  !username.equals("public")) {
1927
        handleUploadAction(request, out, params, fileList,
1928
                           username, groupnames);
1929
      } else {
1930

    
1931
        out.println("<?xml version=\"1.0\"?>");
1932
        out.println("<error>");
1933
        out.println("Permission denied for " + action);
1934
        out.println("</error>");
1935
      }
1936
    } else {
1937
      /*try {
1938
        out = response.getWriter();
1939
      } catch (IOException ioe2) {
1940
        System.err.println("Fatal Error: couldn't get response output stream.");
1941
      }*/
1942
      out.println("<?xml version=\"1.0\"?>");
1943
      out.println("<error>");
1944
      out.println("Error: action not registered.  Please report this error.");
1945
      out.println("</error>");
1946
    }
1947
    out.close();
1948
  }
1949

    
1950
  /**
1951
   * Handle the upload action by saving the attached file to disk and
1952
   * registering it in the Metacat db
1953
   */
1954
  private void handleUploadAction(HttpServletRequest request,
1955
                                  PrintWriter out,
1956
                                  Hashtable params, Hashtable fileList,
1957
                                  String username, String[] groupnames)
1958
  {
1959
    //PrintWriter out = null;
1960
    //Connection conn = null;
1961
    String action = null;
1962
    String docid = null;
1963

    
1964
    /*response.setContentType("text/xml");
1965
    try
1966
    {
1967
      out = response.getWriter();
1968
    }
1969
    catch (IOException ioe2)
1970
    {
1971
      System.err.println("Fatal Error: couldn't get response output stream.");
1972
    }*/
1973

    
1974
    if (params.containsKey("docid"))
1975
    {
1976
      docid = (String)params.get("docid");
1977
    }
1978

    
1979
    // Make sure we have a docid and datafile
1980
    if (docid != null && fileList.containsKey("datafile")) {
1981

    
1982
      // Get a reference to the file part of the form
1983
      FilePart filePart = (FilePart)fileList.get("datafile");
1984
      String fileName = filePart.getFileName();
1985
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
1986

    
1987
      // Check if the right file existed in the uploaded data
1988
      if (fileName != null) {
1989

    
1990
        try
1991
        {
1992
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
1993
           //If document get lock data file grant
1994
           if (DocumentImpl.getDataFileLockGrant(docid))
1995
           {
1996
              // register the file in the database (which generates an exception
1997
              //if the docid is not acceptable or other untoward things happen
1998
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
1999

    
2000
              // Save the data file to disk using "docid" as the name
2001
              dataDirectory.mkdirs();
2002
              File newFile = new File(dataDirectory, docid);
2003
              long size = filePart.writeTo(newFile);
2004

    
2005
              // Force replication this data file
2006
              // To data file, "insert" and update is same
2007
              // The fourth parameter is null. Because it is notification server
2008
              // and this method is in MetaCatServerlet. It is original command,
2009
              // not get force replication info from another metacat
2010
              ForceReplicationHandler frh = new ForceReplicationHandler
2011
                                                (docid, "insert", false, null);
2012

    
2013
              // set content type and other response header fields first
2014
              out.println("<?xml version=\"1.0\"?>");
2015
              out.println("<success>");
2016
              out.println("<docid>" + docid + "</docid>");
2017
              out.println("<size>" + size + "</size>");
2018
              out.println("</success>");
2019
          }//if
2020

    
2021
        } //try
2022
        catch (Exception e)
2023
        {
2024
          out.println("<?xml version=\"1.0\"?>");
2025
          out.println("<error>");
2026
          out.println(e.getMessage());
2027
          out.println("</error>");
2028
        }
2029

    
2030
      }
2031
      else
2032
      {
2033
        // the field did not contain a file
2034
        out.println("<?xml version=\"1.0\"?>");
2035
        out.println("<error>");
2036
        out.println("The uploaded data did not contain a valid file.");
2037
        out.println("</error>");
2038
      }
2039
    }
2040
    else
2041
    {
2042
      // Error bcse docid missing or file missing
2043
      out.println("<?xml version=\"1.0\"?>");
2044
      out.println("<error>");
2045
      out.println("The uploaded data did not contain a valid docid " +
2046
                  "or valid file.");
2047
      out.println("</error>");
2048
    }
2049
  }
2050
}
(36-36/50)